[Cute-Webpack] Introduction to Webpack4 (18 chapters)

Keywords: Javascript Webpack npm sass JSON

introduce

1. Background

Recently, we have been working with our department leaders on the research team (EFT - Front End Novice Village) to help the newcomers quickly understand and integrate into the company team, to help the zero-base newcomers learn and start-up front-end development, and to achieve the company's business development level.

This article is also part of the "EFT - Front-End Novice Village" to help new people get started with Webpack4, which is basic in content and of course can be used as a review material~~Share it with your little friends here!

2. Article Summary

I will introduce and practice from the most basic [project initialization], to [processing CSS / JS / pictures], to [hot update, packaging optimization], and so on.

The article is divided into 18 chapters, about the four most basic core concepts, I can sort out another article Four Core Concepts of Webpack4 Learn.

3. Catalogue of tutorials

I. Project Initialization

1. Initialize demo

New and enter folder leo:

mkdir leo
cd leo

Then install webpack and webpack-cli locally (separate after Webpack 4.0):

npm install webpack webpack-cli --save-dev

Initialize project structure:

+ ├─package.json
+ ├─dist          // Store final packaged file
+ │  └─index.html
+ ├─src           // Store development files such as entry files
+ │  └─index.js
+ ├─webpack.config.js  // Configuration file for webpack

Install lodash:

npm install lodash --save-dev

--save can be abbreviated as -S, --save-dev can be abbreviated as -D.

Develop index.js:

import _ from 'lodash';

function createElement(){
    let div = document.createElement('div');
    div.innerHTML = _.join(['my', 'name', 'is', 'leo'], '');
    return div;
}
document.body.appendChild(createElement());

Develop webpack.config.js:

const path = require('path');

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

2. Packaging tests

Start the first packaging task:

npx webpack

// Output:

Hash: 030b37b6b9a0b4344437
Version: webpack 4.39.1Time: 308ms
Built at: 2019-08-07 08:10:21
  Asset     Size  Chunks             Chunk Names
