Logo Vincent
Back to all posts

Learn Webpack 5.x in One Article

Web
Learn Webpack 5.x in One Article

Preface

Web frontend development relies heavily on webpack.

As we all know, webpack has many complex configurations —

you could even have a dedicated “webpack configuration engineer.”

This article focuses on webpack core concepts

and commonly used configurations in business development,

aiming to teach you webpack usage and configuration in one article.

Common Documentation

webpack official website

webpack guides: Follow the documentation step by step

webpack concepts: Common webpack concepts

webpack configuration: Look up webpack configuration options

Tutorial Approach

To get up to speed quickly, instead of starting from concepts like other articles,

we’ll start directly from hands-on code. Practice code: https://github.com/insistime/webpack-guides

You can clone it locally:

git clone git@github.com:insistime/webpack-guides.git ./webpack-guides

The workflow is as follows:

  1. Checkout the corresponding tag, e.g., tag 0.0.4
git checkout 0.0.4
  1. Install dependencies (different code requires different dependencies)
npm i
  1. Read the code alongside the explanations

  2. Practice on your own

Installation

webpack is a build tool,

so install it as a devDependency:

npm i -D webpack webpack-cli

After installation:

  "devDependencies": {
    "webpack": "^5.59.0",
    "webpack-cli": "^4.9.1"
  },

Code: https://github.com/insistime/webpack-guides/tree/0.0.4

Entry and Output

entry: The entry point. You can configure single or multiple entries.

output: The output configuration for filename, path, etc.

In this example,

the entry is the index.js file under the src folder,

and the output goes to main.js in the dist folder:

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

Code: https://github.com/insistime/webpack-guides/tree/0.0.4

Configuration File

webpack usage generally relies on a configuration file.

Create a webpack.config.js file

with the entry and output example content shown above.

Code: https://github.com/insistime/webpack-guides/tree/0.0.4

Build Script

After installing webpack and preparing the configuration file, how do you build?

Add a script in package.json:

  "scripts": {
    "build": "webpack --config webpack.config.js"
  },

Then run:

npm run build

Result:

Code: https://github.com/insistime/webpack-guides/tree/0.0.4

Testing the Result

Manually create an HTML file to test. You can open it by double-clicking:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Getting Started</title>
  </head>
  <body>
    <script src="main.js"></script>
  </body>
</html>

Result after opening:

Code: https://github.com/insistime/webpack-guides/tree/0.0.4

Checkpoint

So far, we’ve learned:

  1. webpack - Installation

  2. webpack - Configuration file

  3. webpack - Build

  4. webpack - entry

  5. webpack - output

Code: https://github.com/insistime/webpack-guides/tree/0.0.4

File structure:

Module

webpack’s philosophy is that all resources used in web frontend development are modules.

So through webpack configuration,

you can load and use almost any resource in frontend code.

For example, here JS imports CSS, PNG, XML, and other resources:

import _ from 'lodash';
import './style.css';
import Icon from './icon.png';

import Data from './data.xml';
import Notes from './data.csv';

import toml from './data.toml';
import yaml from './data.yaml';
import json from './data.json5';

console.log(toml.title); // output `TOML Example`
console.log(toml.owner.name); // output `Tom Preston-Werner`

console.log(yaml.title); // output `YAML Example`
console.log(yaml.owner.name); // output `Tom Preston-Werner`

console.log(json.title); // output `JSON5 Example`
console.log(json.owner.name); // output `Tom Preston-Werner`

function component() {
  const element = document.createElement('div');

  // Lodash, now imported by this script
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');
  element.classList.add('hello');

  // Add the image to our existing div.
  const myIcon = new Image();
  myIcon.src = Icon;

  element.appendChild(myIcon);

  console.log(Data);
  console.log(Notes);

  return element;
}

document.body.appendChild(component());

Code: https://github.com/insistime/webpack-guides/tree/0.0.9

Loader

Loading resources mostly requires loaders.

For example, loading CSS files requires style-loader and css-loader:

      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader'],
      },

Loaders are not built into webpack,

so you need to install the corresponding loader before using it:

npm i -D style-loader css-loader

This is just the beginning —

you’ll find that using webpack requires installing many dependencies.

Code: https://github.com/insistime/webpack-guides/tree/0.0.9

Asset

webpack also noticed the problem of too many dependencies,

so it built some of the most common ones into webpack itself.

