우아한테크코스 5기 미션 점심 뭐 먹지
의 웹팩 설정 파일을 보며 웹팩 기초를 공부한 과정입니다.
0. 작성 이유
점심 뭐 먹지 미션을 하면서 html
파일을 분리한 구조를 사용했습니다.
당연히 js
에서 html
을 import
할 수 있을 것이라고 생각했는데요, 안되더라구요
그래서 이번 기회에 아예 몰랐던 webpack
공부를 해봤고, 그 정리본입니다.
처음 공부했기 때문에 아래 내용은 정확하지 않을 수도 있어요. 잘못된 부분은 같이 고쳐봐요. 댓글 환영합니다!
1. webpack 이란?
웹 페이지를 만들 때 생기는 수많은 파일들(js
, css
, html
, assets
등) 을 하나로 묶어주는 도구 중 하나 (번들러 라고 합니다)
webpack
이외에도 parcel
같은 번들러가 있습니다.
2. webpack 도입 시 효과
먼저 여러 파일을 하나로 묶어주어서 클라이언트↔서버 간 통신 부하가 줄어듭니다!
또한 모듈끼리는 전역스코프를 공유하는 문제가 있는데요,
이를 해결하기 위해 즉시실행함수로 모듈을 함수스코프로 감싸주거나 <script type=’module’>
를 이용합니다.
하지만 모든 브라우저에서 모듈 시스템(<script type="module">
)을 지원하지 않기 때문에, 호환성에 문제가 생깁니다.
모듈별로 스코프를 만들어주는 역할을 웹팩이 수행합니다!
3. webpack.config.js 란?
파일 번들 시 웹팩이 할일을 설정해주는 파일입니다.
4. 점심 뭐 먹지
의 webpack.config.js
레포 링크: https://github.com/woowacourse/javascript-lunch
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: "development",
entry: "./src/index.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
clean: true,
},
resolve: {
extensions: [".ts", ".js", ".mjs"],
},
module: {
rules: [
{
test: /\.(js|mjs|ts)$/i,
exclude: /node_modules/,
use: {
loader: "ts-loader",
},
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
loader: "file-loader",
options: {
name: "[name].[ext]",
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./index.html",
}),
],
devtool: "inline-source-map",
devServer: {
static: "./dist",
hot: true,
open: true,
},
};
각 설정(프로퍼티)별로 설정을 알아보겠습니다.
알아보기 전에! 점심 뭐 먹지의 package.json 에서는…
"scripts": {
"watch": "webpack --watch",
"start": "webpack serve",
"build": "webpack --mode=production",
...
},
webpack
을 이용해 프로젝트 빌드를 해주고 있습니다.
이제 진짜 알아보죠.
mode
module.exports = {
mode: "development",
...
}
mode
를 통해 파일을 어떻게 번들링을 해줄 것인지 설정할 수 있습니다.
- production(배포) 모드 : 로드 시간을 줄이기 위해 번들 최소화, 가벼운 소스맵 및 애셋 최적화에 초점을 맞춥니다.
- 번들링 결과
- development(개발) 모드 : 개발 생산성을 높이기 위한 모드. 버그발생 위험이 있는 코드를 미리 경고해 주는 검증 코드도 포함되어 있습니다.
- 번들링 결과
production
모드는 띄워쓰기도 없애면서 번들링 파일을 최적화 하고있고, development
모드는 더 보기 쉽게 되어있는 걸 확인할 수 있습니다.
package.json
을 다시보면,
"scripts": {
"watch": "webpack --watch",
"start": "webpack serve",
"build": "webpack --mode=production",
...
},
개발 시(watch, start를 이용)에는 development
모드를 이용하고 있고
배포 시에는 production
모드를 이용하는걸 볼 수 있습니다.
entry
module.exports = {
...
entry: "./src/index.js",
...
}
entry
는 번들링할 시작 파일을 명시할 수 있습니다.
entry
로 설정한 파일에서 사용중인 파일들을(import하여 사용중인 파일이나 이미지) webpack
이 알아서 번들링 해줍니다.
이건 제 점심 뭐 먹지 entry
인데요,
저기서 import
한 파일들을 webpack
이 따라가면서 연관된 파일들을 모두 번들링 해줍니다!
output
module.exports = {
...
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
clean: true,
},
...
}
output
은 번들링된 결과 파일에 대한 설정을 해줍니다.
- filename: 번들링 결과 파일명
- path: 번들링 결과 파일 경로
- clean: 번들링 시 이전에 생성되어있던 번들링 파일을 지우고 번들링
이외에도 많은 설정들이 있습니다.
resolve
module.exports = {
...
resolve: {
extensions: [".ts", ".js", ".mjs"],
},
...
}
resolve
은 모듈(파일)을 해석하는 방식을 설정합니다.
여러 경우에 대해서 설정할 수 있는데요,
점심 뭐 먹지에서는 확장자 extension
에 대해서만 정의해놓았습니다.
extensions: [".ts", ".js", ".mjs"]
이렇게 설정해놓으면 import 할 때 확장자를 생략할 수 있습니다.
생략된 확장자는 웹팩이 저기 명시된 순서대로(ts, js, mjs) 해석합니다.
제 entry
파일을 다시 볼까요?
import
문들을 보면 확장자가 생략되어 있습니다. 생략된 확장자들은 웹팩에서 붙여서 해석합니다.
12번째 줄을 보면 style
도 불러오는 것을 볼 수 있습니다. 저렇게 style을 불러오려면 .css
확장자도 추가해야겠네요.
그래서 저는 extenstions에 이렇게 추가해주었습니다.
extensions: [".ts", ".js", ".mjs", “.css”]
하지만 사실 웹팩은 js
파일만 해석할 수 있습니다.
따라서 저렇게만 해주면 기본 웹팩은 ts
, css
를 이해하지 못하기 때문에, loader
를 설치해서 웹팩 기능을 확장시켜야 합니다.
loader
설정을 module
에서 해봅시다!
module
loader
은 웹팩이 기본적으로 제공해주는 기능에 추가해서 사용할 수 있는 extension
기능이라고 보시면 됩니다.
module.exports = {
...
module: {
rules: [
{
test: /\.(js|mjs|ts)$/i,
exclude: /node_modules/,
use: {
loader: "ts-loader",
},
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
loader: "file-loader",
options: {
name: "[name].[ext]",
},
},
],
},
...
}
module
의 rules
에서 loader
를 적용할 파일들을 정의할 수 있는데요,
즉 각 파일에 대해서 적용할 loader
를 정의하는 것입니다.
test
:loader
를 적용할 파일의 확장자를 정규표현식으로 선언exclude
: 정규표현식에 일치하는 파일 중에서 제외할 파일use
: 사용할loader
들 선언
대표로 .css
에 적용하는 loader
인 style-loader
와 css-loader
에 대해서 알아보겠습니다.
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
(뒤쪽에 있는 loader
가 먼저 실행됩니다. chaining이 있으므로 loader
의 순서가 중요한 경우에 유의합시다)
css-loader
는 css import문을 읽어서 가져와주는 역할style-loader
는 가져온 css를 실제로 주입해주는 역할
css-loader
→ style-loader
순서로 동작해야하므로 위 그림처럼 설정하면 style-loader
가 먼저 동작하기 때문에 에러가 납니다.
따라서 이렇게 설정해야합니다.
그러면 이제 우리는 js, ts 파일에서 css 파일들을 import하여 적용할 수 있습니다! 웹팩이 해당 코드를 이해할 수 있기 때문이죠.
💡 `webpack`에서 제공하는 공식 `loader`와 사용자들이 만든 `loader` 등 많은 `loader`들이 있으니 필요한 기능이 있다면 찾아서 사용합시다.
추가로 저는 js
에서 html
을 import
하기 위해 html-loader
를 이용했습니다!
Plugins
loader
와는 다른 또다른 extension
입니다.
loader
는 번들링 하는 과정(process)에서의 확장기능이라면 plugin
은 최종 번들링 결과물(output
)을 변경해주는 도구입니다. (웹팩 번들링 후 변환된 파일에 추가적인 기능을 더하기 위해 사용합니다.)
plugin
은 loader
보다 더 복합적이고 자유로운 일들을 할 수 있습니다.
loader
는 동작 형태가 규정되어 있지만, plugin
은 plugin
마다 사용방법이 제각각 다릅니다.
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
template: "./index.html",
}),
],
...
}
점심 뭐 먹지에서 사용한 plugin
은 HtmlWebpackPlugin
입니다.
npm
라이브러리인 html-webpack-plugin
을 설치해서 사용합니다.
HtmlWebpackPlugin
은 html
파일을 자동으로 생성해주는 역할을 하는데요,
만약 HtmlWebpackPlugin
없이 build
한다면 html
파일이 없습니다. 그래서 일일히 추가해줘야해서 번거롭죠.
하지만 HtmlWebpackPlugin
을 이용하면, 번들링 결과 생긴 js
파일을 import
(<script type="module" src="./dist/about.bundle.js"></script>
)하는 html
파일을 만들어서 output
디렉터리에 생성해줍니다.
점심 뭐 먹지의 설정에서는 template html
을 이용하는 옵션을 추가했네요.
그러면 template html
에 번들링 된 결과 생성된 bundle.js
파일을 참조하는 html
파일을 만들어줍니다.
)
)
이 외에도 다양한 플러그인들이 있으니, 찾아서 적용하시면 됩니다.
devtool
devtool
은 소스맵을 어떻게 생성할지 그 규칙을 정하는 프로퍼티입니다.
소스맵에 대해서는 링크로 남겨놓았습니다.
devServer
코드를 실행하려고 매번 npm run build
를 수동으로 실행하기엔 번거롭죠. 그래서 webpack
은 코드가 변경될 때 마다 자동으로 컴파일하는 옵션 devServer
을 제공합니다.
devServer
를 사용하려면 먼저 "webpack-dev-server"
npm 라이브러리를 설치해야합니다.
점심 뭐 먹지 package.json
에는 4.11.1 버전을 명시해두었습니다.
module.exports = {
...
devServer: {
static: "./dist",
hot: true,
open: true,
},
};
- static:
webpack-dev-server
이 명시한 디렉터리의 파일을localhost:8080
에서 실행합니다. - open: 서버가 시작된 후 브라우저를 열어줍니다.
- hot(
hot module replacement
): 수정된 부분만 바뀌고, 입력해놓은 정보들은 유지되는 기능입니다.(최적화)
webpack-dev-server
를 실행하려면, npx webpack serve
명령어를 이용하면 됩니다.
여기서 package.json
을 다시보면,
"scripts": {
"watch": "webpack --watch",
"start": "webpack serve",
"build": "webpack --mode=production",
...
},
우리는 미션 프로젝트를 실행할 때 npm run start
을 이용했죠.
즉 webpack-dev-server
를 이용한 것임을 알 수 있습니다!
webpack-dev-server
에 대한 더 자세한 옵션이나 설명은 docs 에서 보실 수 있습니다.
이어서 학습하면 좋은 부분
Code Splitting
과 Lazy loading
: 커진 번들러 파일을 분리하고, 필요한 모듈만 불러오는 방법을 알아봅시다.
마무리
잘 모르고 그 존재만 알았던 웹팩, 정리를 하고나니 어떻게 프로젝트가 설정되었는지 이해할 수 있었어요.
웹팩은 아주 방대하니 시간을 두고 꾸준히 알아가야할 것 같습니다!
Reference
https://www.youtube.com/watch?v=dt2xU71pX88&list=PLuHgQVnccGMChcT9IKopFDoAIoTA-03DA&index=7
'우아한테크코스 5기 프론트엔드' 카테고리의 다른 글
[우아한테크코스 프로젝트 기록] 3차 데모데이 ~ 론칭 페스티벌 (5) | 2023.08.22 |
---|---|
[우아한테크코스 프로젝트 기록] 2차 데모데이 ~ 3차 데모데이 (1) | 2023.08.05 |
[우아한테크코스 프로젝트 기록] 1차 데모데이 ~ 2차 데모데이 (2) | 2023.07.23 |
[우아한테크코스 프로젝트 기록] 동글 첫 만남 ~1차 데모데이 (2) | 2023.07.09 |
CRA 없이 리액트 시작하기 with webpack (11) | 2023.06.30 |