main.js  552 KiB    main  [emitted]  main
Entrypoint main = main.js
[./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {main} [built]
[./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {main} [built][./src/index.js] 225 bytes {main} [built]
    + 1 hidden module

After successful packaging, the generated files are saved in the dist directory.

Now import the packaged main.js in dist/index.html and open the browser test:

<script src="./main.js"></script>

2. webpack Processing CSS Module

In this section, we began to learn how to use webpack to work with css-related modules.

1. Modify Code

In the project src directory, create a new style folder and create a new index.css file:

  ├─package.json
  ├─dist          // Store final packaged file
  │  └─index.html
  ├─src           // Store development files such as entry files
  │  ├─index.js
+ │  └─style
+ │     └─index.css
  ├─webpack.config.js  // Configuration file for webpack

Next, in the new element method of index.js, add class as box so that the new element has the class attribute of box:

// src/index.js

import _ from 'lodash';
import './style/index.css';// Introducing style files

function createElement(){
  let div = document.createElement('div');
  div.innerHTML = _.join(['my', 'name', 'is', 'leo'], '');
+ div.className = 'box';
  return div;
}
document.body.appendChild(createElement());

Then the index.css file is box:

// src/style/index.css

.box{
    color: red;
}

Be careful:

Import'. /style/index.css'is used here; importing our style file does not resolve usage, so we need to use the third-party loader plug-in in the webpack, where we use:

  • css-loader: Used to process css files so that they can be introduced in js files;
  • style-loader: used to inject css files into the <style>tag in index.html;

2. Install Configuration Plug-ins

Install plug-ins:

npm install --save-dev style-loader css-loader

Add a loader configuration for css resolution to webpack.config.js:

// webpack.config.js

module: {
  rules: [
    {
      test: /\.css$/,
      use: ["style-loader", "css-loader"]
    }
  ]
}

Parameter description:

test: Module Suffix Name Required to Match
use: CorrespondingHandled loader Plugin Name(Processing order is right to left).

3. Packaging Test

npx webpack

// Output:

Hash: 28b3965aa1b6a0047536
Version: webpack 4.39.1
Time: 482msBuilt at: 2019-08-09 07:45:25  Asset     Size  Chunks             Chunk Names
main.js  565 KiB    main  [emitted]  main
Entrypoint main = main.js
[./node_modules/_css-loader@3.2.0@css-loader/dist/cjs.js!./src/style/index.css] 190 bytes {main} [built]
[./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {main} [built][./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {main} [built][./src/index.js] 303 bytes {main} [built]
[./src/style/index.css] 447 bytes {main} [built]
    + 3 hidden modules

You can now see that in index.html, the text has turned red and the css code has been added to the <style>tag.

3. Introduction and handling of sass in webpack module

In this section, we'll cover the modules in the webpack and how to work with sass files.

1. Introduction to the webpack module

The module described here refers to the module configuration in the webpack.config.js file, which determines how different types of modules in a project are handled.

As described in the previous section, use the style-loader and css-loader plug-ins to process CSS files.

The webpack module supports the following statements:

  • ES2015 import statement;
  • CommonJS require() statement;
  • AMD define and require statements;
  • The @import statement in the css/sass/less file;
  • Picture links in styles (url(...) or HTML files (<img src=...>);

It is recommended to use the ES2015 import method since this is the standard.

More parameter descriptions are available on the Chinese official website:
webpack Configuration Options

2. Common Modules

2.1 module.noParse

Type of value: RegExp | [RegExp] | function

Prevent webpack s from parsing files that match the criteria, ignore folders that should not contain calls to import, require, define, or any other import mechanism, and ignore libraries can improve build efficiency.

// webpack.config.js

module: {
  noParse: function(content){
    return /jquery|lodash/.test(content);
  }
}

2.2 module.rules

When a module is created, an array of rules matches the request.Use the corresponding loader for the corresponding module according to the rules, or modify the parser.

// webpack.config.js

module: {
  rules: [
    { test: /\.css$/, use: ['style-loader', 'css-loader']}
  ]
}
  • The module.rules parameters are:

Use: Specify a loader for module use, and you can pass in an array of strings in a right-to-left loading order.

  • The module.rules matching criteria are:

{test: Condition}: Matches a specific condition, is not required, supports a regular expression or an array of regular expressions;
{include: Condition}: Matches a specific condition, is not required, supports a string or an array of strings;
{exclude: Condition}: Excludes specific conditions, is not required, supports a string or an array of strings;
{and: [Condition]}: All conditions in the array must be matched;
{or: [Condition]}: Matches any condition in the array;
{not: [Condition]}: This condition must be excluded;

More parameter descriptions are available on the Chinese official website:
<Rule>

// webpack.config.js

module: {
  rules: [
    { 
      test: /\.css$/, 
      use: ['style-loader', 'css-loader'],
      include: [
        path.resolve(__dirname, "app/style.css"),
        path.resolve(__dirname, "vendor/style.css")
      ]
    }
  ]
}

3. Load Sass file

A plugin for sass-loader is required. Install it here first:

npm install sass-loader node-sass --save-dev

Add the leo.scss file in the src/style directory and add the following:

// leo.scss

$bg-color: #ee3;
.box{
    background-color: $bg-color;
}

Then introduce the leo.scss file in src/index.js:

// src/index.js
import './style/leo.scss';

Repackage the npx webpack and open dist/index.html to see that the background color has been added:

4. Add Shortcut Packaging Command

Commands like npx webpack need to be used frequently, and we can write them as commands for each use.

We add a command to the scripts of package.json, build, and later package by executing npm run build:

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

In -c webpack.config.js, -c is followed by the file name of the webpack configuration file, which is not written by default.

4. webpack opens SourceMap and adds CSS3 prefix

SourceMap was added to make it easy to debug styles in the project after packaging and locate them in the source file.

1. Open SourceMap

Both css-loader and sass-loader can enable sourceMap by setting options.

// webpack.config.js

rules: [
  {
    test: /\.(sc|c|sa)ss$/,
    use: [
      "style-loader", 
      {
        loader:"css-loader",
        options:{ sourceMap: true }
      },
      {
        loader:"sass-loader",
        options:{ sourceMap: true }
      },
    ]
  }
]

Re-package and look at the style of index.html, which is already positioned on the source file:

This makes it much easier for us to debug styles during development.

2. Add a CSS3 prefix to the style

Here we use PostCSS, a loader, which is a pre-processing tool for CSS. It can prefix the properties of CSS3, style format checking (stylelint), use the new features of CSS in advance, implement CSS modularization, and prevent CSS style conflicts.

First install PostCSS:

npm install postcss-loader autoprefixer --save-dev

There are also:

  • Poscss-cssnext allows us to use CSS4 styles, complete browser-partially compatible with autoprefixer, and support nested syntax.
  • precss is similar to scss syntax and can be used instead of scss if we just need to use nesting.
  • Poscss-import allows webpack s to listen for and compile when @import CSS files are in place.

More parameter descriptions are available on the Chinese official website:
<postcss-loader>

Start adding postcss-loader and setting autoprefixer:

// webpack.config.js

rules: [
  {
    test: /\.(sc|c|sa)ss$/,
    use: [
      "style-loader", 
      {
        loader:"css-loader",
        options:{ sourceMap: true }
      },
      {
        loader:"postcss-loader",
        options: {
          ident: "postcss",
          sourceMap: true,
          plugins: loader => [
            require('autoprefixer')(),
            // More configurations are available, such as postcss-cssnext mentioned above
            // require('postcss-cssnext')()
          ]
        }
      },
      {
        loader:"sass-loader",
        options:{ sourceMap: true }
      },
    ]
  }
]

You also need to add a judgment browser version to package.json:

// package.json

{
  //...
  "browserslist": [
    "> 1%", // Global browser usage is greater than 1%, the latest two versions are IE8+ browsers prefixed 
    "last 2 versions",
    "not ie <= 8"
  ]
}

For testing purposes, we modified the style of.box in src/style/leo.scss:

// src/style/leo.scss

.box{
    background-color: $bg-color;
    display: flex;
}

Then repackage to see that the prefix for the CSS3 property has been added:

5. Web pack extracts CSS into separate files

In previous studies, CSS style codes were written in the <style>tag of index.html, which makes it inconvenient to write more style codes later on.

So we need to package these styles into separate CSS files.

webpack4 started using the mini-css-extract-plugin plug-in, whereas in version 1-3 it used the extract-text-webpack-plugin.

Note: After extracting styles, you cannot inject them into html using style-loader.

Install plug-ins:

npm install mini-css-extract-plugin --save-dev

Introduce plug-ins:

// webpack.config.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

Then modify the rules, replace the style-loader with MiniCssExtractPlugin.loader, and add the plugins configuration item:

// webpack.config.js

module: {
  rules: [
    {
      test: /\.(sc|c|sa)ss$/,
      use: [
        MiniCssExtractPlugin.loader, 
        {
          loader:"css-loader",
          options:{ sourceMap: true }
        },
        {
          loader:"postcss-loader",
          options: {
            ident: "postcss",
            sourceMap: true,
            plugins: loader => [require('autoprefixer')()]
          }
        },
        {
          loader:"sass-loader",
          options:{ sourceMap: true }
        },
      ]
    }
  ]
},
plugins: [
  new MiniCssExtractPlugin({
    filename: '[name].css', // File name of final output
    chunkFilename: '[id].css'
  })
]

Then repackage, and you can see that there are more main.css files in our dist directory:

Since CSS is now extracted into separate files, we need to manually introduce main.css in dist/index.html:

// index.html

<link rel="stylesheet" href="main.css">

6. Web pack compression CSS and JS

To reduce the size of packaged packages, we often optimize by compressing CSS and JS files, using different plug-ins.

1. Compress CSS

Plug-ins that compress CSS using optimize-css-assets-webpack-plugin.

Install plug-ins:

npm install optimize-css-assets-webpack-plugin --save-dev

Use plug-ins:

// webpack.config.js

// ...omitted
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = {
  // ...omitted
  plugins: [
    // ...omitted
    new OptimizeCssAssetsPlugin({})
  ],
}

Repackaging, you can see that main.css has been compressed into a single line of code, that is, compressed successfully~

2. Compress JS

Plug-ins that compress JS using uglifyjs-webpack-plugin.

Install plug-ins:

npm install uglifyjs-webpack-plugin --save-dev

Introduce plug-ins:

// webpack.config.js

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

Use plug-ins:

// webpack.config.js
// ...omitted
module.exports = {
  // ...omitted
  plugins: [
    // ...omitted
    new OptimizeCssAssetsPlugin({}),
    new UglifyJsPlugin({
      cache: true, parallel: true, sourceMap: true
    })
  ],
}

The parameters of UglifyJsPlugin:

cache: When the JS does not change, it is not compressed;
Parallel: whether parallel compression is enabled;
SourceMap: whether to enable sourceMap;

Then repackage to see main.js, which has been compressed:

7. webpack adds hash value to file name

Since our packaged css and js files are static files, there is a caching problem, so we can add hash values to the file names to prevent caching.

1. Add hash value

Directly in webpack.config.js, add [hash] to the file name where you need to add a hash value:

// webpack.config.js

module.exports = {
  // ...omit the others
  output: {
    filename: 'main.[hash].js',
    path: path.resolve(__dirname, 'dist')
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[hash].css',
      chunkFilename: '[id].[hash].css'
    }),
  ],
}

When the configuration is complete, repackage and you can see that the file name contains a hash value:

2. Dynamic reference to packaged files

Since we previously added a hash value to the packaged file name, it would cause index.html to reference the file incorrectly, so we need to allow it to dynamically import the packaged file.

Here we use the HtmlWebpackPlugin plug-in, which injects packaged CSS or JS file references directly into the HTML template without having to manually modify each time.

Install plug-ins:

npm install html-webpack-plugin --save-dev

Introduce plug-ins:

// webpack.config.js

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

Use plug-ins:

// webpack.config.js

plugins: [
  new HtmlWebpackPlugin({
    title: "leo study!",   // Generated File Title
    filename: "main.html", // Final generated file name
    minify: { // compression option
      collapseWhitespace: true, // Remove spaces
      removeComments: true, // Remove Comments
      removeAttributeQuotes: true, // Remove Double Quotes
    }
  })
],

More information about html-webpack-plugin is available View Documentshttps://github.com/jantimon/h....

After packaging, you can see that there are more main.html files in the dist directory. After formatting, you can see that the packaged CSS files and JS files have been dynamically introduced:

8. webpack Cleanup Directory Plugin

Previously, each time we packaged, we generated a new file, and after adding hash values, there would be no duplication of file names, resulting in redundancy of old files.

To solve this problem, we need to empty the / dist directory before packaging each time.

Here we use the clean-webpack-plugin plugin.

Install plug-ins:

npm install clean-webpack-plugin --save-dev

Introduce plug-ins:

// webpack.config.js

const CleanWebpackPlugin = require('clean-webpack-plugin');

Use plug-ins:

// webpack.config.js

plugins: [
  new CleanWebpackPlugin()
],

The parameter cleanOnceBeforeBuildPatterns is a folder indicating that it needs to be cleared.

This way, before each packaging, we empty the / dist directory once before packaging.

More parameter descriptions are available on the Chinese official website:
<clean-webpack-plugin>

9. Processing and optimizing webpack pictures

1. Picture processing

Introduce pictures into the project:

// src/style/leo.scss

.box{
    background-color: $bg-color;
    display: flex;
    background: url('./../assets/logo.jpg')
}

At this time, if we pack it directly, we will make an error.

We need to use the file-loader plug-in to handle file import issues.

Install plug-ins:

npm install file-loader --save-dev

Use plug-ins:

// webpack.config.js

module: {
  {
    test: /\.(png|svg|jpg|jpeg|gif)$/,
    use: ["file-loader"]
  }]
},

After repackaging, we found that there is an additional file in the dist directory, such as 373e5e0e214390f8aa9e7abb4c7c635c.jpg name, which is the picture we packed.

2. Picture optimization

Further, we can compress and optimize pictures using the image-webpack-loader plug-in.

Install plug-ins:

npm install image-webpack-loader --save-dev

Use plug-ins:

// webpack.config.js

module: {
  {
    test: /\.(png|svg|jpg|jpeg|gif)$/,
    include: [path.resolve(__dirname, 'src/')],
    use: ["file-loader",{
        loader: "image-webpack-loader",
        options: {
          mozjpeg: { progressive: true, quality: 65 },
          optipng: { enabled: false },
          pngquant: { quality: '65-90', speed: 4 },
          gifsicle: { interlaced: false },
          webp: { quality: 75 }
        }
      },
    ]
  }]
},

More parameter descriptions are available on the Chinese official website:
<image-webpack-loader>

Re-packaging, we can see that before and after packaging, the pictures compressed a lot:

10. Web pack picture base64 and font handling

1. Picture base64 processing

The function of url-loader is similar to file-loader, which packages the file corresponding to the URL address into a database URL of base64 to improve the access efficiency.

Install plug-ins:

npm install url-loader --save-dev

Use plug-ins:

Note: The image-webpack-loader previously configured needs to be removed here and url-loader is used.

// webpack.config.js

module: {
  {
    test: /\.(png|svg|jpg|jpeg|gif)$/,
    include: [path.resolve(__dirname, 'src/')],
    use: [
      {
        loader: 'url-loader', // Convert pictures to base64 based on their size
          options: { limit: 10000 }, 
      },
      {
        loader: "image-webpack-loader",
        options: {
          mozjpeg: { progressive: true, quality: 65 },
          optipng: { enabled: false },
          pngquant: { quality: '65-90', speed: 4 },
          gifsicle: { interlaced: false },
          webp: { quality: 75 }
        }
      },
    ]
  }]
},

