Webpack is a static module wrapper for a modern JavaScript application. When WebPack processes an application, it recursively builds a dependency graph containing each module required by the application, and then packages these modules into one or more bundles.

There are four core concepts:

  • Entry: The starting point indicates which module WebPack should use to start building its internal dependency graph, which defaults to./ SRC /index.js. You can configure the entry property to specify the entry.

  • Output: Tells WebPack where to export the bundles created and how to name them. The default output is./dist/main.js, and output can be specified.

  • Loader: Loader gives WebPack the ability to process other types of files and convert them into valid modules for their use and to be added to dependency diagrams.

  • Plugin: Loader is used to transform certain types of modules, while plug-ins can be used to perform a wider range of tasks, including packaging optimization, resource management, and injection of environment variables. The plugins can be imported by require and then added to the plugins array.

Project initialization

Run NPM init -y to initialize the project, install webpack, webapck-cli:

npm install webpack webpack-cli -D
Copy the code

The installed version is:

"Webpack" : "^ 5.64.2", "webpack - cli" : "^ 4.9.1." "Copy the code

Create a new SRC /idnex.js file:

class Animal {
    constructor(name) {
        this.name = name;
    }
    getName() {
        return this.name; }}const dog = new Animal('dog');
Copy the code

From the command line, run NPX webpack –mode=development to see that a dist/main.js file has been added to the root directory. Used here are webapck default configuration, in node_modules/webpack/lib/WebpackOptionsDefaulter. Have a look at the detail in the js, In node_modules/webpack/lib/config/defaults. Js

F(output, "path", () => path.join(process.cwd(), "dist"));
Copy the code

We can set our own import and export configuration, customize the packaged import file and export file:

Create a new webpack.config.js file:

const path = require('path');

module.exports = {
  entry:'./src/index.js'.output: {
    path: path.resolve(__dirname, 'dist'), // Must be an absolute path
    filename: 'bundle.js',}}Copy the code

NPM run build is usually used for project packaging. Now we need to add configuration to the package.json script:

"build": "cross-env NODE_ENV=production webpack",
"devBuild": "cross-env NODE_ENV=development webpack"
Copy the code

The complete webpack.config.js is as follows:

