이 글은 생활코딩 - WebPack 수업을 듣고 정리한 글입니다.
여러개의 리소스 파일(js, css, jpg)을 하나의 js 파일로 묶어주는 도구
여러개의 파일을 하나로 묶어주기 때문에 네트워크 접속의 부담을 줄 일 수 있다. 더 빠른 서비스를 제공할 수 있다.
여러개의 서로 다른 패키지들이 서로 같은 이름의 전역 변수를 사용하면 프로그램은 오동작하게 된다. 이런 문제를 극복하기 위해서 등장한 것이 모듈이다. 웹팩은 아직 최신 기술이라서 적용하기가 애매한 기술인 모듈을 오래된 브라우저에서도 사용할 수 있게 도와준다.
웹팩에는 매우 많은 플러그인들이 존재한다.. 이런 플러그인을 이용하면 웹개발시에 필요한 다양한 작업을 자동화 할 수 있다.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TEST</title>
<!-- <script src="./source/hello.js"></script>
<script src="./source/world.js"></script> -->
</head>
<body>
<h1>Hello, Webpack</h1>
<div id="root"></div>
<script type="module">
import hello_word from "./source/hello.js";
import world_word from "./source/world.js";
document.querySelector('#root').innerHTML = hello_word + ' ' + world_word;
</script>
</body>
</html>
source/hello.js
var word = 'Hello';
export default word;
source/world.js
var word = "World";
export default word;
모듈을 사용하기 전에는 단순히
script
태그를 이용하여 js코드 안에 있는 것들을 가져왔지만 그렇게 되면word
라는 중복되는 것이 발생하여 원치않은 결과를 가져올 수 있다.
따라서 모듈을 사용하여script
태그가 아닌import
로 원하는 결과 값을 변수로 가져오고, 내보내는 부분에서도export default
를 써주어 내보낼 값을 지정한다.
package.json 생성
npm init -y
webpack 설치
npm install -D webpack webpack-cli
입구(entry)에 해당되는 파일: index.js
생성
import hello_word from "./hello.js";
import world_word from "./world.js";
document.querySelector('#root').innerHTML = hello_word + ' ' + world_word;
번들링 하기
npx webpack --entry ./source/index.js --output-path ./public
번들링된 main.js
(() => {
"use strict";
document.querySelector("#root").innerHTML = "Hello World"
})();
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TEST</title>
<!-- <script src="./source/hello.js"></script>
<script src="./source/world.js"></script> -->
</head>
<body>
<h1>Hello, Webpack</h1>
<div id="root"></div>
<script src="./public/main.js"></script>
</body>
</html>
오래된 브라우저도 번들링 된 js 파일을 사용하여 지원할 수 있다는 점에서 장점이 있음
웹팩에게 체계적이고 재사용하기 좋게 시키기 위한 방법 --> config 파일 생성
webpack.config.js
const path = require('path');
module.exports = {
entry: "./source/index.js",
output: {
path: path.resolve(__dirname, "public"),
filename: 'index_bundle.js'
}
}
entry: 입구를 설정할 파일 경로
output-path: 이 파일이 실행될 경로 path 모듈을 require해서 갖고와서 resolve를 사용하여 현재 디렉토리의 "public"폴더에 결과를 저장
filename: output 파일 이름
실행 명령어
npx webpack
운영 모드의 기본값: 아무것도 설정 x, production모드, development모드
개발모드 webpack.config.js
const path = require('path');
module.exports = {
mode: "development",
entry: "./source/index.js",
output: {
path: path.resolve(__dirname, "public"),
filename: 'index_bundle.js'
}
}
index_bundler.js
/*
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./source/hello.js":
/*!*************************!*\
!*** ./source/hello.js ***!
\*************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nvar word = 'Hello';\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (word);\n\n//# sourceURL=webpack://test/./source/hello.js?");
/***/ }),
/***/ "./source/index.js":
/*!*************************!*\
!*** ./source/index.js ***!
\*************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _hello_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./hello.js */ \"./source/hello.js\");\n/* harmony import */ var _world_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./world.js */ \"./source/world.js\");\n\n\ndocument.querySelector('#root').innerHTML = _hello_js__WEBPACK_IMPORTED_MODULE_0__.default + ' ' + _world_js__WEBPACK_IMPORTED_MODULE_1__.default;\n\n//# sourceURL=webpack://test/./source/index.js?");
/***/ }),
/***/ "./source/world.js":
/*!*************************!*\
!*** ./source/world.js ***!
\*************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nvar word = \"World\";\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (word);\n\n//# sourceURL=webpack://test/./source/world.js?");
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
/******/ ![](https://velog.velcdn.com/images%2Fhustle-dev%2Fpost%2F669f9118-72da-4d0c-a8a7-577b1e3a802a%2Fwebpack.png)
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module can't be inlined because the eval devtool is used.
/******/ var __webpack_exports__ = __webpack_require__("./source/index.js");
/******/
/******/ })()
;
production모드를 실행시키고 싶으면 mode안의 내용을 production으로 바꾸던가 아니면 webpack.config.prod.js라는 파일을 생성해서 그곳의 모드를 production으로 바꾼뒤, npx webpack config webpack.config.prod.js로 실행!
style.css
body {
background-color: powderblue;
color: tomato;
}
index.js
import hello_word from "./hello.js";
import world_word from "./world.js";
import css from './style.css';
document.querySelector('#root').innerHTML = hello_word + ' ' + world_word;
console.log('css', css);
webpack.config.js
const path = require('path');
module.exports = {
mode: "development",
entry: "./source/index.js",
output: {
path: path.resolve(__dirname, "public"),
filename: 'index_bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
],
},
],
},
};
뒤 쪽에 있는 로더가 먼저 실행됨(css-loader)먼저 그 후에 style-loader를 실행!
로더가 없었으면 css파일을 index.html파일에서 불러와 실행시켜야 하지만 이렇게 loader를 설정해주면 index_bundler.js파일 하나로 css또한 설정할 수 있음.
완성된 파일들을 여러개 지정해서 출력하는 법
webpack.config.js
const path = require('path');
module.exports = {
mode: "development",
entry: {
index: "./source/index.js",
about: "./source/about.js",
},
output: {
path: path.resolve(__dirname, "public"),
filename: '[name]_bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
],
},
],
},
};
entry부분에 입구로할 파일들을 지정해두고, output부분에 파일 이름을 [name]으로 지정을 해두어서 완성된 파일들이 각각 나오도록 지정함.
loader 보다 복잡한 작업을 할 수 있는 확장 기능인 플러그인
이 플러그인은 webpack번들을 제공하는 HTML파일 생성을 단순화 한다.
설치방법
npm install --save-dev html-webpack-plugin
사용법
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
entry: 'index.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'index_bundle.js',
},
plugins: [new HtmlWebpackPlugin()],
};
HtmlWebpackPlugin을 가져와서 module.exports 부분에 plugins에 위와 같이 사용할 수 있음.
예제와 같이 2가지 파일을 모두 생성하려면
new HtmlWebpackPlugin({
template: './source/index.html',
filename: './index.html',
chunks: ['index']
}),
new HtmlWebpackPlugin({
template: './source/about.html',
filename: './about.html',
chunks: ['about']
})
다음과 같이 2개 모두 생성해주면 된다.
npx webpack --watch
위 명령어는 작업중 파일이 변경되었을 때, 변경된 부분을 감지하고 자동으로 컴파일을 다시 해줌.
lodash 패키지 포함시키기
npm install lodash
사용시
import _ from "lodash";
변경부분
hello_word + ' ' + world_word;
// lodash 사용
_.join([hello_word, world_Word], ' ');
결과는 똑같음