Reference : webpack.docs
webpack은
모든 file을 module로 간주하며
project에 필요한 모든 모듈을 dependency graph에 따라 번들링하는 도구이다.
번들링된 결과물을 bundle이라 한다.
./src/index.js
module.exports = {
entry: './path/file.js';
};
./dist/main.js
const path = require('path');
module.exports = {
entry: './path/file.js';
output: {
path: path.resolve(__dirname, 'dist');
filename: 'myBundle.js';
}
};
box 밖에서, webpack은 Javascript 언어로 작성된 파일(module)만 읽어들일 수 있다.
따라서 Loaders를 사용해 다른 형식의 파일(module)을 valid한 modules로 바꾸고 dependency graph에 추가한다.
loaders는 2가지의 property를 갖는다.
npm install --save-dev css-loader ts-loader
const path = require('path');
module.exports = {
output: {
filename: 'my-first-webpack.bundle.js'
},
module: {
rules: [
{ test: /\.css$/, use: 'css-loader' },
{ test: /\.ts$/, use: 'ts-loader'}
]
}
};
import / require() 선언에
.txt 파일이 포함될 떄
raw-loader를 사용해서 transform하고, bundle에 추가
정규식에 quote를 추가하지 말 것!
동일한 regex에 대해 다수의 loader를 추가할 경우
right에서 left로 실행된다. (array에서 pop하기 떄문)
npm install --save-dev css-loader style-loader sass-loader
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: 'style-loader'},
{
loader: 'css-loader',
options: { module: true }
},
{ loader: 'sass-loader'}
]
}
]
};
};
loader가 할 수 없는 모든 역할을 수행
plugins는 bundle 최적화, assets management, 환경변수 injection과 같은 역할을 수행한다.
대부분의 plugins는 options를 통해 커스터마이징이 가능하며
new operator를 통해 여러 인스턴스를 생성할 수 있다.
npm i --save-dev html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); // built in plugins
module.exports = {
entry: 'index.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'index_bundle.js'
},
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }
]
},
plugins: [
new HtmlWebpackPlugin({template: './src/index.html'})
],
};
// dist/index.html이 생성된다.
// entry point가 여러 개 일 경우, script로 포함된다.
module.exports = {
mode: 'production'
};
reference : https://www.valentinog.com/blog/webpack/
npm init -y
npm i webpack webpack-cli webpack-dev-server --save-dev
// in package.json
"scripts": {
"dev": "webpack --mode devleopement"
}
development mode
Development
로 변경production mode
production
으로 변경1) entry point
2) output
3) loaders
4) plugins
5) code splitting
// webpack.config.js
const path = require('path');
module.exports = {
entry: {
index: path.resolve(__dirname, 'source', 'index.js');
},
output: {
path: path.resolve(__dirname, 'build')
}
}
HtmlWebpackPlugin : bundle을 로딩할 HTML파일을 생성해주는 플러그인
npm i html-webpack-plugin --save-dev
// webpack.cofig.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
output: {
path: path.resolve(__dirname, './dist'),
filename: 'bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
title: 'myApp',
template: './src/template.html', // DOM element를 추가하기 위해 설정
}),
new HtmlWebpackPlugin({
title: 'chang hyun', // title 태그
filename: 'index2.html', // output file 이름
inject: 'head', // script 위치 결정
scriptLoading: 'defer',
// favicon: 'path',
meta: { // meta 태그
viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'
},
base: 'https://naver.com/path/', // nase 태그,
minify: true, // minify 유무
hash: true, // scripts , css 파일 hash 컴파일링 옵션 (브라우저 캐싱 방지로 사용)
cache: true, // 캐싱을 통해 변경된 파일만 emit
showErrors: true, // 에러 발생 시 html 파일에 detail이 표기됨
})]
}
// 아래 깃헙 링크를 참고하면 여러 세팅이 가능
https://github.com/jantimon/html-webpack-plugin#options
// package.json
"scripts": {
"start": "webpack-dev-server --mode development --open"
}
local server를 launch
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.filename$/,
use: ["loader-b", "loader-a"]
}
]
},
};
css-lodaer : CSS file type을 모듈화해 import가 가능해짐
style-loader : js로 변환된 stylesheet을 DOM에 입힘
npm i css-loader style-loader --save-dev
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
module: { // 다른 type을 loader를 통해 모듈화
rules: [
{
test: /\.s|css$/,
use: ["style-loader", "css-loader", "sass-loader"] // css type을 바꾼 후, style을 적용해야 되므로 순서에 유의할 것 (LIFO)
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'src', 'index.html')
})
]
};
// index.js
import './css/style.css';
import './css/style.scss';
es6 import는 synchronous하므로 specification이 동일한 selector가 있을 경우
style.sass의 스타일링에 적용됨
npm i @babel/core babel-loader @babel/preset-env --save-dev
// babel.config.js
{
"presets": [
"@babel/preset-env"
]
}
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: ["babel-loader"]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html")
})
]
};
webpack은 두 종류의 mode로 나뉜다.
- bundle을 browser로 load하며
- minification을 진행하지 않기 때문에 빠르게 reloading이 가능.
- TerserWebpackPlugin을 통해 번들 사이즈를 줄이고
- ModuleConcatenationPlugin을 통해 호이스팅을 scope화한다.
- process.env.NODE_ENV 환경변수를 'production'으로 설정한다.
- 환경변수를 통해 조건적으로 production모드에 적용할 수 있음.
// in package.json
"scripts" : {
"dev": "webpack --mode development",
"start": "webpack-dev-server --mode development --open",
"build": "webpack --mode production"
}
최적화 기법 중 하나로
주요 기법
multiple entry points
- 작은 프로젝트에서만 효과적
optimization.splitChunks
dynamic imports
npm i moment
// index.js
import moment from 'moment';
npm run build
/*
index.js에서 대용량 라이브러리를 import해 그대로 빌드할 경우
라이브러리를 포함한 모든 코드가 bundle로 올라가게 되는데,
webpack.config의 optimization.splitChunks를 통해
moment.js를 main bundle 밖의 다른 번들로 분리하면 main 번들의 로딩 타임을 줄일 수 있게 된다.
*/
// webpack.config.js
module.exports = {
optimization: {
splitChunks: { chunks: "all" }
},
};
Code splitting might be used
module level에서의 dynamic import를 통한 code splitting 기법을 살펴보자면
const getUserModule = () => import('./common/usersAPI')
// getUserModule을 실행할 경우, import하여 모듈을 리턴한다.
const btn = document.getElementById('btn');
btn.addEventListener('click', () => {
getUserModule().then(({ getUsers }) => {
getUsers().then(json => console.log(json))
});
})
"scripts": {
"dev": "webpack --mode development",
"start": "webpack-dev-server --mode development --open --hot",
"build": "webpack --mode production"
},
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: path.join(__dirname, 'src', 'index.js'),
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './dist')
},
module: {
[
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.s|css$/,
exclude: /node_modules/,
use: ['style-loader', 'css-loader']
}
]
},
plugins: [
new HtmlWebpackPlugin({
template:'./public/index.html'
})
]
}
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
}
안녕하세요 웹팩 정리하신 글 잘보았습니다! 그런데 혹시
동일한 regex에 대해 다수의 loader를 추가할 경우right에서 left로 실행된다. (array에서 pop하기 떄문)
여기서 array 에서 pop 하기 때문이라는 이유는 어디서 보셨는지 알수있을까요!!?