More parameter descriptions are available on the Chinese official website:
<url-loader>

2. Font handling

Font processing is the same as picture processing, except that we have different test values when configuring rules:

// webpack.config.js

module: {
  {
    test: /\.(woff|woff2|eot|ttf|otf)$/,
    include: [path.resolve(__dirname, 'src/')],
    use: [ 'file-loader' ]
  }
},

11. webpack Configuration Merge and Extract Public Configuration

There are many differences between development and production profiles, but some are the same. In order not to modify the configuration every time the environment is changed, we need to merge the profiles and extract the public configuration.

We used the webpack-merge tool to merge the two profiles.

Install plug-ins:

npm install webpack-merge --save-dev

We then adjusted the directory structure to make it easier for us to change the name of the original webpack.config.js file to webpack.commen.js and copy two identical files, one for webpack.prod.js and the other for webpack.dev.js.

  ├─package.json
  ├─dist
  ├─src
- ├─webpack.config.js
+ ├─webpack.common.js  // webpack public profile
+ ├─webpack.prod.js    // webpack production environment profile
+ ├─webpack.dev.js     // webpack development environment profile

Since our files are adjusted, in package.json, the packaging commands also need to be adjusted and the model mode is configured.

"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
- "build": "npx webpack -c webpack.config.js",
+ "build": "npx webpack -c webpack.dev.js --mode development",
+ "dist": "npx webpack -c webpack.prod.js --mode production"
},

