A, use,

For the use of Webpack, here is a brief summary of the official documentation.

There will be a default configuration system for Webpack4. Simply speaking, there will be a default configuration file of webpack.config.js in the root directory of the project, where the entry file is SRC /index.js and the package exit folder is dist.

There will be a first look at a simple webPack basic configuration structure

{
    entry:'./src/index.js'.output: {path: __dirname+'/dist'.filename: '[name].js'
    },
    mode:'production'.module: {},plugins:[]
}
Copy the code

1.1 the entrance

Entry: specifies the entry file. The address is a character relative to the path to the root node of the item (for example, a single page with only one entry)

1.2 the output

Output specifies the output. The argument is an object, where path specifies the output folder. The address needs to be an absolute path

1.3 model

Mode, usually two values ‘developement’ and ‘production’, is used to mark the corresponding development and production environments, and Webpack does some default configurations depending on the value. For example, production compresses the code. At the same time, during development or packaging, values are stored in the Node module process variable process.env.node_env for use.

1.4 module

Module, because Webpack is based on Node, itself can run and identify JS files, so other modules, such as CSS, images, etc., can load these files by configuring the Loader in module. At the same time, the loader can also compile and process ES6, TS and other upper-level syntax and templates.

1.5 plug-in

Plugins, as documented, are the backbone feature of WebPack and are designed to solve problems that loader cannot implement. For example, common UglifyJsPlugin compression code, CopyWebpackPlugin copies static resources, HtmlWebpackPlugin uses HTML templates and so on

Second, the optimization

The official documentation for the simple use of Webpack is very detailed. Let’s summarize webpack optimization, which I’ve divided into three parts: code style, build efficiency, and load performance

2.1 Code Style

When you’re developing a single page, you’re going to have a development environment and a package, and then you have a friend who’s me and you’re going to have three profiles;

  • Webpack.base. js: basic configuration
  • Webpack.dev.js: development environment configuration
  • Webpack.pro.js: Package configuration

Webpack.base.js common configuration section, and then production and packaging configurations are extended by means of merge.

Configure the command line in the scripts of package.json;

  • “dev”:”webpack –config webpack.dev.js”,
  • “build”:”webpack –config webpack.pro.js”

That’s really clear, and that’s fine. But then I used the React scaffolding create-react-app and looked at the configuration file and thought it made more sense.

First, it does not use Webpack on the command line, thus eliminating the need to install WebPack-CLI

Configure command lines in scripts of package.json in create-react-app.

  • “start”: “node scripts/start.js”,
  • “build”: “node scripts/build.js”

Write scripts in the project directly using Node execution, configuration files more on the simulation of the main content

// webpack.config.js
module.exports = function(webpackEnv){
    const isEnvDevelopment = webpackEnv === 'development';
    const isEnvProduction = webpackEnv === 'production';
    return {
        // ...
        mode: webpackEnv,
        // ...
        plugins:[
            new pulicPlugin(),
            isEnvDevelopment && new Plugin1(),
            isEnvProduction && new Plugin2(),
        ].filter(Boolean)
        / /...}}Copy the code

Webpack.config. js exports a function that specifies the environment as a parameter, and then customizes the parameter to return a webPack configuration parameter, with start.js and build.js bodies presumably as well

