위코드 프론트앤드 스터디 준비를 위한 포스팅입니다!
7.3 웹팩 초급편
웹팩은 모듈 번들러
다. 모듈은 하나의 파일이라고 생각하면 된다.
번들은 여러 파일을 합쳐서 하나의 파일을 만들어준 결과 파일이라고 생각하면 된다.
번들러는 번들을 해주는 것이다. 그래서 웹팩은 모듈 번들러
이다.
웹팩, 바벨 등등 온갖 프론트 용어가 난무하므로 항상 깔끔하게 한 문장으로 정리해서 머리속에 입력하는 습관이 필요하다.
웹팩이 필요한 이유
CRA로 프로젝트를 생성할 때는 웹팩을 직접 설정하지 않았다. 이미 내장되어있기 때문이다. 그래서 웹팩의 존재를 모를 수 있다. 하지만 CRA로 프로젝트를 만들지 않으면 웹팩 설정을 일일이 해주어야 하며, CRA를 사용하지 않는 회사도 많기 때문에 웹팩을 사용할줄 알아야 한다.
react에서 컴포넌트를 작성할 때 한 파일에 하나의 컴포넌트를 정의했다.
너무 당연한 개발방식처럼 느껴지겠지만, pre course에 했던 게임 숙제를 생각해보자.
index.html
파일에서 마지막에 script 태그로 JavaScript 파일을 가져왔다.
이때 파일 순서가 중요했다. 그래서 Hero, Enemy 정의한 파일 먼저 작성하고 마지막에 init.js에서
Hero, Enemy를 가져와서 썼다.
브라우저에서 파일을 순서대로 로드하기 때문에 변수를 먼저 선언하고나서야 다른 파일에서 해당 변수를 쓸 수 있었기 때문이다.
이런식은 변수를 선언하면 전역변수가 되며, 직접 namespace를 만들어줘야하고, 파일 순서도 중요하고… 점점 파일이 많아지면서 서로 종속관계의 알기 어렵고 순서를 맞추기도 복잡해진다. 이런 문제들을 웹팩이 해결해준다.
7.3.1 웹팩 실행하기
설정파일 이용하기
프로젝트 루트에 webpack.config.js
파일을 만들어 설정한다.
"build": "rm -rf dist && NODE_ENV=production webpack"
process.env.NODE_ENV 같은 경우 package.json script에 추가해 놓았다.
module.exports = {
mode: process.env.NODE_ENV,
output: {
path: path.resolve(__dirname, './dist'),
filename: 'js/main.js'
}
}
mode가 프로덕션이면 자바스크립트 코드 압축을 포함한 여러가지 최적화 기능이 기본으로 들어간다.
압축하고 싶지 않으면 optimization: { minimizer: [] }
를 추가한다.
웹팩 번들 후의 파일은 제대로 보고 분석한 적이 없는데 책에 잘 설명되어 있다.
7.3.2 로더 사용하기
로더(loader)는 모듈을 입력으로 받아서 원하는 형태로 변환한 후 새로운 모듈을 출력해주는 함수다. js, img, css, csv 파일 등 모든 파일은 모듈이 될 수 있다.
babel-loader
자바스크립트 파일을 처리한다. 예를 들어 jsx 문법으로 작성된 리액트 코드를 처리할 때도 필요하다. babel 세팅도 해야한다. @babel/preset-react 프리셋을 사용하도록 설정한다. (babel 내용은 앞에서)
webpack.config.js 중 일부분 - js 확장자를 갖는 모듈은 babel-loader가 처리하도록 설정한다.
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: ['babel-loader']
}
]
}
css-loader
로더를 배열로 입력하면 오른쪽 로더부터 실행한다. sass를 사용하기 위해 sass-loader를 추가했고, js 마다 css를 import해서 사용할 수 있도록 MiniCssExtractPlugin.loader 를 사용하였다. 하지만 책에 의하면 css-module을 사용하는게 더 편리할 것 같다. 다음에 세팅해봐야지
{
test: /\.(sa|sc)ss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
}
file-loader
파일로더를 사용하지 않으면 root 경로에 모든 파일이 번들된다. 개발모드에서 사용한 경로대로 그대로 파일이 번들되길 바라면 file-loader를 사용하자. 그리고 name설정을 하지 않으면 파일 이름에 해시값이 포함되며 브라우저 캐싱효과를 활용할 수 있다. 이전에 설정할 때 왜 이미지 파일이름에 해시값이 포함되지 않고 같은 이름으로 하게 했는지 기억이 나지 않는다. 아마도 css에서 해당 파일을 읽어오지 못해서 그랬던 걸까?
{
test: /\.(png|jpe?g|gif|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[path][name].[ext]'
}
}
]
}
7.3.3 플러그인 사용하기
플러그인은 로더보다 강력한 기능을 갖는다. 로더는 특정 모듈에 대한 처리만 담당하지만 플러그인은 웹팩이 실행되는 전체 과정에 개입할 수 있다.
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
}),
new HtmlWebpackPlugin({
template: './src/index.html'
}),
]
js 파일이 번들 될 때마다 바뀌는 경우라면 매번 index.html을 수정해주어야 한다. HtmlWebpackPlugin을 설치하면 자동으로 js 파일을 추가해준다.