what
Webpack은 모듈 번들러 도구로 JavaScript 파일들을 브라우저에서 사용하기 위해 묶는 것이지만
모든 리소스 또는 에셋(Assets)을 변형, 번들링 또는 패키징 할 수 있습니다.
why bundling?
Webpack과 같은 도구를 사용하여 번들링 하는 이유는 웹이 오랜 시간 사용해왔던 HTTP/1.1의 비효율적인 요청 때문입니다.
2015년 2월 표준 승인된 HTTP/2 사용이 가능한 브라우저에서는
이러한 문제가 해결됩니다. HTTP/1.1과 달리 리소스를 한 번에 하나씩이 아니라, 동시 다발적으로 요청/응답할 수 있습니다. 다시 말해 리소스 요청 횟수가 많아지더라도 속도가 크게 느려지지 않습니다.
HTTP/1.1은 서버에 리소스를 하나씩 요청한 후, 응답을 받고 나서야
다른 리소스를 또 하나 요청합니다. 예를 들어 index.html 요청/응답이 끝난 후에야 style.css 요청/응답. 다음은 script.js 요청/응답 ...... 즉, 리소스 개수가 많아질 수록 사이트/애플리케이션 속도는 느려집니다.
하지만 IE에서는 HTTP/2를 지원하지 않으므로 IE를 사용하지 않는
환경이 아니라면 서버에 요청하는 리소스 횟수를 줄여야 합니다.
참고로 IE11은 HTTP/2를 지원하지만... Windows10에 한정됩니다.
bundling === SpeedUp!
Webpack을 사용하면 리소스 개수를 현저하게 줄일 수 있어 서버에 요청 횟수를 줄일 수 있어 속도를 향상시킬 수 있습니다.
TL; DR
ES 모듈 , CommonJS 혹은 AMD 모듈을 번들로 제공합니다.
런타임 시, 비동기(Async) 적으로 불러들이는 단일 번들(Bundle, 묶음) 또는
여러 청크(Chunk, 덩어리)를 생성하여 초기 로드 시간을 줄여줍니다.
컴파일 시, 종속성(Dependancy) 문제를 해결하여 런타임 크기 줄입니다.
다양한 로더 (Loader)를 지원하며, 컴파일하는 동안 파일을 전처리 할 수 있습니다.
(예: Babel/TypeScript, Sass/LESS, Pug 등)
모듈 (Module, 독립성이 보장된 재사용 가능한 코드 묶음) 단위 플러그인 시스템을 지원합니다.
HMR (Hot Module Replacement) 지원하여 코드 수정 시 자동 번들링 및 페이지 업데이트를 수행할 수 있습니다.
CSS, Images, Fonts 리소스 또한 모듈 단위로 묶어 배포 가능합니다.
Webpack CLI
# 프로젝트 디렉토리 생성 및 생성된 디렉토리로 이동
# mkdir = make directory
# cd = change directory
$ mkdir <project_directory> && cd <project_directory>
# 프로젝트 초기화
# package.json 파일 생성
$ npm init -y
Start Project
Webpack 실습을 위한 프로젝트 디렉토리를 생성하고, 생성된 디렉토리로 이동해 봅시다.
프로젝트를 초기화하여 package.json 파일을 생성한 후, webpack 개발 모듈을 로컬 설치합니다.
# 지역 설치
# 대부분 프로젝트에서 로컬로 설치하는 것이 좋습니다.
# 변경 내용을 도입 할 때 프로젝트를 개별적으로 쉽게 업그레이드 할 수 있기 때문이죠.
# webpack의 로컬 설치를 실행하기 위해서는 bin버전에 액세스해야 합니다.
# node_modules/.bin/webpack
$ npm install --save-dev webpack # npm i -D webpack
$ npm install --save-dev webpack@<version> # npm i -D webpack@3.6.0
# 전역 설치
# 이 방법은 권장되지 않습니다.
# 전역으로 설치하면 특정 버전만 사용 가능하기 때문입니다.
$ npm install --global webpack # npm i -g webpack
# 설치 가능한 버전 확인
$ npm show webpack@3.* version
Install Webpack
Webpack을 설치하기 위해서는 사전에 Node.js가 필요합니다.
설치 방법은 전역 또는 지역 설치가 가능합니다. 아래 코드를 참고하여 설치해 봅니다.
<project_directory>
|- package.json
+ |- index.html
+ |- /src
+ |- main.js
main.js
간단한 DOM 스크립트를 처리하는 코드를 src/main.js 에 작성해 봅니다.
해당 코드는 Lodash 라이브러리에 의존합니다.
// src/main.js
((global = window, document = window.document, _ = window._) => {
const heading_message = ['Hello', 'Webpack', ':)'];
function component() {
let el = document.createElement('h1');
// Lodash 라이브러리 join() 메서드 사용
el.innerHTML = _.join(heading_message, ' ');
return el;
}
document.body.appendChild( component() );
}());
<project_directory>
|- package.json
+ |- index.html
+ |- /src
+ |- main.js
index.html
웹 브라우저에서 해석되어 처리될 index.html 마크업을 작성합니다.
Lodash 라이브러리(CDN)를 head 요소 내부에서 호출하고, src/main.js 파일을 body 요소 끝 부분에서 호출해 봅니다.
<!DOCTYPE html>
<html lang="ko-KR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Webpack 프로젝트 설정</title>
<script src="https://unpkg.com/lodash"></script>
</head>
<body>
<script src="./src/main.js"></script>
</body>
</html>
Problem
지금까지 사용한 방법은 일반적인 프론트엔드 환경에서 JavaScript를 프로젝트에 사용한 예시입니다.
이와 같은 방법을 사용할 경우 문제가 발생할 수 있습니다.
✔︎ 스크립트가 외부 라이브러리에 의존한다는 점이 명시적이지 않습니다.
✔︎ 종속된 개발 모듈이 호출되지 않았거나 호출되는 순서가 잘못된 경우, 애플리케이션이 올바르게 작동하지 않습니다.
✔︎ 종속된 개발 모듈이 호출 되었지만 애플리케이션에서 사용 되지 않아도, 웹 브라우저는 불필요한 파일을 무조건 다운로드 하게 됩니다.
<project_directory>
|- package.json
+ |- /dist
+ |- index.html
- |- index.html
|- /src
|- main.js
Change Structure & Import Module
앞서 거론 했던 문제를 해결하기 위해 Webpack을 사용하여 프로젝트를 관리하는 방법을 학습해 봅시다.
index.html을 dist/ 디렉토리를 생성한 후 내부로 이동 시킵니다. 이어서 Lodash 개발 모듈을 로컬 설치한 후, src/main.js 파일을 수정합니다.
# Lodash 모듈을 설치합니다.
npm i -S lodash
import _ from 'lodash';
const heading_message = ['Hello', 'Webpack', ':)'];
function component() {
let el = document.createElement('h1');
el.innerHTML = _.join(heading_message, ' ');
return el;
}
document.body.appendChild( component() );
<project_directory>
|- package.json
+ |- /dist
+ |- index.html
- |- index.html
|- /src
|- main.js
Modify index.html
dist/index.html 에서 기존의 JavaScript 파일 호출 코드를 모두 제거한 후,
bundle.js 파일을 호출하는 코드를 추가합니다.
<!DOCTYPE html>
<html lang="ko-KR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Webpack 프로젝트 설정</title>
</head>
<body>
<!-- bundle.js 호출 코드로 변경합니다. -->
<script src="./bundle.js"></script>
</body>
</html>
# Webpack 모듈 명령을 사용하여 src/index.js 파일을 dist/bundle.js로 번들링 하여 출력합니다.
# webpack의 로컬 설치를 실행하기 위해서는 bin버전에 액세스해야 합니다.
# node_modules/.bin/webpack
# webpack <엔트리(입력)_파일> <아웃풋(출력)_파일>
$ ./node_modules/.bin/webpack src/main.js dist/bundle.js
# npx 개발 모듈 설치 시
# $ npm i -g npx
$ npx webpack src/main.js dist/bundle.js
Webpack CLI × Bundling
Webpack CLI 명령을 사용하여 src/index.js 파일을 dist/bundle.js 파일로 번들링하여 생성 출력해 봅니다.
webpack 3.6.0
Usage: https://webpack.js.org/api/cli/
Usage without config file: webpack <entry> [<entry>] <output>
Usage with config file: webpack
Config options:
--config Path to the config file
[문자열] [기본: webpack.config.js or webpackfile.js]
--config-name Name of the config to use [문자열]
--env Environment passed to the config, when it is a function
Basic options:
--context The root directory for resolving entry point and stats
[문자열] [기본: The current directory]
--entry The entry point [문자열]
--watch, -w Watch the filesystem for changes [여부]
--debug Switch loaders to debug mode [여부]
--devtool Enable devtool for better debugging experience (Example:
--devtool eval-cheap-module-source-map) [문자열]
-d shortcut for --debug --devtool eval-cheap-module-source-map
--output-pathinfo [여부]
-p shortcut for --optimize-minimize --define
process.env.NODE_ENV="production" [여부]
--progress Print compilation progress in percentage [여부]
Module options:
--module-bind Bind an extension to a loader [문자열]
--module-bind-post [문자열]
--module-bind-pre [문자열]
Output options:
--output-path The output path for compilation assets
[문자열] [기본: The current directory]
--output-filename The output filename of the bundle
[문자열] [기본: [name].js]
--output-chunk-filename The output filename for additional chunks
[문자열] [기본: filename with [id] instead of [name] or [id] prefixed]
--output-source-map-filename The output filename for the SourceMap [문자열]
--output-public-path The public path for the assets [문자열]
--output-jsonp-function The name of the jsonp function used for chunk
loading [문자열]
--output-pathinfo Include a comment with the request for every
dependency (require, import, etc.) [여부]
--output-library Expose the exports of the entry point as library
[문자열]
--output-library-target The type for exposing the exports of the entry
point as library [문자열]
Advanced options:
--records-input-path Path to the records file (reading) [문자열]
--records-output-path Path to the records file (writing) [문자열]
--records-path Path to the records file [문자열]
--define Define any free var in the bundle [문자열]
--target The targeted execution environment [문자열]
--cache Enable in memory caching
[여부] [기본: It's enabled by default when watching]
--watch-stdin, --stdin Exit the process when stdin is closed [여부]
--watch-aggregate-timeout Timeout for gathering changes while watching
--watch-poll The polling interval for watching (also enable
polling) [문자열]
--hot Enables Hot Module Replacement [여부]
--prefetch Prefetch this request (Example: --prefetch
./file.js) [문자열]
--provide Provide these modules as free vars in all modules
(Example: --provide jQuery=jquery) [문자열]
--labeled-modules Enables labeled modules [여부]
--plugin Load this plugin [문자열]
--bail Abort the compilation on first error
[여부] [기본: null]
--profile Profile the compilation and include information in
stats [여부] [기본: null]
Resolving options:
--resolve-alias Setup a module alias for resolving (Example:
jquery-plugin=jquery.plugin) [문자열]
--resolve-extensions Setup extensions that should be used to resolve
modules (Example: --resolve-extensions .es6,.js)[배열]
--resolve-loader-alias Setup a loader alias for resolving [문자열]
Optimizing options:
--optimize-max-chunks Try to keep the chunk count below a limit
--optimize-min-chunk-size Try to keep the chunk size above a limit
--optimize-minimize Minimize javascript and switches loaders to
minimizing [여부]
Stats options:
--color, --colors Enables/Disables colors on the console
[여부] [기본: (supports-color)]
--sort-modules-by Sorts the modules list by property in module
[문자열]
--sort-chunks-by Sorts the chunks list by property in chunk
[문자열]
--sort-assets-by Sorts the assets list by property in asset
[문자열]
--hide-modules Hides info about modules [여부]
--display-exclude Exclude modules in the output [문자열]
--display-modules Display even excluded modules in the output
[여부]
--display-max-modules Sets the maximum number of visible modules in
output [숫자]
--display-chunks Display chunks in the output [여부]
--display-entrypoints Display entry points in the output [여부]
--display-origins Display origins of chunks in the output [여부]
--display-cached Display also cached modules in the output
[여부]
--display-cached-assets Display also cached assets in the output[여부]
--display-reasons Display reasons about module inclusion in the
output [여부]
--display-depth Display distance from entry point for each
module [여부]
--display-used-exports Display information about used exports in
modules (Tree Shaking) [여부]
--display-provided-exports Display information about exports provided
from modules [여부]
--display-optimization-bailout Display information about why optimization
bailed out for modules [여부]
--display-error-details Display details about errors [여부]
--display Select display preset (verbose, detailed,
normal, minimal, errors-only, none) [문자열]
--verbose Show more details [여부]
옵션:
--help, -h 도움말을 보여줍니다 [여부]
--version, -v 버전 넘버를 보여줍니다 [여부]
--json, -j Prints the result as JSON. [여부]
Webpack CLI × Help
Webpack CLI 도움말을 확인해 봅니다.
$ webpack --help, -h
# webpack <엔트리(입력)_파일> <아웃풋(출력)_파일>
# webpack 명령어 옵션: -p, --optimize-minimize
$ npx webpack src/main.js dist/bundle.js -p
Minification
번들링 후, 코드를 압축하여 생성 출력하는 옵션 플래그(Option Flag)를 사용해 봅시다.
# webpack <엔트리(입력)_파일> <아웃풋(출력)_파일>
# webpack 명령어 옵션: -d, --debug --devtool sourcemap --output-pathinfo
$ npx webpack src/main.js dist/bundle.js -d
Sourcemap
번들링 한 파일의 코드를 내비게이션 할 수 있도록 소스맵 파일을 생성하는 옵션 플래그(Option Flag)를 사용해 봅시다.
# webpack <엔트리(입력)_파일> <아웃풋(출력)_파일>
# webpack 명령어 옵션: -w, --watch
$ npx webpack src/main.js dist/bundle.js -w
watch
src/main.js 파일을 저장할 때 마다, 이를 관찰하여 자동으로 Webpack 명령을 실행하는 옵션 플래그(Option Flag)를 사용해 봅시다.
{
"scripts": {
"bundle": "webpack src/main.js dist/bundle.js",
"map": "npm run bundle -- -d",
"watch": "npm run bundle -- -w",
"watch:map": "npm run bundle -- -wd",
"build": "npm run bundle -- -p"
}
}
NPM Script
지금까지 다뤄 본 Webpack CLI를 pakcage.json 파일에 scripts 로 등록해 봅시다.
Loaders
# Babel을 사용하기 위한 개발 모듈
# babel-core
# babel-loader
# babel-preset-env
$ npm i -D babel-core babel-loader babel-preset-env
Install Babel Loader
ECMASCript 2015(이하 ES6)를 지원하지 않는 클라이언트 환경에서 ES6를 사용하려면, Babel 트랜스파일러를 사용하여 변환해야 합니다.
Babel을 프로젝트에 사용하기 위해 필요한 개발 모듈을 로컬 설치해 봅시다.
{
"scripts": {
"bundle": "webpack src/main.js dist/bundle.js --module-bind 'js=babel-loader'",
"map": "npm run bundle -- -d",
"watch": "npm run bundle -- -w",
"watch:map": "npm run bundle -- -wd",
"build": "npm run bundle -- -p"
},
"babel": {
"presets": ["env", {
"targets": {
"browsers": ["last 2 versions", "safari >= 7", "ie >= 8"]
}
}]
}
}
Webpack + Babel Loader
package.json 파일 bundle 스크립트에 Webpack 옵션 --module-bind 를 사용하여 'js=babel-loader'를 설정합니다.
이어서 .babelrc 파일에 작성하는 코드와 동일한 코드를 "babel"에 추가합니다. (참고: https://goo.gl/RD15AU)
# CSS 번들링을 위한 개발 모듈
# style-loader
# css-loader
npm i -D style-loader css-loader
Install Style/CSS Loaders
웹팩을 사용해 CSS 번들링을 수행하고자 한다면 style-loader, css-loader를 설치/설정 사용합니다.
{
"scripts": {
"bundle": "webpack src/main.js dist/bundle.js
--module-bind 'css=style-loader!css-loader'
--module-bind 'js=babel-loader'
",
"map": "npm run bundle -- -d",
"watch": "npm run bundle -- -w",
"watch:map": "npm run bundle -- -wd",
"build": "npm run bundle -- -p"
},
}
Webpack + CSS Loader
package.json 파일 bundle 스크립트에 Webpack 옵션 --module-bind 를 사용하여 'css=style-loader!css-loader'를 설정합니다.
설정을 마친 후에는 src/main.js 파일에 import 구문을 사용하여 CSS 파일을 호출합니다. (번들링 수행)
// src/main.js
import './css/main.css';
Configuration
<project_directory>
|- package.json
+ |- webpack.config.js
|- /node-modules
|- /dist
|- /src
webpack.config.js
대부분의 프로젝트는 좀 더 복잡한 설정이 필요합니다 . 설정 파일이 필요한 이유죠.
이것은 터미널에 많은 명령을 입력해야하는 것보다 훨씬 효율 적이므로 CLI 옵션을 대체 할 설정 파일을 만들어 봅시다.
// ——————————————————————————————————————
// 의존성 개발 모듈 로드
// ——————————————————————————————————————
const path = require('path');
// ——————————————————————————————————————
// Webpack 환경설정
// ——————————————————————————————————————
module.exports = {
// 입력 설정
entry: './src/main.js',
// 출력 설정
output: {
path: path.resolve(__dirname, './dist'),
filename: 'bundle.js'
}
};
{
"scripts": {
"webpack": "webpack --config webpack.config.js"
},
}
Run Webpack using configuration
package.json 파일에 환경설정(Configuration) 파일을 사용하여 Webpack을 실행하는 스크립트 구문을 추가합니다.
참고: https://goo.gl/1gyx3C
# NPM 스크립트 명령 실행
$ npm run webpack
<project_directory>
|- package.json
|- webpack.config.js
|- /node-modules
|- /dist
|- /src
babel-loader + presets
ES6를 ES5로 변환하기 위한 babel-loader 설정을 webpack.config.js 파일에 추가해 봅니다.
이어서 실험적인 Babel 프리셋 Stage에 대해 알아본 후, 설치/설정 해봅시다.
module.exports = {
// 로더 설정
module: {
// 규칙 설정
rules: [
// Babel
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
// https://goo.gl/KHtTU1
cacheDirectory: true,
presets: ['env']
}
}
}
]
}
};
$ npm i -D babel-preset-stage-0
module.exports = {
// 로더 설정
module: {
// 규칙 설정
rules: [
// Babel
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
// https://goo.gl/KHtTU1
cacheDirectory: true,
presets: ['env', 'stage-0']
}
}
}
]
}
};
<project_directory>
|- package.json
|- webpack.config.js
|- /node-modules
|- /dist
|- /src
babel plugin
Babel 플러그인을 추가하고자 할 경우 options 항목에 plugins 배열을 추가한 후, 설정합니다.
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: ['env'],
plugins: [ require('babel-plugin-transform-object-rest-spread') ]
}
}
}
]
}
};
$ npm i -D babel-plugin-transform-object-rest-spread
<project_directory>
|- package.json
|- webpack.config.js
|- /node-modules
|- /dist
|- /src
css-loader
module.exports = {
// 로더 설정
module: {
// 규칙 설정
rules: [
// CSS
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};
CSS 번들링을 위한 css-loader 설정을 webpack.config.js 파일에 추가해 봅니다.
<project_directory>
|- package.json
|- webpack.config.js
|- /node-modules
|- /dist
|- /src
css-loader option
// CSS
{
test: /\.css$/,
// 로더 마다 개별 설정
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
sourceMap: true
}
}
]
}
로더 마다 개별 설정이 필요한 경우, use 설정 배열 내부에 로더 마다 객체를 통해 설정합니다.
아래 코드를 참고하여 설정을 작성해 봅니다.
URL Loader & File Loader
이미지 및 폰트 파일을 번들 과정에서 base64로 인코딩된 URL로 변경합니다. | 필요한 객체를 파일로 내보내고 공개 URL을 반환하도록 webpack에 지시합니다.
module.exports = {
module: {
rules: [
// 이미지 파일
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
name: [name].[hash].[ext], // 출력 이름
limit: 10000, // 단위 바이트(Byte)
fallback: 'file-loader' // 기본 값
}
},
]
}
]
}
};
$ npm i -D url-loader file-loader
module.exports = {
module: {
rules: [
// 폰트 파일
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
use: 'file-loader',
}
]
}
};
img Loader
이미지 파일을 압축합니다.
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
name: [name].[hash].[ext],
limit: 10000,
}
},
{
loader: 'img-loader',
options: { enabled: true }
}
]
}
]
}
};
$ npm i -D img-loader
resolve
// webpack.config.js
module.exports = {
// 리졸브(결정) 설정
// https://goo.gl/NnR9ME
resolve: {
// 모듈을 해석 할 때 검색해야 할 디렉토리 설정
// 배열 값의 인덱스가 작을 수록 우선권이 높음
// 기본 값: ['node_modules']
modules: [path.reslove(__dirname, './src'), 'node_modules'],
// 생략 가능한 확장자 설정
// 기본 값: ['.js', '.json']
extensions: ['.js', '.json', '.es6', '.ts', '.css'],
// 모듈을 쉽게 불러오기 위한 별칭 설정
alias: {
'@': path.resolve(__dirname, 'src/js/'),
'@css': path.resolve(__dirname, 'src/css/'),
}
}
}
이 옵션은 모듈이 어떻게 해석되는지를 변경합니다.
Webpack은 적절한 기본값을 제공하지만, 기본 값을 사용자 설정에 따라 변경할 수 있습니다.
<project_directory>
|- package.json
|- webpack.config.js
|- /node-modules
|- /dist
|- /src
Development Setting
module.exports = {
// 소스맵 설정
// https://webpack.js.org/configuration/devtool/
devtool: 'cheap-module-eval-source-map',
// 관찰 모드
// https://webpack.js.org/configuration/watch/
watch: true
};
변경된 파일이 저장될 때 마다 파일을 관찰하여 webpack 명령을 재 실행하기 위한 옵션과,
다수의 코드를 번들링하되 효율적으로 관리하기 위한 소스맵 설정을 추가합니다.
{
"scripts": {
"start": "npm run webpack",
"webpack": "webpack --config webpack.config.js",
"webpack:watch": "npm run webpack -- -w"
},
}
NPM Scripts
package.json 파일에 환경설정(Configuration) 파일을 사용하여 Webpack을 실행하는 스크립트 구문을 추가합니다.
webpack:watch 스크립트는 watch 옵션을 외부에서 명령에 따라 실행할 수 있도록 설정할 수 있습니다.
Plugins
Module Concatenation Plugin
과거에는 번들링 할 때 webpack의 트레이드 오프 중 하나는 번들의 각 모듈이 개별 함수 클로저로 래핑 된다는 것이었습니다.
하지만 개별 래퍼 함수를 사용하면 브라우저에서 실행되는 속도가 느려집니다. 이에 반해 Rollup과 같은 도구는 모든 모듈의 범위를
하나의 개별 함수 클로저로 래핑하기에 브라우저에서 실행되는 속도가 빠릅니다. 이 플러그인은 webpack에서 동일한 연결 동작을 활성화합니다.
// ——————————————————————————————————————
// 모듈 로드
// ——————————————————————————————————————
// 웹팩
const webpack = require('webpack');
// 웹팩 플러그인
// 모듈 결합: https://goo.gl/Qd5zzw
const ModuleConcat = webpack.optimize.ModuleConcatenationPlugin;
// ——————————————————————————————————————
// Webpack 환경설정
// ——————————————————————————————————————
module.exports = {
// 플러그인 설정
plugins: [
new ModuleConcat()
]
};
Extract Text Webpack Plugin
번들된 텍스트(예 CSS 코드)를 별도의 파일로 추출합니다.
// 모듈 텍스트 출력: https://goo.gl/gWLzmL
const ExtractText = require('extract-text-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
// ExtractTextWebpackPlugin 플러그인 extract() 설정
use: ExtractText.extract({
fallback: 'style-loader',
use: [{ loader: 'css-loader', options: { sourceMap: true } }]
}),
}
]
},
plugins: [
// ExtractTextWebpackPlugin 플러그인 설정
new ExtractText('bundle.css'),
]
};
$ npm i -D extract-text-webpack-plugin
Uglifyjs Webpack Plugin
이 플러그인은 UglifyJS v3 (uglify-es) 을 사용 하여 자바 스크립트를 축소합니다.
// JavaScript 파일 압축: https://goo.gl/ZVM2Gj
const UglifyJS = require('uglifyjs-webpack-plugin');
module.exports = {
module: { ... },
plugins: [
// UglifyJS 웹팩 플러그인 설정
new UglifyJS(),
]
};
$ npm i -D uglifyjs-webpack-plugin
// JavaScript 파일 압축: https://goo.gl/ZVM2Gj
const UglifyJS = require('uglifyjs-webpack-plugin');
module.exports = {
module: { ... },
plugins: [
// 옵션 설정
new UglifyJS({
cache: true,
sourceMap: true,
uglifyOptions: {
ie8: false,
ecma: 8,
output: {
comments: false,
beautify: false,
},
warnings: false,
}
}),
]
};
Dev or Build Process
이 플러그인은 UglifyJS v3 (uglify-es) 을 사용 하여 자바 스크립트를 축소합니다.
{
"scripts": {
"dev": "webpack",
"build": "BUILD=true webpack",
"clear": "rm -rf dist"
}
}
// BUILD 환경설정 변수
let BUILD = process.env.BUILD || false;
// 웹팩 환경설정 객체
let config = { ... };
// 빌드 환경일 경우, 조건 처리
if (BUILD) {
config.plugins.push(new new UglifyJS({
// ...
}));
}
// 배포
module.exports = config;
Environment Plugin
환경설정 변수를 손쉽게 등록해주는 플러그인 입니다.
const webpack = require('webpack');
// 웹팩 플러그인
// 환경설정 변수 등록: https://goo.gl/hLcUNY
const Env = webpack.EnvironmentPlugin;
module.exports = {
// 플러그인 설정
plugins: [
new Env({
// 기본 값 설정
DEV: 'dev'
})
]
};
const webpack = require('webpack');
// 환경설정 변수 설정
let DEV = process.env.DEV ||'dev';
// `entry` 파일
// src/main.js
// 환경 변수 DEV 값이 true일 경우 처리
if ( process.env.DEV === 'dev' ) {
// ...
}
// 빌드 환경에서는 해당 변수가 설정 값으로 변경
// DEV=build npm run build
// ※ 브라우저 환경에서는 process.env에 접근 X
if ( 'build' === 'dev' ) {
// ...
}
Webpack Plugins
웹팩은 다양한 플러그인을 제공합니다. 용도에 따라 필요한 플러그인을 조합하여 프로젝트에 구성할 수 있습니다.
Webpack Dev Server
# webpack-dev-server 개발 모듈 로컬 설치
# npm install --save-dev webpack-dev-server
npm i -D webpack-dev-server
install
webpack 설정을 통해 파일 변경 저장 시, 번들링은 수행되어 편리하지만, 파일 변경이 발생할 때 마다 웹 브라우저를 매번 새로고침 해야 하기에 번거롭습니다.
webpack-dev-server는 간단한 웹 서버(Node.js + Express.js 를 기반으로 작동하는 개발용 서버)로 설치하면 파일 변경 시마다 매번 새로고침 하지 않아도 되어 편리 합니다.
<project_directory>
|- package.json
|- webpack.config.js
|- /node-modules
|- /dist
|- /src
devServer Setting
let dist = path.resolve(__dirname, './dist');
module.exports = {
// webpack-dev-server 설정
// https://webpack.js.org/configuration/dev-server/
devServer: {
contentBase: dist, // 콘텐츠 제공 서버 설정
port: 9000, // 요청을 수신 대기 할 포트 번호 설정
compress: true, // gzip 압축 사용 설정
https: true, // https 사용 설정
inline: true, // 인라인 모드 사용 설정
hot: true, // HMR(핫 모듈 리플레이스먼트) 모드 사용 설정
open: true, // 기본 브라우저 자동 열림 설정
overlay: true, // 경고,오류 발생 시 브라우저 전체화면 표시 설정
},
};
변경된 파일이 저장될 때 마다 파일을 관찰하여 webpack 명령을 재 실행하기 위한 옵션과,
다수의 코드를 번들링하되 효율적으로 관리하기 위한 소스맵 설정을 추가합니다.
<project_directory>
|- package.json
|- webpack.config.js
|- /node-modules
|- /dist
|- /src
HMR
const webpack = require('webpack');
module.exports = {
// webpack-dev-server 설정
devServer: {
hot: true,
},
// 플러그인 설정
plugins: [
new webpack.HotModuleReplacementPlugin()
],
};
핫 모듈 교체(HMR)는 webpack이 제공하는 가장 유용한 기능 중 하나 입니다.
완전히 새로 고침 할 필요없이 런타임에 모든 종류의 모듈을 업데이트 할 수 있습니다.
{
"scripts": {
"start": "webpack-dev-server",
"webpack": "webpack --config webpack.config.js",
"webpack:watch": "npm run webpack -- -w --progress"
},
}
NPM Scripts
package.json 파일에 환경설정(Configuration) 파일을 사용하여 webpack-dev-server를 실행하는 스크립트 구문을 추가합니다.
start 스크립트는 npm start 명령으로 실행할 수 있습니다.
Sass Loader
what
Sass는 CSS 프리프로세서(Pre-Processor)로 CSS의 비효율적인 부분을 커버 하는 스타일 스크립트입니다.
# SASS 번들링을 위한 개발 모듈
# node-sass
# sass-loader
npm i -D node-sass sass-loader
Install Sass Modules
Sass 프리프로세서(전처리기)를 사용하고자 한다면, 다음의 개발 모듈을 설치해야 합니다.
필요한 개발 모듈을 로컬 설치해 봅시다.
<project_directory>
|- package.json
|- webpack.config.js
|- /node-modules
|- /dist
|- /src
sass-loader
// SASS
{
test: /\.s(c|a)ss$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
}
webpack.config.js 파일에 sass-loader 설정을 추가합니다.
scss, sass 파일의 경우, sass-loader를 사용하도록 설정합니다.
Post CSS Loader
what
PostCSS는 JS 플러그인을 사용하는 CSS 컴파일러입니다.
미래의 CSS 문법을 오늘 날 바로 사용할 수 있도록 만들어 줍니다.
# PostCSS 개발 모듈 설치
npm i -D postcss-loader
Install PostCSS Modules
PostCSS 컴파일러를 사용하고자 한다면, 다음의 개발 모듈을 설치해야 합니다.
필요한 개발 모듈을 로컬 설치해 봅시다.
Reference
Guide
Webpack의 기본 사용법을 넘어 보다 전문적으로 사용하고자 한다면 가이드를 살펴보고 실습해보는 것이 좋습니다.