1. Adjust webpack.common.js

Let's first adjust the webpack.common.js file to keep the generic configuration, not delete it, as follows:

// webpack.common.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  module: {
    noParse: function (content) {return /jquery|lodash/.test(content);},
    rules: [
    {
      test: /\.(png|svg|jpg|jpeg|gif)$/,
      include: [path.resolve(__dirname, 'src/')],
      use: [{
        loader: 'url-loader', // Convert pictures to base64 based on their size
        options: { limit: 10000 },
      },{
        loader: "image-webpack-loader",
        options: {
          mozjpeg: { progressive: true, quality: 65 },
          optipng: { enabled: false },
          pngquant: { quality: '65-90', speed: 4 },
          gifsicle: { interlaced: false },
          webp: { quality: 75 }
        }
      }]
    },{
      test: /\.(woff|woff2|eot|ttf|otf)$/,
      include: [path.resolve(__dirname, 'src/')],
      use: [ 'file-loader' ]
    }]
  },
  plugins: [
      new HtmlWebpackPlugin({
          title: "leo study!",
          filename: "main.html",
          template: path.resolve(__dirname, 'src/index.html'), 
          minify: {
              collapseWhitespace: true,
              removeComments: true,
              removeAttributeQuotes: true,
          }
      }),
      new CleanWebpackPlugin()
  ],
}