In webpack 5.x, some loaders are built in.

For example, the old file-loader, url-loader, and raw-loader

now correspond to asset/resource, asset/inline, and assets/source in webpack 5.x.

So in webpack 5.x, the configuration for images and fonts is:

      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource',
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource',
      },

Code: https://github.com/insistime/webpack-guides/tree/0.0.9

Checkpoint

So far, we’ve learned:

  1. webpack - module

  2. webpack - loader

  3. webpack - asset

Code: https://github.com/insistime/webpack-guides/tree/0.0.9

File structure:

Plugin

In the first checkpoint above, the HTML file was created manually.

That process is cumbersome.

webpack’s plugin mechanism solves this problem nicely.

The plugin we’ll cover here is html-webpack-plugin.

Yes, you still need to install it before using it:

npm i -D html-webpack-plugin

Then configure it:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: {
    index: './src/index.js',
    print: './src/print.js',
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Output Management',
    }),
  ],
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
  },
};

After building, you’ll find that an HTML file is automatically generated in the dist folder:

Here’s a brief comparison of loader and plugin:

loader: A tool for loading resources into webpack.

plugin: A tool for extending webpack’s capabilities.

These capabilities are generally non-core features.

Code: https://github.com/insistime/webpack-guides/tree/0.1.3

Revisiting Entry and Output

You’ll notice the example above generated two JS files,

and the JS filenames were also changed.

This relies on the entry change:

  entry: {
    index: './src/index.js',
    print: './src/print.js',
  },

And the output change:

  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
  },

You can see that entry now has two entry points.

The output filename uses [name] to represent the original filename.

The output adds a clean property, which cleans the dist folder before each build.

Code: https://github.com/insistime/webpack-guides/tree/0.1.3

Checkpoint

So far, we’ve learned:

  1. webpack - plugin

  2. webpack - entry, multiple entries

  3. webpack - output, [name]

  4. webpack - output, clean

Code: https://github.com/insistime/webpack-guides/tree/0.1.3

Mode

The code above builds without issues,

but there’s always a warning like this:

The warning is clear — mode is not set.

webpack’s mode tells webpack which mode to use,

such as development or production. See: https://webpack.js.org/configuration/mode/#mode-development

The differences are roughly whether to minify, build to memory vs. files, etc.

Set a mode like this:

  mode: 'development',

Build again, and the warning is gone:

Code: https://github.com/insistime/webpack-guides/tree/0.1.8

Watch

webpack has a built-in watch feature — no extra dependencies needed.

Add a watch script:

"watch": "webpack --config webpack.config.js --watch"

Run the watch script:

Modify files under src, and webpack will automatically rebuild:

So watch monitors file changes and automatically rebuilds.

Code: https://github.com/insistime/webpack-guides/tree/0.1.8

Watch in Practice

At this point you’ll notice a problem — we’ve been opening HTML files by double-clicking,

meaning we preview HTML via the file protocol directly in the browser,

not through an HTTP server.

In practice, you need a server to serve the HTML files.

Here we’ll temporarily use pm2 as a substitute.

For pm2 usage, see this article: Learn pm2 in One Article

Install pm2:

npm i -g pm2

Run the HTML files:

cd dist
pm2 serve .

pm2 will run a server serving the contents of the dist folder:

You can see it uses port 8080,

so you can access it locally via port 8080:

The watch workflow in practice:

  1. npm run watch

  2. pm2 serves the dist folder

  3. Access port 8080 to see the result

  4. Modify files under src

  5. Refresh the page to see the effect

Code: https://github.com/insistime/webpack-guides/tree/0.1.8

devServer

Do you really need to set up pm2 alongside webpack?

Actually, webpack already provides a development server for you.

Install the dependency:

npm i -D webpack-dev-server

Add the configuration:

  devServer: {
    static: './dist',
  },

Add the script:

    "start": "webpack serve --open",

Run devServer:

What does webpack-dev-server do?

  1. Build files

  2. Start a server to serve files from dist

  3. Open the browser

  4. Watch for file changes

Essentially, webpack-dev-server is watch + pm2 combined.

See: https://www.npmjs.com/package/webpack-dev-server

The development workflow now becomes:

  1. npm run start

  2. Access port 8080 to see the result

  3. Modify files under src

  4. Refresh the page to see the effect

