---
# System prepended metadata

title: Webpack 5 Notes
tags: [Webpack, Web Technology, Optimization, App, Software Packaging]

---

# 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.

![](https://hackmd.io/_uploads/ryEQ4ttWT.jpg)

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" })
    ]
}
```