오늘은 웹팩 번들러를 달았어요!
사실 Parcel
을 할까도 굉장히 고민이 많았어요.
결국 번들러도 상황에 맞는 선택이라 생각하는데, 현재 프로젝트가 작은데다, 굳이 엄~청 디테일한 옵션을 달 게 없어서, parcel
만으로도 충분했기 때문이에요.
사실 웹팩을 달기 위한 이유는 다음과 같았어요.
- 언젠가 먼 미래에, 디테일한 설정을 위해
webpack
과 친해질 일이 필요하겠다! (사실, 프로젝트의 목적이 제 실력을 증빙하기 위한 거니까요!)- 따라서 설정해본 적은 있어도, 직접 욕심내며 설정해본 적은 없다! 이 참에 도전해보자!!
- 지금 당장
npm
패키지를 달고 싶은데, 라이브러리는 현재module
타입으로 불러올 수 없다. 그렇다고cjs
,mjs
로 모두 일간성 있게 통일시키기는 굳이...?라는 생각이 든다. 따라서 이를 모듈로 쉽게 불러오려면 번들러 사용이 적합하겠다!- 빌드할 시, 성능도 빨라질 뿐더러 (모듈을 하나로 통합시키기 때문), HMR 기능도 충분히 잘 제공하고 있어서, 이를 개발 환경 서버로 이용하기 좋아보였다!
그래서 어떻게 보면 계륵인 이 친구랑, 이번에 친해지기로 마음을 먹었어요.
그렇다면, 어떻게 제가 이 친구를 사용할 수 있게 됐는지, 과정을 살펴보죠!
저는 다음과 같이 패키지를 설치했답니다. 꼭 참고해주세요!
{
"type": "module",
"name": "no-hesitation",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"@babel/polyfill": "^7.12.1",
"dotenv": "^10.0.0",
"normalize.css": "^8.0.1"
},
"devDependencies": {
"@babel/cli": "^7.14.8",
"@babel/core": "^7.15.0",
"@babel/plugin-proposal-class-properties": "^7.14.5",
"@babel/preset-env": "^7.15.0",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.2.2",
"clean-webpack-plugin": "^4.0.0-alpha.0",
"css-loader": "^6.2.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.1",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.3.2",
"mini-css-extract-plugin": "^2.2.1",
"node-sass": "^6.0.1",
"prettier": "^2.3.2",
"sass-loader": "^12.1.0",
"style-loader": "^3.2.1",
"url-loader": "^4.1.1",
"webpack": "^5.51.1",
"webpack-cli": "^4.8.0",
"webpack-dev-server": "^4.1.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"dev:webpack": "webpack-dev-server --mode development",
"build": "webpack --mode production"
},
"repository": {
"type": "git",
"url": "git+https://github.com/JengYoung/No-Hesitation.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/JengYoung/No-Hesitation/issues"
},
"homepage": "https://github.com/JengYoung/No-Hesitation#readme"
}
이렇게 하면, 이제 저희가 필요할 웹팩 설정들이 완료가 돼요!
이제 여기서 우리는 꼭 알아야 할 친구들이 있어요. entry
output
module
rules
등인데요!
정~말 간단히 짚고 넘어가볼까요?
entry
니 어데서 시작하나 ?!output
니 결과물 어따 내뱉을래 ?!module
니 모듈로 내뱉을 때 어떤 규칙으로 할낀대 !plugin
이제 번들된 거 어떻게 처리할래?!devServer
서버 어떻게 옵션 설정할낀대!
입니다. 생각보다 간단하죠?! 저도 이게 처음에는 정~말 당황스러웠어요.
하지만 다음과 같은 생각을 하니, 좀 간단해졌습니다.
이거 결국에는
module.export = {...}
잖아?
그럼 모듈로 내뱉어져서 일종의 객체처럼 쓸 건데, 그럼 결국에는 어떤 api쓸 때 옵션 쓰는거랑 비슷한 거 아냐?!
결국에 우리는 어떤 어려운 것들을 처리하기 위해, 웹팩이란 걸 썼을 뿐입니다. 그리고 그저 웹팩은 모듈인 파일들을 번들시켜줄 뿐이구요! 생각보다 겁 먹을 일이 없더라구요!
그럼, 내용물을 볼까요?
const path = require('path');
const HtmlPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: ['@babel/polyfill', './src/index.js', './src/sass/main.scss'],
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
devServer: {
static: './dist',
hot: true, // 이게 HMR을 가능하게 해줘요!!
},
module: {
rules: [
{
test: /\.js$/,
include: [path.resolve(__dirname, 'src')],
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-proposal-class-properties'],
},
},
},
{
test: /\.png$/, // .png 확장자로 마치는 모든 파일
loader: 'file-loader',
options: {
publicPath: './dist/', // prefix를 아웃풋 경로로 지정
name: '[name].[ext]?[hash]', // 파일명 형식
},
},
{
test: /\.png$/,
use: {
loader: 'url-loader', // url 로더를 설정한다
options: {
publicPath: './dist/', // file-loader와 동일
name: '[name].[ext]?[hash]', // file-loader와 동일
limit: 10000, // 10kb 미만 파일만 data url로 처리
},
},
},
{
test: /\.s?css$/,
use: [
'style-loader', // creates style nodes from JS strings
'css-loader', // translates CSS into CommonJS
'sass-loader', // compiles Sass to CSS, using Node Sass by default
],
exclude: /node_modules/,
},
],
},
plugins: [
new HtmlPlugin({
template: './index.html',
hash: true,
}),
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({ filename: 'css/style.css' }),
],
devtool: 'source-map',
mode: 'development',
};
네, 저는 다음과 같이 빌드할 옵션들을 설정해줬어요.
솔직히 저도 거의 다 참고하면서 작성했지만 일부 핵심들만 살펴보자면 다음과 같아요.
바벨, 참 고마운 친구에요! 이 친구 없으면 우리는 정말 🐶고생을 해야 한답니다...!
이 친구가 이제 js
파일에 대해서 잘~처리해줄 건데요, preset
과 plugin
이 필요해요.
일단 저런 것들을 설정해준다면, 자바스크립트의 최신 문법을 지원하지 않는 브라우저에서도 쓸 수 있도록 해줍니다!
조만간 이는 바벨 포스팅으로 다뤄볼게요 😝
js와 호환되어 만들어진 css를 style 태그로 만들어 직접 붙여주는 (역할을 해요! 말이 좀 어렵긴 한데, 저는 다음과 같이 이해했답니다)
결과적으로는 다음과 같죠!
어때요! 잘 붙여졌죠?!
그리고 플러그인의 경우에는 조심해야 할 게, 저 순서에 유의해서 붙여줘야 한답니다!!! 제가 알기로는 뒤에서부터? 처리되는 걸로 알고 있어요!
제 일차적인 목적은 결국 index.html
을 빌드해서 서버 환경으로 띄워놓는 거였어요. 따라서 저와같이 html
의 형태로 만들어야 하실 분들은 이 플러그인이 반드시 필요하답니다.
template
html
을 지정하면 돼요! 대부분이 index.html
이겠지만요!hash
빌드를 한 다음에, 이전에 했던 결과물이 남아 있으면 딱히 좋을 게 없죠? 이를 처리해주는 고마운 친구에요~~
css
도 결국 번들되면, 하나의 파일로 남는데요!
그렇게 되면 큰 파일을 다운로드 받기가 꽤나 부담일 수 있어요.
차라리 일단 번들하되, 역할에 따라 css파일을 잘게 나눠서 속도를 높이자!는 취지에서 설정한 플러그인입니다!
네, 결과적으로 잘 되나 볼까요?!
네, 성공했읍니다!!!
솔직히 이 글이 제가 지금 프로젝트하면서 급하게 쓴 거라, 헷갈릴 수 있는데요!
만약 처음이시라면 꼭 저 5가지만 살~짝씩만 공부하셔도, 무난히 가능할 거에요!
결국 이 친구들이 핵심이고, 나머지는 더욱 설정해준다! 라고 생각하시면 되겠습니다.
그래도 헷갈리면, 우리가
map
을 쓸 때, 3번째 인자가 있음에도 쓰지 않죠?!
결국 디테일한 설정들은 취사선택이고,
저 5가지 애들이map
메서드에서key
와index
번호에 대한 매개변수 정도의 중요한 애들이라고 보면 돼요!
그렇다고, 나머지 친구들을 과소평가하는 건 절대 금물!! ❌❌
그럼, 다들 즐거운 프로젝트하세유!!