const path = require('path'); const isDev = process.env.NODE_ENV === 'development'; module.exports = { mode:isDev ? 'development' : 'production', devtool: isDev ? 'source-map' : false, entry:'./ SRC /index.js', output: {path: path.resolve(__dirname, 'dist'), // Must be absolute path filename: 'bundle.js', } }Copy the code

Now run NPM run build or NPM run devBuild to complete the package, generating a package file under dist/build.js.

The foundation of the project has been set up. Now let’s do some interesting small cases.

The basic case

Translate JS to a lower version

The previously packaged code is ES6 code, and to translate ES6 code into ES5 code, you need to use babel-Loader and its dependencies.

npm install babel-loader -D
npm install @babel/core @babel/preset-env @babel/plugin-transform-runtime -D
npm install @babel/runtime @babel/runtime-corejs3
Copy the code

Loader has two attributes:

  1. testProperty to identify which files will be converted.
  2. useProperty that defines which loader should be used during the conversion.

There are two ways to use loader:

  • Configuration mode (recommended) : Onwebpack.config.jsSpecifies the loader in the file
  • Inline mode: in eachimportStatement displays the specified loader

Add module.rules to webpack.config.js:

rules: [
	{
        test: /\.jsx? $/,
        use: ['babel-loader'].exclude: /node_modules/ // Exclude the node_modules directory}]Copy the code

Also configure a. Babelrc file in the root directory:

{
    "presets": ["@babel/preset-env"]."plugins": [["@babel/plugin-transform-runtime",
            {
                "corejs": 3}}]]Copy the code

Run NPM run devBuild from the command line and you can see that the ES6 code has been translated.

View the page in your browser

You can dynamically display the page content based on the configuration file.

Install the required plug-ins:

"Webpack - dev - server" : "^ 4.5.0" "HTML - webpack - plugin" : "^ 5.5.0",Copy the code

Create a new public/index.html and public/config.js file in the root directory:

module.exports = {
    dog: {
        template: {
            hair: 'red'.name:'jack'}},cat: {
        template: {
            hair: 'black'.name:'Jerry'}}}Copy the code
<! DOCTYPEhtml>
<html>
<head>
	<title><%= (htmlWebpackPlugin.options.config.name) %></title>
	<meta charset="utf-8">
</head>
<body>
    <div><%= (htmlWebpackPlugin.options.config.hair) %></div>
    <div class="color">hello world</div>
    
</script>
</body>
</html>
Copy the code

Add script to package.json:

"dev": "cross-env NODE_ENV=development webpack-dev-server"
Copy the code

Add a plugin to webpack.config.js:

const HtmlWebpackPlugin = require('html-webpack-plugin'); . Plugins: [new HtmlWebpackPlugin({template: './public/index.html', filename: 'index.html', // config.template }) ],Copy the code

Run NPM run dev to see the contents of the Dog template at http://localhost:8080/.

Working with style files

Webpack uses loader to process CSS. First install dependencies:

npm install style-loader less-loader css-loader postcss-loader autoprefixer less -D
Copy the code

Add to relus:

{
      test: /\.(le|c)ss$/,
      use: ['style-loader', 'css-loader', {
          loader: 'postcss-loader',
          options: {
              plugins: function () {
                  return [
                      require('autoprefixer')()
                  ]
              }
          }
        }, 'less-loader'],
        exclude: /node_modules/
    }
Copy the code

New SRC/index. CSS:

.color{
    color:red;
}
Copy the code

Webpackage 5.0 is not compatible with loader of higher version. It is successfully packaged after downgrade.

"Autoprefixer" : "^ 9.0.0", "postcss - loader" : "^ 3.0.0", //https://github.com/laravel-mix/laravel-mix/issues/2471 //https://stackoverflow.com/questions/64057023/error-postcss-plugin-autoprefixer-requires-postcss-8-update-postcss-or-do wngraCopy the code

You can already see the Page’s Hello World turning red.

The image processing

You can use url-loader to process local resources.

Configure loader in rules:

{
        test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
                limit: 10240, //10K
                esModule: false
            }
          }
        ],
        exclude: /node_modules/
      }
Copy the code

Add images to index.css:

.img{ width:100vh; height: 100px; border:1px solid red; background:url('.. /pka1.png'); }Copy the code

You can now successfully see the introduced image on the page.

Static resource copy

When you need to use existing local files that do not need webpack compilation, you can use the copy-webpack-plugin instead of manually copying to the build directory (dist).

The plug-in takes two parameters:

  • Patterns, {Array < String | Object >}, related patterns of a specified file for the plug-in.
    • From Specifies the path to copy the file
    • To output path
    • How does Content decide to interpret the path from
    • ToType determines the options to dir- directory, file- file, and template- template
    • GlobOptions, which allows you to configure the Glob pattern matching library used by the plug-in
  • Options, {Object}, specify plug-in options

Create a new file public/js/color.js’ ‘public/js/filter.js and:

Console. log(' Here is the JS file to import ')Copy the code
Console. log(' This is the JS file to filter ')Copy the code

Add configuration to webpack.config.js:

const CopyWebpackPlugin = require('copy-webpack-plugin'); . // Plugins add new CopyWebpackPlugin({patterns:[{from: 'public/js/*.js', to: path.resolve(__dirname, 'dist', 'js'), toType:'dir', globOptions:{ ignore: ["**/filter.*"], } }, })Copy the code

Run NPM run devBuild and you can see that there is a copy of the js folder in the dist directory with only color.js in it.

Package the CSS file separately

If you need to package CSS files separately, use the mini-CSS-extract-plugin.

This plug-in extracts CSS into a separate file. It creates a CSS file for each JS file that contains CSS. It supports loading CSS and SourceMap on demand.

It builds on new WebPack V5 features and requires WebPack 5 to work.

Common parameters:

  • Filename Determines the name of each output CSS file
  • ChunkFilename determines the name of the non-entry block

NPM install mini-css-extract-plugin -d,

Change the webapck. Config. Js:

const MiniCssExtractPlugin = require('mini-css-extract-plugin'); . new MiniCssExtractPlugin({ filename: 'css/[name].css' })Copy the code

And use MiniCssExtractPlugin. Replace style – loader loader.

Run nom Run devBuild and you’ll see a new CSS file in the dist directory.

According to the need to load

Most of the time we don’t need to load all the JS files at once, but should load the required code at different stages. Webpack has a powerful built-in feature for splitting code to load on demand.

For example, the VUE documentation states that routing lazy loading can be used to improve performance:

JavaScript packages can become very large when packaged to build applications, affecting page loads. It would be much more efficient if we could split the components corresponding to different routes into different code blocks and then load the components only when the routes are accessed.

const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')
Copy the code
Hot update

Configure hot:true in devServer and then in webpack.config.js:

const webpack = require('webpack'); . / / in the plugins to add new plugin webpack. HotModuleReplacementPlugin (), / / hot update plug-inCopy the code

The code address