This is a series of articles on the basic of WebPack js optimization, JS compatibility handling, how to use WebPack to make some browsers incompatible with ES6/ES7,React JSX escape to ES5, how to use ESLint code verification in the development environment for a unified style. HTML compression, and other webpackage 5 configurations such as resolve, noParse, IgnorePlugin, output.library, output. libraryTarget.

Official start:

Prepare the skills

Basic NodeJS knowledge and NPM instructions

Note: the webpack version used in this series is: “webpack”: “^5.68.0”,

“Webpack – cli” : “^ 4.9.2”,

JS Compatibility processing

Use babel-loader to handle JS compatibility issues

Babel is actually a platform for compiling JavaScript. It can escape ES6/ES7,React JSX to ES5

1. If it’s just basic JS compatibility, just add presets to babel-loader and use @babel/preset-env for some general syntax-compatibility

Use @babel/runtime-corejs3 and @babel/plugin-transform-runtime before webPack4 use @babel/polyfill before webPack4

The downside of this is that I only solve part of the compatibility problem, but I import all the compatibility code, which is too bulky

3, need to do compatibility processing to do: as needed to load use — “core-js”

Install @babel/core and babel-loader @babel/present-env

Install dependencies

  • Babel-loader uses Babel and Webpack to translate JavaScript files
  • @babel/@babel/coreBabel compilation core package
  • babel-preset-env
  • React can be used instead of the @babel/@babel/preset-reactReact preset
  • @babel/plugin-proposal-decorators compile class and object decorators into ES5
  • @babel/plugin-proposal-class-properties Transforms static class properties and initializes properties declared by syntax using properties
npm i babel-loader @babel/core @babel/preset-env @babel/preset-react  -D
Copy the code
npm i @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties @babel/plugin-proposal-private-property-in-object  @babel/plugin-proposal-private-methods -D
Copy the code

2. Modify the webpack.config.js configuration file