2. Install babel-loader

babel-loader is installed to convert ES6 and above JS code to ES5.

npm install babel-loader @babel/core @babel/preset-env --save-dev

Use plug-ins:

// webpack.common.js

rules: [
  // ...omit the others
  {
    test: /\.js$/,
    use: [{
      loader: 'babel-loader',
      options: {
        presets: ['@babel/preset-env']
      }
    }],
    exclude: /(node_modules|bower_components)/,
  }
]

More information about babel-loader is available View Documentshttps://webpack.js.org/loader....

3. Adjust webpack.dev.js

Here we need merge-webpack plug-ins for configuration consolidation:

// webpack.dev.js

const path = require('path');
const merge = require('webpack-merge');
const common = require('./webpack.common.js');

let devConfig = {
  mode: 'development',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [{
      test: /\.(sc|c|sa)ss$/,
      use: [
        'style-loader', {
          loader: "css-loader",
          options: { sourceMap: true }
        }, {
          loader: "postcss-loader",
          options: {
              ident: "postcss", sourceMap: true,
              plugins: loader => [ require('autoprefixer')() ]
          }
        }, {
          loader: "sass-loader",
          options: { sourceMap: true }
        }
      ]
    }]
  }
}
module.exports = merge(common, devConfig)

4. Adjust webpack.prod.js