// start.js
const configFactory = require('webpack.config');
const webpack = require('webpack');
const config = configFactory('development');
const complier = webpack(config);
return new Promise((resolve, reject) = > {
    compiler.run((err, stats) = > {
      let messages;
      if (err) {
        if(! err.message) {return reject(err);
        }
        / /...
      }
    / /...
    })
Copy the code

The first step is to pass the webpack-merge without having to install webpack-merge. In addition, the previous method is to perform only webpack compilation, and the scaffolding complements the statistical analysis after compilation.

2.2 Construction efficiency

  • 1, dllPlugin

DLL means dynamic link library, the main idea in Webpack is to separate some third party library packaging, as long as the third party library does not need to upgrade, every time the project is started or packaged, there is no need to repeat packaging these libraries.

The react project is used as an example to add a webpack.dll.config.js configuration to config

const webpack = require('webpack');
const path = require('path');
module.exports =  {
    entry: {
        vendor: ['react'.'react-dom'.'react-router-dom']},output: {
        path: path.resolve(__dirname,'.. /dist'),
        filename: '[name].js'.library: '[name]_[hash]',},plugins: [
        new webpack.DllPlugin({
            context: __dirname,
            name: '[name]_[hash]'.// Need to be the same as output.library
            path: path.resolve(__dirname, '.. /dist/[name]-manifest.json'),}})]Copy the code

Package. The json increases the command line “build: DLL” : “webpack – config config/webpack. DLL. Config. Js – mode production”;

After the command is executed, two vendor-manifest.json and vendor.js files are generated in the dist folder. Vendor. js is a separate static resource, while vendor-manifest.json is a manifest file to describe the source path of the resource.

The separation is then made available to the project via the DllReferencePlugin, adding the configuration to webpack.config.js

new webpack.DllReferencePlugin({
  context: __dirname,
  manifest: require('.. /dist/vendor-manifest.json'), // Specify the location of the DLL description
}),
Copy the code

This is done through DLL separation, but there is still a step to go. When we run the project, we find that the HTML is not imported vendor.js. We need to manually update the HTML template or add it using the add-asset-html-webpack-plugin.

const AddAsssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
//....
plugins:[
  // ...
  new AddAsssetHtmlWebpackPlugin({
    filepath: path.resolve(__dirname, '.. /dist/*.js'),
    hash:true.// Prevent caching after attaching hash to file name
    outputPath: 'static/js'.//
    publicPath: '/static/js'
  })
  / /...
]
Copy the code

Then the finished project can run normally.

  • 2, HappyPack

Happypack speeds up webpack packaging. Essentially happypack uses multiple processes through JS to accelerate packaging.

const HappyPack = require('happypack');
const os = require('os');
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
// introduce happypack, ThreadPool ThreadPool using system core number
module.exports = {
  / /...
  module: {
    rules: [{test:/\.js$/.use:[
          {
            // loader:'babel-loader',
            // options:{
            / /...
            // }
            loader:'happypack/loader? id=happyBabel'.// Add trigger happypack to loader to transfer the original configuration to happypack}]}]},plugins: [new HappyPack({
      id:'happyBabel'.// ID Is the same as the id configured in the loader
      threadPool: happyThreadPool,
      verbose: false.// Whether to output process logs
      loaders:[
        {
          loader:'babel-loader'.options: {... }}]})]}Copy the code

2.3 Loading Performance

  • 1, Gzip

GZIP encoding over the HTTP protocol is a technique used to improve the performance of WEB applications. High-traffic WEB sites often use GZIP compression technology to give users a sense of speed. This usually refers to a feature installed in WWW servers that compresses the content of web pages to display in the visiting computer’s browser when someone visits a web site on the server. Generally for plain text content can be compressed to 40% of the original size. This transfer is fast, the effect is that you click on the url will be quickly displayed. Of course, this also increases the load on the server. General server are installed with this functional module.

The main principle of Gzip is to temporarily replace the repeated character fragments to reduce the file size.

How to check?

The accept-Encoding field in the HTTP request header of the browser client tells the server the accepted Encoding format. If the value contains gzip, the browser supports parsing the return of gzip. If the server is enabled and returns a Gzip response, the response header will have a content-Encoding field that says Content-Encoding: Gzip. That is, the response is compressed into Gzip on the server and then decompressed for use by the client.

How to use it?

Taking the create-React-app scaffolding as an example, the console outputs the following after packaging.

The size of the file is suggested to be the size after using Gzip. We check that the real file size is indeed much larger, and the Gzip file suffix is gz. For Gzip of static resources, you need to add the compression-webpack-plugin configuration to webpack.

const CompressWebpackPlugin = require('compression-webpack-plugin');
// Add to plugins
new CompressWebpackPlugin({
    test: /\.(js|css)$/.// Compress js and CSS
    threshold: 10240.// The resource is too small to be necessary, and decompression is also a loss
    minRatio: 0.6 // Compress the minimum ratio lower limit
    // Use the default values for other parameters
  })
Copy the code

After the configuration is complete, the packaged code static resource that meets the above conditions will have a gzip file with the suffix.gz, and the client configuration is complete. Gz files are automatically requested when clients that parse Gzip request static resources on the server. Taking ANTD as an example, the volume of a complete ordinary compressed package is close to 2M, but after Gzip compression, the volume will be reduced to less than 600KB. Combining with the principle of Gzip, the compression efficiency of this UI component with strong reuse will definitely be relatively high.

Static resources are done, and the server can do some optimization. The server uses Gzip to compress data returned by some interfaces. Koa is used as an example to install koA-COMPRESS

const compress = require('koa-compress')
const Koa = require('koa')
const app = new Koa()
app.use(compress({
  filter: function (content_type) {
  	return /text/i.test(content_type)
  },
  threshold: 2048.flush: require('zlib').Z_SYNC_FLUSH
}))
Copy the code

Using the default configuration of Demo, the interface response value that meets the configuration conditions will be compressed into Gzip and returned to the client.

  • 2. Load on demand

Multiple routes in a single-page application are configured to be loaded on demand to prevent excessive resources from being loaded on the first page.

An article on code splitting

The React project is used as an example to configure routing components using react-loadable

import Loadable from 'react-loadable';

// Modify the configuration before, package after entering the home page will load the corresponding resources
import oldViewComponent from './viewComponent'; <Route path='/view' component={oldViewComponent} /> // () => import('./viewComponent'), loading: }) <Route path='/view' component={newViewComponent} />Copy the code