{ test: /.jsx? $/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: [['@babel/preset-env', {// Load useBuiltIns as needed: 'usage', // Specify core-JS version corejs: {version: Targets: {Chrome: '60', Firefox: '60', IE: '9', Safari: '10', edge: '17' } }], '@babel/preset-react' ], plugins: [ ["@babel/plugin-proposal-decorators", { legacy: true }], ["@babel/plugin-proposal-private-property-in-object", { "loose": true }], ["@babel/plugin-proposal-private-methods", { "loose": true }], ["@babel/plugin-proposal-class-properties", { loose: true }], ] } } },Copy the code

The. / SRC/index. Js modified

// ./src/index/js import dataJson from './data.json'; import './index.css'; import './index.less'; import './index.scss'; import './assets/icons/iconfont.css'; Function add(x, y) {return x + y; } console.log(add(1, 2)); console.log(dataJson, 'dataJson'); // js const logo = require('./assets/ vite.png'); const img = new Image(); img.src = logo; document.body.appendChild(img); class Person { constructor() { this.name = 'hello' } setName(name) { this.name = name } } let p1 = new Person(); P1. Elegantly-named setName (' webpack5 series'); console.log(p1.name) const total = [1, 2, 3, 4].reduce((a, b) => a + b) console.log('total', total)Copy the code

New jsconfig. Json

{
    "compilerOptions": {
        "experimentalDecorators": true
    }
}
Copy the code

Run webpack

The reduce method, which previously did not support arrays under IE11, is now compatible

ESLint code verification

Syntax check ESLint

Rule:cloud.tencent.com/developer/c…

ESlint syntax checks configuration instructions

Install eslint-webpack-plugin :(this plugin uses eslint to find and fix problems in JavaScript code.)

Note: only check your own source code, third-party libraries do not have to check

Note: If you don’t have ESLint >= 7 installed, you’ll need to install it via NPM first:

Install and configure the eslint-webpack-plugin

1) install eslint-webpack-plugin :(this plugin uses eslint to find and fix problems in JavaScript code.)

NPM install eslint-webpack-plugin –save-dev note: if eslint >= 7 is not installed, you will need to install it via NPM:

npm install eslint --save-dev
Copy the code

2) Configuration: webpack.config.js file:

const ESLintPlugin = require('eslint-webpack-plugin'); Plugins: [new ESLintPlugin({exclude:'node_modules', // exclude eslint from node_modules folder fix:true // automatically fix JS format errors})],Copy the code

Setting check Rules

Js Style Guide library: Airbnb

By setting the rule of plug-in: eslint – config – reality – base: refer to the official document: www.npmjs.com/package/esl…

The default export includes all ESLint rules, including ECMAScript 6+. It requires esLint and eslint-plugin-import

Eslint-import-resolver-webpack (this is required if an alias is configured in webpack.config.js and an alias is used when importing)

use

1, install,

npm i eslint-config-airbnb-base eslint-plugin-import @babel\eslint-parser --save-dev
Copy the code

2) Configuration: two ways:

Method 1:.eslintrc.js file add:

module.exports = {"extends": "airbnb-base"
}
Copy the code

Method 2: Package. json file to add: // Inherit the Airbnb style. For details, you can check the airbnb style in Github

"eslintConfig": { "extends": "airbnb-base"}
Copy the code

Run webpack

Warning Unexpected console statement no-console, you can add // eslint-disable-next-line to the js file above the console.log() output You can ignore the warning prompt for the output statement.

No – indef changes

Json file to add: // Inherit airbnb style. For details, check airbnb repository on Github

"eslintConfig": {
        "extends": "airbnb-base",
        "env": {
            "browser": true
        }
    }
Copy the code

To the.eslintrc.js file add:

module.exports = {
    "parser": "@babel/eslint-parser",
    "extends": "airbnb-base",
    "parserOptions": {
        "ecmaVersion": 2015,
        "requireConfigFile": false,
        "ecmaFeatures": {
            "experimentalObjectRestSpread": true,
            "impliedStrict": true,
            "classes": true
        }
    },
    "rules": {
        "semi": "error",
        "no-console": "off",
        "linebreak-style": "off",
        "eol-last": "off"
            //"indent":["error",2]
    },
    "env": {
        "browser": true,
        "node": true
    }
}
Copy the code

Eslintrc.js will not report errors during compilation, use.eslintrc.js because it also added the closing error “no-console”

No use of babel-ESLint, the deprecated babel-esLint parser does not support the ES6 module and can be updated

Install React

npm i eslint-plugin-react eslint-plugin-react-hooks and eslint-plugin-jsx-a11y -D
Copy the code

Ps: Note that we no longer use eslint-loader but eslint-webpack-plugin instead.

Js compressed

  • Terser-webpack-plugin is a plug-in that optimizes and compresses JS resources

Mode :’production’ will automatically start a series of plugins, including automatic compression

use

1, install,

npm i terser-webpack-plugin -D
Copy the code

2. Modify webpack.config.js

reference

const TerserPlugin = require('terser-webpack-plugin');
Copy the code

use

optimization: { minimizer: [ new CssMinimizerWebpackPlugin(), new TerserPlugin(), ], minimize: // If you also want to enable CSS optimizations in your development environment, set optimization.minimize to true:},Copy the code

HTML compression

Or the previous HtmlWebpackPlugin to add related attributes can be

Add minify to new HtmlWebpackPlugin in webpack.config.js

New HtmlWebpackPlugin({// copy the './index.html' file and automatically import all the resources (js/ CSS) that package the output. Template: './index.html', minify: CollapseWhitespace: true, // remove comment removeComments: true}}),Copy the code

Run webpack

See code compression in Build \index.html

Image optimization

1. We also put the pictures in a folder

Test: /.(jpe? G | PNG | | GIF SVG) $/, type: "asset", the generator: {/ / and the output. AssetModuleFilename is the same, the time of this writing is introduced into will also add the filename path: 'imgs/[name].[hash:6][ext]' }, }Copy the code

Run webpack

Check the build folder and find an IMGS folder containing all the images we introduced

Viewing the browser also works

2. We can also change output

Output: {// output name string (default) filename template of entry chunk filename: 'js/[name].[contenthash:10].js', // the output path __dirname nodejs variable represents the directory of the current file. The absolute path must be an absolute path (using node.js's path module) path: resolve(__dirname, 'build'), assetModuleFilename:'imgs/[contenthash:6][ext]' }Copy the code

Ps: What is the priority of the first and second methods?

Set in generator in loader

The generator: {/ / and the output assetModuleFilename is the same, the time of this writing is introduced into will also add the filename path: '/ imgs [name]. [6] hash: [ext]'}Copy the code

The priority is a little higher

3, we know that when the image is smaller than a certain size, base64 image is used to reduce the request

Test: /.(jpe? G | PNG | | GIF SVG) $/, type: "asset", / / / / parsing parser: {/ / base64 conditions dataUrlCondition: {maxSize: 25 * 1024, / / 25 KB}}, the generator: {/ / and the output. AssetModuleFilename is the same, the time of this writing is introduced into will also add the filename path: 'imgs/[name].[hash:6][ext]' }, }Copy the code

If type: “asset/inline”, the resource will be loaded inline and packed, but the image size will be base64 and the HTML will be too bulky.

Type: “asset”, which is automatic, determines the size of the resource by default. If the resource file is larger than 8K, it is asset/resource. If the resource file is smaller, it is “asset/inline”.

Run webpack

Check the build/ IMGS folder and notice that an image file is missing

Viewing a browser

Fewer images are displayed in Base64 format because they are smaller than the size we set.

resolve

1, extensions,

If you specify extension, you don’t need to add a file extension to require or import

Webpack attempts to parse modules from left to right in the extensions configuration array

resolve: {
  extensions: [".js",".jsx",".json",".css"]
}
Copy the code

Note that:

  1. High frequency file name suffix in front;
  2. After manual configuration, the default configuration will be overwritten

If you want to keep the default configuration, you can use… The extended operator represents the default configuration, for example

resolve: {
 extensions: ['.js', '...'], 
}
Copy the code

2, alias

Configuring aliases speeds up WebPack’s search for modules

Resolve :{// Alias :{'@': resolve(' SRC '), 'components': resolve(' SRC /components'),}}Copy the code

use

// use SRC alias @import '@/index.css'Copy the code

3 、modules

Configure the directory in which webpack looks for third-party modules. By default, only node_modules is used to look for third-party modules. If you have modules in a folder in your project that are frequently imported and don’t want to write a long path, you can simplify this by configuring resolve.modules.

  • For modules that declare dependencies directly (like react), Webpack does a path search similar to Node.js, searching the node_modules directory

  • This directory is just for use

    resolve.modules
    Copy the code

    Default configuration for field configuration

    resolve: {
        modules: ['node_modules'],
    }
    Copy the code

    If you can be sure that all third-party dependencies in your project are in node_modules in the project root directory

    resolve: {
        modules: [resolve(__dirname, 'node_modules')],
    }
    Copy the code

4、 mainFields

Some third-party modules provide multiple pieces of code, such as bootstrap. You can view the package.json file of bootstrap:

{
    "style": "dist/css/bootstrap.css",
    "sass": "scss/bootstrap.scss",
    "main": "dist/js/bootstrap",
}
Copy the code

Resolve. MainFields default configuration is [‘browser’, ‘main’], which first looks for the brower field in the corresponding dependency package.json, and if not, looks for the main field.

For example: import ‘bootstrap’ By default, find the file specified in the main field of the corresponding dependency package.json, dist/js/bootstrap.

If we want import ‘bootsrap’ to find CSS files by default, we can configure resolve.mainFields to:

module.exports = {
    //....
    resolve: {
        mainFields: ['style', 'main'] 
    }
}
Copy the code

When package.json is not present in the directory, we say that the index.js file in the directory will be used by default, which can also be configured

Resolve: {mainFiles: ['index'], // You can add other default file names},Copy the code

Ps: By default, package.json files are found by the name of the main field in the file

Resolve: {// set target === "web" or target === "webworker". ['browser', 'module', 'main'], // target values are other, mainFields default values are: mainFields: ["module", "main"],}Copy the code

5, resolveLoader

ResolveLoader has the same set of attributes as the Resolve object above, but is only used to resolve the Loader package for WebPack.

In general, keep the default configuration, but if you have a custom Loader, you need to configure it, it may not be able to find the Loader error

noParse

  • module.noParseField that can be used to configure which module file contents do not need to be parsed
  • Large third-party libraries that do not need to resolve dependencies (i.e., no dependencies) can be configured through this field to improve the overall build speed

Import mechanisms such as import, require, and define cannot be used in module files that are ignored using noParse

module.exports = { // ... The module: {noParse: / jquery | lodash /, / / / / or regular expressions using the function noParse (content) {return/jquery | lodash /. The test (content)},}}Copy the code

IgnorePlugin

IgnorePlugin is used to ignore specific modules so that WebPack does not pack those specified modules

1 src/index.js

import moment from  'moment';
import 'moment/locale/zh-cn'
console.log(moment().format('MMMM Do YYYY, h:mm:ss a'));
Copy the code

2 webpack.config.js

import moment from  'moment';
console.log(moment);
      new webpack.IgnorePlugin({
          //A RegExp to test the context (directory) against.
          contextRegExp: /moment$/,
          //A RegExp to test the request against.
          resourceRegExp: /^./locale/
      new MiniCSSExtractPlugin({
          filename:'[name].css'
      })
Copy the code
  • The first is a regular expression that matches the path of the introduced module
  • The second is the name of the directory in which the module is matched

Cross domain, server proxy

We know that in the development phase, we call other third-party API interfaces, if different domains will appear cross-domain, we can not develop. You can’t use mock data forever, and you still need a real interface for both the front and back.

Change the devServer

// DevServer is used to automate (automatically compile, automatically open browser, automatically refresh browser...) NPX webpack-dev-server = NPX webpack-dev-server = NPX webpack-dev-server DevServer: {// NPX webpack-dev-server: {// NPX webpack-dev-server: {// NPX webpack-dev-server: Resolve (__dirname, 'build'), // enable gzip compress: true, // port: 8888, // automatically open browser: true, // enable HMR function hot: Proxy: {'/ API ': {target: 'http://localhost:5000', pathRewrite: {'/ API ': {target: 'http://localhost:5000', pathRewrite: { '^/api': '' } } } }Copy the code

onBeforeSetupMiddleware

  • OnBeforeSetupMiddleware can be used to intercept partial requests returning specific content, or to implement simple data mocks, before being processed by the Webpack-dev-server static resource middleware.

    devServer: { onBeforeSetupMiddleware(devServer){// express() devServer.app.get('/api/users', (req, res) => { res.json([{ id: 1 }, { id: 2 }]); }); }}Copy the code

webpack-dev-middleware

Webpack-dev-middleware is a middleware that provides webpack-dev-server static service capabilities in Express

npm install webpack-dev-middleware --save-dev
const express = require('express');
const app = express();
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackOptions = require('./webpack.config');
webpackOptions.mode = 'development';
const compiler = webpack(webpackOptions);
app.use(webpackDevMiddleware(compiler, {}));
app.listen(3000);
Copy the code
  • The advantage of webpack-dev-server is that it is relatively simple to install dependencies and run commands directly
  • While the use ofwebpack-dev-middlewareThe advantage of webPack-dev-Server is that you can quickly add webpack-Dev-server functionality to existing Express code, while using Express to add additional functionality as needed, such as mock services, proxy API requests, and so on

Thank you

This is the end of this introduction, then will be sorted out webpack knowledge system content sharing, enjoy looking forward to, thank you for reading ~~