For the same configuration of production environments, we also need merge-webpack plug-ins for configuration consolidation:

// webpack.prod.js

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const merge = require('webpack-merge');
const common = require('./webpack.common.js');

let prodConfig = {
  mode: 'production',
  output: {
    filename: 'main.[hash].js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [{
      test: /\.(sc|c|sa)ss$/,
      use: [
        MiniCssExtractPlugin.loader, {
          loader: "css-loader",
          options: { sourceMap: true }
        },  {
          loader: "postcss-loader",
          options: {
            ident: "postcss", sourceMap: true,
            plugins: loader => [ require('autoprefixer')() ]
          }
        }, {
          loader: "sass-loader",
          options: { sourceMap: true }
        }
      ]
    }]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[hash].css',
      chunkFilename: '[id].[hash].css'
    }),
    new OptimizeCssAssetsPlugin({}),
    new UglifyJsPlugin({
      cache: true, parallel: true, sourceMap: true
    }),
  ],
}
module.exports = merge(common, prodConfig)

12. webpack monitors sourceMap for automatic compilation and js enablement

1. Open sourceMap for js

When the webpack packages the source code, it is difficult to trace the location of errors and warnings in the source code.

If three source files are packaged into one bundle and one of the files has an error in code, the stack chase will point to the bundle.

For the convenience of locating errors, we use the inline-source-map option, taking care not to use it in production environments.

// webpack.dev.js

let devConfig = {
  // ...omit the others
+  devtool: 'inline-source-map'
}

2. Test sourceMap

To test for success, we'll add a log print to the src/index.js code on line 12.

// src/index.js

// ...omit the others
+ console.log(111)

Contrast the difference between before and after opening sourceMap:

3. Turn on monitoring automatic compilation

It's tiring to compile the code manually every time we finish modifying it.

To do this, we use the--watch command, which lets us compile automatically every time we save.

