First attach the project effect:

The address of the project: http://47.105.144.204/index

Making: github.com/dsying/reac…

The previous WebPack configuration file was not optimized

const path = require('path')
const webpack = require('webpack')
const HTMLPlugin = require('html-webpack-plugin')

// Determine if it is a development environment
const isDev = process.env.NODE_ENV === 'development'

const config = {
    / / the entry
    entry: {
        app: path.join(__dirname, '.. /client/app.js')},/ / export
    output: {
        filename: '[name].[hash].js'.// The file is repackaged after changes, and the hash value changes to refresh the cache
        path: path.join(__dirname, '.. /dist'),
        / / is very important
        publicPath: '/public/',},/ / parsing
    resolve: {
        extensions: ['.js'.'.jsx'].// Automatically resolve the defined extension
    },
    module: {
        rules: [{// preloading (run eslint-loader to check the code specification before compiling, do not compile if there is an error)
                enforce: 'pre'.test: /.(js|jsx)$/.loader: 'eslint-loader'.exclude: [
                    path.join(__dirname,'.. /node_modules')]}, {// Convert JSX to JS
                test: /.jsx$/.loader: 'babel-loader'
            },
            {   // Convert ES6 syntax to lower version syntax
                test: /.js$/.loader: 'babel-loader'.exclude: [// exclude js from node_modules
                    path.join(__dirname,'.. /node_modules')]}, {// Parse the image
              test: /\.(png|jpg|gif|svg)$/.loader: 'file-loader'.options: {
                name: '[name].[ext]? [hash]'}}},plugins: [
        // Generate an HTML page and inject all the output files packed with entries into the HTML page
        new HTMLPlugin({
            template: path.join(__dirname, '.. /client/template.html')})],// Development mode
    mode: 'development'
}

if(isDev){
    config.entry = [
        'react-hot-loader/patch'.// Set here
        path.join(__dirname, '.. /client/app.js')
    ]
    config.devtool = '#cheap-module-eval-source-map'
    config.devServer = {
        host: '0.0.0.0'.port: '8887'.contentBase: path.join(__dirname, '.. /dist'), // Tell the server from which directory to serve the content
        hot: true.// Enable webPack's module hot replace feature
        overlay: {// When a compiler error or warning occurs, a black background layer and error message are displayed on the page
            errors: true
        },
        publicPath: '/public/'.// Webpack-dev-server packages are stored in memory. The external root directory of the packaged resources is publicPath. In other words, we set the location of the packaged resources
        historyApiFallback: {
            index: '/public/index.html'
        },
        proxy: { // The client port is 8887 and the server interface is 3333, so we need to set the proxy
          '/api' : 'http://localhost:3333'
        }
    }
    config.plugins = [...config.plugins, new webpack.HotModuleReplacementPlugin() ]
}
module.exports = config
Copy the code

After running NPM run build(package.json configuration)

Compressed JS files

  // The first way
  const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
  config.plugins.push(
    new UglifyJsPlugin(),
  )
  // The second way
  config.optimization ={
    minimize: true
  }
Copy the code

The subcontract

Separate the third-party libraries into separate Vendor chunks

  config.entry = {
    app: path.join(__dirname, '.. /client/app.js'),
    vendor: [
      'react'.'react-dom'.'react-router-dom'.'mobx'.'mobx-react'.'axios'.'query-string'.'dateformat'.'marked']}Copy the code

  • SplitChunks: WebPack4 removes the commonChunkPlugin and splitChunks are used instead
  • RuntimeChunk: Use webPack-generated runtime as a separate chunk. Runtime contains the module’s manifest logic for loading and parsing when modules interact.
  config.optimization = {
    runtimeChunk: {
      name: "manifest"
    },
    splitChunks: {
      cacheGroups: {
        commons: {
          test: /[\\/]node_modules[\\/]/.name: "vendor".chunks: "all"}}}}Copy the code

Using chunkhash

In the previous configuration, output was configured like this

output: {
    filename: '[name].[hash],js'
}
Copy the code

The hash values of all files generated after packaging are the same. When we modify the business code, resulting in the repackaging of app.js, the hash values of app, Vendor and Mainfest of the three chunks will change. Instead of using Vendor and Mainfest’s cache when the browser accesses the page (because the file name has changed), it has to re-send the HTTP request resource. Chunkhash allows each chunk to have its own hash value

config.output.filename = '[name].[chunkhash].js'
Copy the code

When I get to this stage, I suddenly realize that mode is not changed to production in my configuration, which is why my code is a bit big. It was repackaged with a lot more caveats

const config = {
    performance: {
        / / false | | "error" / / "warning" don't show performance tip | in the form of error tip | to warn...
        hints: "warning".// The development environment sets a large prevention warning
        // Controls when WebPack generates performance hints based on the maximum size of the entry point, an integer type, in bytes
        maxEntrypointSize: 5000000.// Maximum size of a single resource. Default: 250000 (bytes)
        maxAssetSize: 3000000}}Copy the code

NPM start after