3/21 일일정리 웹팩 실습
React Project Bundling
어제에 이어서 이번에는 React로 만든 프로젝트에 웹팩으로 번들링를 해봤다.
원래는 CRA로 만든 프로젝트는 npm start를 하면 자체적으로 번들링을 해주는데,
웹펙과 번들링을 알아보기 위해 직접 webpack.config.js 파일을 만들고 여러가지 설정을 해봤다.
//webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "app.bundle.js",
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
exclude: /node_modules/,
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html"),
}),
],
};
일단은 어제 해본 웹팩 설정을 base로 하여 필요한 것들을 추가하기로 했다.
리마인드를 해보자면
entry 프로퍼티에는 번들링를 시작할 파일을 지정한다. 여러개를 지정할수 있지만 여기서는 하나만 지정했다.
output 프로퍼티에는 번들링하여 만들어질 파일을 담을 폴더와, 번들링 파일 이름을 지정해준다. dist폴더의 app.bundle.js 파일에 번들링된 코드를 작성할 것이다.
module에는 loader를 지정하는에 일단은 css파일을 같이 번들링해주는 style-loader와 css-loader가 지정되어 있다.
plugins는 추가적인 플러그인을 지정하는데 지금은 html plugin이 지정되어 있다.
이번에 사용할 react 프로젝트의 구성은 위와 같다. index.js로 진입하면 다른 js 파일들은 연결되어 있으므로 따로 처리할 건 없었다. index.css도 마찬가지로 index.js에 import 되어있기 때문에 index.js 파일을 entry로 지정한다.
output은 dist라는 파일에 app.bundle.js라는 파일로 지정해줬다.
clean : ture 옵션은 파일을 번들링 할 때 이전 결과물을 삭제하고 다시 폴더를 만들어주는 옵션이다.
이제 loader를 지정해주는 부분이 중요한데 React 의 jsx 파일은 js파일이 아니기 때문에 브라우저가 읽지 못한다. 따라서 js파일로 변환해줘야 하는데 jsx파일을 js 파일로 변환해주는 babel-loader를 사용해야 한다.
일단 babel -loader를 설치하고
npm install -D babel-loader @babel/core @babel/preset-env webpack
config 파일의 module 내부에 babel-loader를 추가한다.
정규 표현식으로 .js로 끝나는 파일은 babel-loader를 적용하도록 해주었다.
option에는 @babel/preset-env, @babel/preset-react를 지정해준다.
* @babel/preset-react에서 runtime : 'automatic' 옵션을 주지 않으면 import를 제대로 하지 못해서 에러가 발생한다.
그리고 css 파일도 변환해야 하기 때문에 css-loader와 style-loader를 지정해준다.
plugins 에는 index.html을 지정해서 자동으로 bundle 파일을 불러올 수 있도록 해준다.
webpack.config.js 완성본
//webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "app.bundle.js",
clean: true,
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [
"@babel/preset-env",
["@babel/preset-react", { runtime: "automatic" }],
],
},
},
},
{
test: /\.css$/,
use: ['style-loader', "css-loader"],
exclude: /node_modules/,
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "public", "index.html"),
}),
]
};
폴더와 파일이 잘 만들어지고, html파일로 웹을 켜보면 제대로 동작하는 것을 볼 수 있다.
CSS minify
추가로 CSS에 minify를 적용해 보았다.
mini-css-extract-plugin
먼저 mini-css-extract-plugin을 사용하여 번들링을 해봤다.
mini-css-extract-plugin을 설치하고 require로 불러온다.
plugins에 new 키워드로 인스턴스를 만들어서 등록한다.
그리고 css loader 부분에 style-loader 대신 mini-css-extract-loader를 지정해준다.
이렇게 하면 번들파일에 css를 넣는것이 아니라 따로 css파일을 만들어서 폴더에 넣어준다.
mini-css-extract-plugin 쓰는 이유는 최적화를 위해서이다. 번들링을 하게되면 하나의 파일이 되면서 용량이 커지는데, 이렇게하면 웹페이지의 첫 화면을 로딩할 때 시간이 오래 걸릴 수 있다. 파일을 분리하면 전체 웹페이지의 리소스를 한번에 로딩하는 것이 아니라 사용자가 필요할 때까지 미뤄두다가 원하는 시점에 리소스를 로딩한다.(대표적으로는 무한 스크롤)
css-minimizer-webpack-plugin은 css 파일을 압축시켜주는 cssnano라는 라이브러리를 사용하는 플러그인이다.
원래는 기존 css 파일과 똑같이 나오는데 css-minimizer-webpack-plugin을 적용하면
이렇게 한줄로 길~~~~게 나온다.
webpack-bundle-analyzer
이번에는 webpack-bundle-analyzer라는 플러그인을 사용해보았다.
이 플러그인은 번들링 할 때 각 파일의 사이즈를 알 수 있도록 시각화 해서 보여주는 플러그인 이다.
이 플러그인도 다른 플러그인과 마찬가지로 config파일에 require로 불러와서
plugins 에 등록해주면 된다.
옵션같은 경우
analyzerMode : static은 분석파일을 번들링 폴더에 담는 옵션이다.
openAnalyzer : false는 분석파일을 바로 열지 않도록 하는 옵션이다.
generateStatsFile : true 는 분석파일을 json 형태로 저장하는 옵션이다.
statsFilename은 분석파일 이름.json 형태로 작성한다.
reportFilename은 분석파일 이름.html 형태로 작성한다.
이렇게 작성하고 번들링하면 폴더에 우리가 지정한이름의 파일 2개가 추가로 생성된다.
bundle-report.html 파일을 열어보면 다음과 같은 웹페이지가 나온다.
마우스 커서를 올려보면 번들링 된 파일의 사이즈나 용량 같은 것이 나온다.
여기서 Gzipped size가 실제로 번들링된 크기라고 한다.
이 페이지를 보면서 어떤 파일이 사이즈가 어떤지를 알 수 있는데 이것을 토대로 파일들을 수정하고, 필요없는 파일들을 제거하면서 웹페이지 최적화를 진행할 수 있다.
Reference
- 코드스테이츠