To do this, we need to add the--watch command to the package command in package.json:

// package.json

- "build": "npx webpack --config webpack.dev.js",
+ "build": "npx webpack --config webpack.dev.js --watch",

This is only for development environments, production environments are not required.

13. webpack Hot Updates

The previous section describes monitoring automatic compilation. When we save a file, it compiles automatically, but we still need to refresh the page manually to see the compiled results.

So in order to automatically compile and reload, we can use webpack-dev-server to start a simple web server and reload it in real time.

1. Turn on hot updates

Plug-in Installation:

npm install webpack-dev-server --save-dev

Use plug-ins:

// webpack.dev.js

const webpack = require('webpack');
const webpack = require('webpack');

let devConfig = {
  // ...omit the others
  devServer: {
    contentBase: path.join(__dirname, 'dist'), 
    compress: true,
    hot: true,
    overlay: true, 
    open:true,
    publicPath: '/',
    host: 'localhost',
    port: '1200'
 }
 plugins: [
    new webpack.NamedModulesPlugin(), // It's easier to see since (patch)
    new webpack.HotModuleReplacementPlugin() // Replace Plug-in
 ]
}

Start hot update:

npx webpack-dev-server --config webpack.dev.js

Common configurations:

contentBase: path.join(__dirname, 'dist'), //The directory where the pages loaded by the local server are located
clinetLogLevel: 'warning', // Possible values are none, error, warning or info (default)
hot:true,//Start the hot update replacement feature with the webpack.HotModuleReplacementPlugin plug-in
host:'0.0.0.0', // Start the host of the server
port:7000,      // Port number
compress:true,  // Enable gzip compression for all services
overlay: true,  // Show full screen coverage in browser
stats: "errors-only" ,// Show only errors in packages
open:true, // When Open is enabled, the dev server opens the browser.
proxy: {   // Set up proxy
    "/api": {
        target: "http://localhost:3000",
        pathRewrite: {"^/api" : ""}
    }
}

When we visit http://localhost:1200/main.html, we can see the page, modify the file, and the page will refresh at the same time.

2. Optimize commands

We can write npx webpack-dev-server --config webpack.dev.js to package.json as a command:

// package.json

"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "build": "npx webpack --config webpack.dev.js --watch",
  "dist": "npx webpack --config webpack.prod.js",
+ "watch": "npx webpack-dev-server --config webpack.dev.js"
},

14. webpack Setup Proxy Server and babel Conversion and Optimization

1. Set up a proxy server

Next to the previous section, set up a proxy server for the webpack:

// webpack.dev.js

