CRA 없이 리액트 개발환경을 구성해보려고 하는데,
대부분의 블로그들이
" 웹팩 환경설정은 webpack.config.js 파일에서 하는거고, 제 코드를 복붙하시면 됩니다 " 라는 식이었습니다.
나중에 언젠가 웹팩 설정때문에 발목이 잡힐 것 같아서, webpack.config.js 의 설정들을 파헤쳐보기로 했습니다.
💡 이 포스팅에서는 React + TypeScript 설정을 기반으로 합니다.
학습중인 주제이므로, 틀린 내용이 있을 수 있습니다.
댓글로 피드백 주시면 감사하겠습니다.
자바스크립트 코드가 많아지면 자연스럽게 파일을 나누게 되는데, 이 때 파일 하나 하나 불러오는 게 네트워크 속도를 느리게 할 수 있겠죠.
이 때 웹팩이 수많은 자바스크립트 파일을 하나의 파일로 묶어(bundle) 네트워크 비용을 최소화해줍니다.
흩어진 파일들을 확장자별로 번들링해주는 웹팩.
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const mode = process.env.NODE_ENV || "development";
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
우선 path
는 번들의 엔트리와 아웃풋의 경로 설정에 쓰이게 되는데, 자세한 것은 밑에서 설명하겠습니다.
mode
는 프로젝트가 프로덕트 모드 혹은 개발모드냐를 저장하고 있는 변수입니다.
HtmlWebpackPlugin
과 CleanwebpackPlugin
은 npm에서 다운받은 모듈로, 각각 html 파일의 번들링과 아웃풋 폴더의 클린업을 할 때 사용합니다.
module.exports = {}
webpack.config.js 파일을 어디에선가 require() 메소드로 끌어다 쓰기 때문에, module.exports 로 설정들을 내보내줍니다.
entry: {
app: path.join(__dirname, "src", "index.tsx"),
},
// 최종 html에서 사용할 js 파일은 app.js 파일인데, 이 파일은 엔트리 포인트인 src/index.tsx로부터 빌드됩니다.
웹팩으로 여러 코드들을 번들링 하려면 복잡하게 얽힌 코드들의 맨 처음 시작점이 되는 파일이 필요한데, 이를 엔트리 파일 이라고 부릅니다.
엔트리파일을 명시해줘야 웹팩이 번들링 시작점을 찾을 수 있습니다.
output: {
filename: "[name].js", // [app].js (엔트리의 키가 app이므로)
path: path.resolve(__dirname, "dist"),
// 웹팩 설정 완료 후 빌드하면 프로젝트 루트 경로에 dist폴더가 생기고 그 안에 번들링 결과물인 [app].js가 들어있게 됩니다.
},
엔트리 파일로부터 복잡하게 얽혀있던 코드들을 하나의 파일로 번들링한 결과물을 설정하는 단계입니다.
filename
은 번들링된 파일의 이름을 설정합니다.
path
는 번들링된 파일을 어느 경로에 저장할지 설정합니다.
path.join() 과 path.resolve() 의 차이는 join()의 경우 인자들을 모두 concat 하지만, resolve는 인자들을 루트로 인식합니다.
예시:
path.join('/a', '/b') // Outputs '/a/b' path.resolve('/a', '/b') // Outputs '/b'
module: {
rules: [
{
test: /\.(ts|tsx)$/, // tsx나 ts파일을 발견하면
use: "ts-loader", // 해당 loader를 통해서 ts를 js로 변환합니다.
exclude: /node_modules/, // 패키지 폴더는 제외합니다.
},
],
},
웹팩은 자바스크립트만을 모듈화 대상으로 인식하기 때문에,
타입스크립트나 바벨도 웹팩이 인식하게끔 설정해줘야 합니다.
여기서는 일단 타입스크립트만 로더로 불러왔습니다.
plugins: [
new HtmlWebpackPlugin({
// 빌드시 html에 값을 전달, html 변경 & html 코드 압축(공백, 주석제거) & webpack으로 빌드한 번들 파일을 자동으로 html에 추가
template: "./src/index.html", // index.html 파일을 템플릿으로 씁니다.
templateParameters: {
// 해당 템플릿에 전달하는 인자들
env: process.env.NODE_ENV === "production" ? "" : "[DEV]",
},
minify:
process.env.NODE_ENV === "production" // 프로덕션 모드일경우 공백,주석 제거
? {
collapseWhitespace: true,
removeComments: true,
}
: false,
}),
new CleanWebpackPlugin(), // 빌드때마다 dist 폴더 클린업
],
로더가 파일단위로 처리해주는 반면, 플러그인은 번들된 결과물을 처리합니다.
HtmlWebpackPlugin
의 경우 template
에 지정한 html 파일을 번들링하는데, 이때 공백이나 주석을 제거하는 옵션을 넣어 용량을 줄일 수 있습니다.
CleanWebpackPlugin
의 경우, 번들링 결과물이 담기는 장소인 dist
폴더를 매 빌드 때마다 비워주는 플러그인입니다.
// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const mode = process.env.NODE_ENV || "development";
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
mode,
entry: {
// 최종 index.html에서 사용할 js 시작점은 app.js 파일인데, 이 파일은 src/index.tsx로부터 빌드된다.
app: path.join(__dirname, "src", "index.tsx"),
},
output: {
filename: "[name].js", // [app].js
path: path.resolve(__dirname, "dist"), // 빌드하면 dist폴더가 생기고 그 안에 번들링 결과물인 [app].js가 들어있다.
},
resolve: {
extensions: [".jsx", ".js", ".tsx", ".ts"], // 웹팩에서 처리해주는 확장자들
},
module: {
rules: [
{
test: /\.(ts|tsx)$/, // tsx나 ts파일을 발견하면
use: "ts-loader", // 해당 loader를 통해서 ts를 js로 변환한다.
exclude: /node_modules/,
},
],
},
plugins: [
new HtmlWebpackPlugin({
// 빌드시 html에 값을 전달, html 변경 & html 코드 압축(공백, 주석제거) & webpack으로 빌드한 번들 파일을 자동으로 html에 추가
template: "./src/index.html", // index.html 파일을 템플릿으로 쓴다.
templateParameters: {
// 해당 템플릿에 전달하는 인자들
env: process.env.NODE_ENV === "production" ? "" : "[DEV]",
},
minify:
process.env.NODE_ENV === "production" // 프로덕션 모드일경우 공백,주석 제거
? {
collapseWhitespace: true,
removeComments: true,
}
: false,
}),
new CleanWebpackPlugin(), // 빌드때마다 dist 폴더 클린업
],
};
김정환님 블로그 : https://jeonghwan-kim.github.io/js/2017/05/15/webpack.html
kihyeon8949 님 벨로그 : https://velog.io/@kihyeon8949/CRA%EC%97%86%EC%9D%B4-Tool-React-Typescript-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0
웹팩 공식 사이트 : https://webpack.js.org/
path.join() 과 path.resolve() 의 차이 : https://stackoverflow.com/questions/35048686/whats-the-difference-between-path-resolve-and-path-join
제공한 붙여넣기 코드를 통해 webpack.config.js 파일에서 Webpack 환경 설정에 대한 매우 유용한 기사입니다. 매우 빠르다! @geometry dash subzero