Code: https://github.com/insistime/webpack-guides/tree/0.1.8

Checkpoint

So far, we’ve learned:

  1. webpack - mode

  2. webpack - watch

  3. webpack - devServer

Code: https://github.com/insistime/webpack-guides/tree/0.1.8

Code Splitting

If two JS files both import a common JS library, such as lodash:

The current build result looks like this:

Both files are large because they both contain the lodash library.

Code: https://github.com/insistime/webpack-guides/tree/0.1.9

How do you extract this common library? Modify the configuration:

  optimization: {
    splitChunks: {
      chunks: 'all',
    },
  },

Run again, and lodash has been extracted:

Code: https://github.com/insistime/webpack-guides/tree/0.2.0

Checkpoint

So far, we’ve learned:

  1. webpack - code splitting

Code: https://github.com/insistime/webpack-guides/tree/0.2.0

Basics Summary

webpack has more concepts beyond this,

such as caching, tree shaking, production, etc.

But those are optimization topics. The basics are now covered.

To summarize, we’ve learned:

  1. webpack - Installation

  2. webpack - Configuration file

  3. webpack - Build

  4. webpack - entry

  5. webpack - output

  6. webpack - module

  7. webpack - loader

  8. webpack - asset

  9. webpack - plugin

  10. webpack - mode

  11. webpack - watch

  12. webpack - devServer

  13. webpack - code splitting

React

With webpack basics complete, there are generally two directions going forward:

  1. Optimize webpack configuration for production environments

  2. Use webpack in development practice, e.g., how to use webpack with a React project

Here’s a simple React code example for demonstration:

const React = require('react');
const ReactDOM = require('react-dom');

ReactDOM.render(<h1>Helloo, world!</h1>, document.getElementById('root'));

Install dependencies:

-- react
npm i react react-dom

-- babel
npm i -D babel-loader @babel/core @babel/preset-react

Modify configuration:

  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: { presets: ["@babel/preset-react"] }
      },
    ],
  },

Build successful:

Code: https://github.com/insistime/webpack-guides/tree/1.0.3

Sass

Besides React, CSS frameworks are also essential.

Here we use Sass as an example to demonstrate webpack configuration.

The code imports an additional SCSS file:

Install dependencies:

npm i -D sass sass-loader css-loader style-loader

Modify configuration:

      {
        test: /\.scss$/i,
        use: [
          "style-loader",
          "css-loader",
          "sass-loader",
        ],
      },

Build successful:

Code: https://github.com/insistime/webpack-guides/tree/1.0.4

Checkpoint

So far, we’ve learned:

  1. webpack - React configuration

  2. webpack - Sass configuration

The Problem

At this point, you’ll notice a problem.

In development practice, webpack depends on many other npm packages, like this:

  "devDependencies": {
    "@babel/core": "^7.17.5",
    "@babel/preset-react": "^7.16.7",
    "babel-loader": "^8.2.3",
    "css-loader": "^6.7.1",
    "html-webpack-plugin": "^5.5.0",
    "imports-loader": "^3.1.1",
    "sass": "^1.49.9",
    "sass-loader": "^12.6.0",
    "style-loader": "^3.3.1",
    "webpack": "^5.65.0",
    "webpack-cli": "^4.9.1",
    "webpack-dev-server": "^4.6.0",
    "webpack-merge": "^5.8.0"
  },

Imagine you’re maintaining 5 such projects.

That means 5 copies of similar dependencies.

Take html-webpack-plugin for example —

it could exist in all 5 projects,

and you’d need to keep it updated to the latest version.

That’s quite painful.

qiao-webpack

A wrapper npm package was created for this. Feel free to use it: https://qiao-webpack.vincentqiao.com/#/

Summary

  1. webpack - Installation

  2. webpack - Configuration file

  3. webpack - Build

  4. webpack - entry

  5. webpack - output

  6. webpack - module

  7. webpack - loader

  8. webpack - asset

  9. webpack - plugin

  10. webpack - mode

  11. webpack - watch

  12. webpack - devServer

  13. webpack - code splitting

  14. webpack - React configuration

  15. webpack - Sass configuration

  16. webpack - Out-of-the-box tool: qiao-webpack, https://qiao-webpack.vincentqiao.com/#/

  17. webpack - Guides and blog column: https://blog.csdn.net/uikoo9/category_11471307.html

© 2026 Vincent. All rights reserved.