해당 포스팅은 실전 리액트 프로그래밍 (리액트 훅부터 Next.js까지)-이재승의 '7장. 바벨과 웹팩 자세히 들여다보기' 를 학습하며 작성했습니다.
플러그인은 로더보다 강력하다. 로더는 특정 모듈에 대한 처리만 담당하지만, 플로그인은 웹팩이 실행되는 전체 과정에 개입한다.
mkdir webpack-plugin
cd .\webpack-plugin\
npm init -y
npm install webpack webpack-cli
루트에 src 폴더를 만들고 그 밑에 index.js파일을 만들자.
import React from 'react'
import ReactDOM from 'react-dom'
function App(){
return(
<div className="container">
<h3 className="title">안녕하세요 웹팩 플로그인 예제입니다.</h3>
<p>html-webpack-plugin을 사용합니다.</p>
</div>
)
}
ReactDOM.render(<App/>, document.getElementById('root'));
npm install babel-loader @babel/core @babel/preset-react react react-dom
프로젝트 루트에 webpack.confog.js 파일을 만들고 babel-loader를 사용하도록 설정한다.
// load babel load
const path = require("path");
module.exports = {
entry: {
main: "./src/index.js",
},
output: {
filename: "[name].[chunkhash].js",
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.js$/, //any js files
use: {
loader: "babel-loader",
options:{
presets: ['@babel/preset-react'],
}
},
},
],
},
mode:'production'
};
chunkhash를 사용하면 파일의 내용이 수정될 때마다 파일 이름이 변경되도록 할 수 있다.
babel.config.js를 작성하지 않아도 module > rules > use> options 에서 직접 바벨 설정을 할 수 있다
웹팩에서 실행해서 나오는 결과물을 확인하기 위해서는 이전처럼([front-backend 분리] 로더 사용하기) 직접 html 파일을 수동으로 작성해야 한다. 위에서 chunkhash 옵션을 설정했기 때문에 파일의 내용이 변경될 때마다 html 파일의 내용도 수정해야한다. 이러한 작업을 자동으로 하는 플로그인이 'html-webpack-plugin' 이다.
npm install clean-webpack-plugin html-webpack-plugin
// load babel load
const path = require("path");
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); //추가
const HtmlWebpackPlugin = require('html-webpack-plugin') //추가
module.exports = {
entry: {
main: "./src/index.js",
},
output: {
filename: "[name].[chunkhash].js",
path: path.resolve(__dirname, 'dist'),
},
plugins:[ //추가
new CleanWebpackPlugin(), // 웹팩 실행시마다 dist 폴더 정리
new HtmlWebpackPlugin({template: './template/index.html'})
//index.html 자동 생성되도록 template 옵션 설정0000000000
],
module: {
rules: [
{
test: /\.js$/, //any js files
use: {
loader: "babel-loader",
options:{
presets: ['@babel/preset-react'],
}
},
},
],
},
mode:'production'
};
[추가한 내용 ]
const CleanWebpackPlugin = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins:[
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({template: './template/index.html'})
],
프로젝트 루트에 template 폴더를 만들고, 그 밑에 index.html 파일을 만들어보자.
html-webpack-plugin이 생성하는 HTML에 포함시킬 내용을 index.html 파일에 추가한다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>웹팩 플러그인 예제</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
npx webpack
./dist/main.6af761bb7fd041a69456.js 파일 생성
./dist/index.html 파일 생성
<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>웹팩 플러그인 예제</title><script defer="defer" src="main.6af761bb7fd041a69456.js"></script></head><body><div id="root"></div></body></html>
자동으로 index.html header에
DefinePlugin은 모듈 내부에 있는 문자열을 대체해 준다. 웹팩에 내장된 플러그인이기 때문에 별도 설치할 필요 없다.
index.js
import React from 'react'
import ReactDOM from 'react-dom'
function App(){
return(
<div className="container">
<h3 className="title">안녕하세요 웹팩 플로그인 예제입니다.</h3>
<p>html-webpack-plugin을 사용합니다.</p>
<p>{`앱 버전은 ${APP_VERSION}입니다.`}</p>
<p>{`${NUM} * ${NUM} = ${NUM*NUM}.`}</p>
</div>
)
}
ReactDOM.render(<App/>, document.getElementById('root'));
webpack.config.js
//...
plugins:[
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({template: './template/index.html'}),
new webpack.DefinePlugin({
APP_VERSION:'"1.2.3"',
NUM: '5',
})
],
//...
결과를 확인해보면
아래와 같은 자주 사용되는 모듈을 미리 등록하여 매번 작성하지 않게 해준다.
import React from 'react'
import $ from 'jquery'
웹팩에 내장된 플러그인이기 때문에 별도 설치할 필요 없다.
// ...
plugins:[
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({template: './template/index.html'}),
new webpack.DefinePlugin({
APP_VERSION:'"1.2.3"',
NUM: '5',
}),
new webpack.ProvidePlugin({
React: 'react',
$:'jquery'
})
],
//...