let devConfig = {
  // ...omit the others
  devServer: {
    // ...omit the others
    proxy: { 
      "/api": { // Requests that start with'/api'will jump to the following target configuration
        target: "http://192.168.30.33:8080",
        pathRewrite: {
          "^api": "/mock/api"
        }
    }
 }
}

Finally, when we request the / api/getuser interface, it is forwarded to http://192.168.30.33:8080/mock/api.

2. babel conversion and optimization

Installation of the babel-loader plug-in was introduced in advance in [11, Configuration Consolidation and Extraction of Public Configurations for webpack].

Here's how babel-loader is optimized.

babel-loader can configure cacheDirectory to improve packaging efficiency:

  • cacheDirectory: The default value is false, which caches folders when built on and subsequently reads from the cache, which improves packaging efficiency.

15. webpack Opens Eslint

Install plug-ins:

npm install eslint eslint-loader --save-dev

You also need to install the eslint interpreter, check rules, and so on:

npm install babel-loader standard --save-dev

2. Add.eslintrc.js

Create.eslintrc.js in the project root directory, specifying eslint rules.

This configuration has a bit more to go to My gist replicationhttps://gist.github.com/pinga... .

3. Add.eslintignore

Create.eslintignore in the project root directory, specifying eslint to ignore files that are not checked, such as:

/dist/
/node_modules/

16. Web pack parsing module extension and alias

In the webpack configuration, we use resolve to configure how modules are resolved.

This is very important, for example, import from'lodash', which actually loads and parses the lodash.js file.

This configuration is used to set how loading and parsing occurs.

During the parsing process, we can configure:

1. resolve.alias

When we import some files, we need to write long paths, which makes the code more complex.

To do this, we can use resolve.alias to create an alias for import or require to make module introduction easier.

Use Configuration:

// webpack.common.js

module.exports = {
  entry: './src/index.js',
+ resolve: {
+   alias: {
+     '@' : path.resolve(__dirname, 'src/')
+   }
+ }
  // Omit Others
}

The meaning of the alias parameter:

Use @ instead of path.resolve (u dirname,'src/'), so let's test it next.

We added leo.js in the src/directory:

// leo.js

export let name = 'pingan';

Then to src/index.js:

// index.js

import { name } from '@/leo.js';

This will allow normal introduction.

Of course, we can also set different aliases for different paths according to the actual situation:

// webpack.common.js


alias: {
  '@' : path.resolve(__dirname, 'src/')
+ 'assets' : path.resolve(__dirname, 'src/assets/')
}

More parameter descriptions are available on the Chinese official website:
<resolve>

2. resolve.extensions

resolve.extensions is used to automatically resolve the identified extensions so that when we import a module, we don't need to set an extension. The default value is:

extensions: [".js", ".json"]

Use Configuration:

// webpack.common.js

import { name } from '@/leo';

17. External expansion of webpack configuration

When we introduced jquery using CDN, we didn't want to package it in the project, so we could configure the externals External Extension option to exclude those modules from the output bundle:

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>

Configure externals:

// webpack.common.js

module.exports = {
  // ...omit the others
+ externals: {
+   jquery: 'jQuery'
+ },
}

With the above configuration, we won't package modules that don't need to be packaged.And the following code works:

import $ from 'jquery';

$('.leo').show();

More parameter descriptions are available on the Chinese official website:
<externals>

18. webpack Packaging Analysis Report and Summary of Optimization

1. Generate reports

Here we use the webpack-bundle-analyzer plug-in to analyze the packaged file data, and always find the direction of project optimization.

webpack-bundle-analyzer uses an interactive scalable tree to visualize the size of the webpack output file.

Install plug-ins:

npm install webpack-bundle-analyzer --save-dev

This is only used in the development environment.

Use plug-ins:

// webpack.dev.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
    // ...
  ]
}

After configuring, we execute npm run build packaging, which will automatically open a page for data report analysis at http://127.0.0.1:8888/:

webpack-bundle-analyzer will help us:

  • See what modules are included in our packages;
  • See exactly what each module is made up of;
  • Finally optimize it!

We often optimize the module with the largest area in the report!

2. Optimize projects through reports

As we can see, lodash.js accounts for a very large amount of memory in the packaged project, so we optimized it for lodash.js.

We changed lodash.js to CDN:

// index.html

<script src="https://cdn.bootcss.com/lodash.js/4.17.15/lodash.js"></script>

Then set up the externals mentioned in the previous section:

// webpack.common.js

externals: {
  jquery: 'jQuery',
+ lodash: '_'
},

After packaging again, you can see that lodash.js is no longer in the package:

And packaged files will work:

More parameter descriptions are available on the Chinese official website:
<webpack-bundle-analyzer>

Reference material

summary

This article is based on New Webpack 4.0 Tutorial 4.x Road to Fairy, 2019 The learning path summarized by learning is suitable for getting started. It covers more areas and has a longer content. It needs to be able to study calmly.

If there are any errors in the content, please leave a message and I will modify it in time.

The code for this article is ultimately hosted on my github. Click to view(https://github.com/pingan8787....

Hope your article will be helpful to you, and you guys are welcome to give us your pointers.

Author Wang Ping'an
E-mail pingan8787@qq.com
Blog www.pingan8787.com
WeChat pingan8787
Daily article recommendation https://github.com/pingan8787...
ES Brochure js.pingan8787.com

WeChat Public Number

Posted by examancer on Tue, 13 Aug 2019 17:13:12 -0700