# Webpack 5 Notes
###### tags: `Webpack` `Web Technology` `Software Packaging` `App` `Optimization`
Establish an overall understanding of webpack 5 and understand how to use its functionalities, loaders, plugins, & optimization.

ref:
- [[筆記][React]從零到一的webpack開發環境(1)-安裝執行篇 - 神Q超人- iThome 系列文](https://ithelp.ithome.com.tw/articles/10200329)
- [Webpack Tutorial 繁體中文 Gitbook - neighborhood999](https://neighborhood999.github.io/webpack-tutorial-gitbook/)
- [Guide to Webpack 5 - stackabuse](https://stackabuse.com/guide-to-webpack-5/)
- [webpack documentation - webpack.org](https://webpack.js.org/concepts/)
- [webpack 進階學習](https://www.cnblogs.com/skychx/tag/Webpack/)
## Preset Webpack
#### npm install
```bash
npm i -g webpack webpack-cli
#npm i -D webpack webpack-cli
```
#### command
```bash
webpack
webpack --watch # auto build after save files
```
## webpack config options
#### [Example] webpack.config.js
```javascript
const path = require("path")
module.exports = {
mode: "development", // development: error debug ; production: chunks, optimization, minified ...
entry: {
home: path.resolve(__dirname, "src/assets/js/home.js"),
},
output: {
path: path.resolve(__dirname, "dst"),
filename: "[contenthash].js", // [name] [contenthash]
clean: true, // remove old bundle.js before build
assetModuleFilename: "[name][ext]" // remain intact name for output other files
},
plugins: [
new HtmlWebpackPlugin({
title: "Home | coffcat.com",
filename: "index.html",
template: path.resolve(__dirname, "src/_template.html"),
}),
],
module: {
rules: [{ test: /\.css$/, use: ["style-loader", "css-loader"] }],
},
}
```
## plugins
1. npm install -D
2. use plugin as an Object in webpack.config
### html webpack plugin
from src-template.html to dst-index.html
#### webpack.config.js
```javascript
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
...,
plugins: [
...,
new HtmlWebpackPlugin({
title: "Home | coffcat.com",
topic: "AAAAAAA",
filename: "index.html",
template: path.resolve(__dirname, "src/_template.html"),
}),
]
}
```
#### src-template.html
```jsx
<!DOCTYPE html>
<html lang="en">
<head>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<h1><%= htmlWebpackPlugin.options.topic %></h1>
</body>
</html>
```
### copy path to dst plugin
copy path to output
#### webpack.config.js
```javascript
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
...,
plugins: [
...,
new CopyWebpackPlugin([
{ from: path.resolve(__dirname,"src/img"), to: "img" }
])
]
}
```
### css extract to file plugin
#### webpack.config.js
```javascript
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
...,
plugins: [
...,
new MiniCssExtractPlugin(),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"]
},
]
}
}
```
## loaders
import other resources into webpack entry.js
1. npm install -D
2. use loaders by provide "custom-loader" in *module.rules*
### css loader
#### npm install
```bash
npm i -D style-loader css-loader
```
#### webpack.config.js
```javascript
module.exports = {
...,
module: {
rules: [
...,
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
],
}
}
```
#### index-webpack.js
```javascript
import "../css/main.css"
import styles from "../css/utils.css"
console.log(styles.loading);
...
```
### scss loader
#### npm install
```bash
npm i -D node-sass sass-loader
```
#### webpack.config.js
```javascript
module.exports = {
...,
module: {
rules: [
...,
{
test: /\.s[ac]ss$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
],
}
}
```
### tailwind css loader (with postcss)
#### npm install
```bash
npm i -D babel-loader @babel/core @babel/preset-env
style-loader css-loader
postcss postcss-loader postcss-preset-env
```
#### webpack.config.js
```javascript
module.exports = {
...,
module: {
rules: [
...,
{
test: /\.css$/,
include: path.resolve(__dirname, 'src'),
use: ['style-loader', 'css-loader', 'postcss-loader'],
},
],
}
}
```
#### tailwind.config.js
```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{js,jsx}"],
mode: "jit",
theme: {
extend: {
colors: {
"home": "#050816",
},
boxShadow: {
"card": "0px 35px 120px -15px #211e35",
},
screens: {
"xs": "450px",
},
backgroundImage: {
"bg": "url(img/bg.png)",
},
},
},
plugins: [],
};
```
#### postcss.config.js
```javascript
const tailwindcss = require("tailwindcss");
module.exports = {
plugins: [
"postcss-preset-env",
tailwindcss
],
};
```
### babel loader (Ex. jsx syntax, ES6 modules syntax ...)
#### npm install
```bash
npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-react
# preset-env === preset-es2015
```
#### webpack.config.js
```javascript
module.exports = {
...,
module: {
rules: [
...,
// jsx
// transpile js(x) with webpack-babel-loader using @babel/core in npm-dev-dependecy
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
["@babel/preset-react", { "runtime": "automatic" }]
// runtime: "automatic" enables no requirement of importing React for every file
]
}
}
},
// ES6 modules to ES5
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
],
}
}
```
### html loader
for loading _template.html (or other html files), and let html utilized other loaders & plugins
#### webpack.config.js
```javascript
module.exports = {
...,
module: {
rules: [
...,
{
test: /\.(html)$/,
use: ['html-loader']
}
],
}
}
```
### files loader (Ex. jpeg, svg, webp ...)
for *webpack5*, use asset/resource instead of "file-loader" / "url-loader" (not compatible)
[Asset Modules - webpack.org](https://webpack.js.org/guides/asset-modules/)
#### webpack.config.js
```javascript
module.exports = {
...,
module: {
rules: [
...,
{
test: /\.(svg|ico|png|webp|jpg|gif|jpeg)$/,
type: "asset" // auto switch inline / resource (url) by default 8KB
// "asset/resource"
// "asset/inline"
}
],
}
}
```
## webpack dev tool
### hot reload server
#### npm install
```bash
npm i -g webpack-dev-server
#npm i -D webpack-dev-server
```
#### command
```bash
webpack serve
```
#### webpack.config.js
```javascript
module.exports = {
...,
devServer: {
port: 8080, // default = 8080
open: false, // open the browser when compilation development version once has done
hot: true, // hot module reloading (HMR)
allowedHosts: "all",
static: {
directory: OUTPUT_ROOT_PATH,
},
watchFiles: [ path.resolve(__dirname, 'src') ],
},
};
```
### devtools
devtools generate "source map" keeping track of where all content came from, and let browser know the potential errors locations.
#### webpack.config.js
```javascript
module.exports = {
...,
devtool: "inline-source-map",
};
```
### webpack bundle analyzer
generate pack origin & zip size analysis for bundle.js at *dst/report.html*
#### webpack.config.js
```javascript
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
module.exports = {
...,
plugins: [
...,
new BundleAnalyzerPlugin({ analyzerMode: "static" })
]
}
```