Project optimization configuration based on VUE-CLI4 construction project

preface

Starting with VUE-CLI3, VUe-CLI provided us with a quick one-click build tool that, on most simple projects, ensured that the various build tools worked smoothly based on intelligent default configurations so that we could focus on writing the application instead of spending days on configuration issues. But writing the right configuration files can really make our projects better, have better performance, and have better structure. This article summarizes the commonly used optimization configuration based on personal project experience.

Optimizing the allocation of

  1. webpack-bundle-analyzer

The package analysis plugin is already built into vue-CLI, so you just need to configure scripts in package.json:

"scripts": {
    "serve": "vue-cli-service serve"."build": "vue-cli-service build"."analyzer": "vue-cli-service build --report"
  },
Copy the code

You can generate a report. HTML analysis report at package time.

  1. productionSourceMap

    A Source Map is an information file that stores location information. Each position of the transformed code corresponds to the position before the transformation. With this, when something goes wrong, debug displays the original code, not the converted code.

    In most cases, we don’t need the Source Map file in production, but it takes up a lot of volume, so we ungenerate the Source Map file in production.

    module.exports = {
    	productionSourceMap: false,}Copy the code

    For an introduction to Source Map, check out Ruan Yifeng’s article JavaScript Source Map

  2. Adding an Alias

    We usually introduce an alias when the project is large. Add an alias as follows:

    module.exports = {
      chainWebpack: config= > {
        // Add an alias
        config.resolve.alias
          .set("vue$"."vue/dist/vue.esm.js")
          .set("@", resolve("src"))
          .set("@assets", resolve("src/assets"))
          .set("@scss", resolve("src/assets/scss"))
          .set("@components", resolve("src/components"))
          .set("@plugins", resolve("src/plugins"))
          .set("@views", resolve("src/views"))
          .set("@router", resolve("src/router"))
          .set("@store", resolve("src/store"))
          .set("@layouts", resolve("src/layouts"))
          .set("@static", resolve("src/static")); }};Copy the code

    This can be resolved by adding an alias.config.js file to the root directory of the project. This file contains the following contents:

    const resolve = dir= > require('path').join(__dirname, dir)
    
    module.exports = {
      resolve: {
        alias: {
          The '@': resolve('src'),
          'static': resolve('static'),
          'public': resolve('public'),}}}Copy the code
  3. Enable Gzip compression

    Gzip is an abbreviation for several file compression programs, usually the implementation of the GNU Project. Here Gzip stands for GNU Zip. It is also often used to refer to the file format gzip. At present, the main gZIP compression optimization, is through the gzip compression program, to compress resources, so as to reduce the file size of the resource request. The compression process can be compressed when the server receives a request, or it can be compressed during construction. For example, we can use compression-webpack-plugin for webpack and gzip for project construction. The general configuration is as follows:

    const CompressionPlugin = require("compression-webpack-plugin")
    module.exports = {
    configureWebpack:config= >{
            if(progress.env.NODE_ENV === 'production') {return{
                    plugins: [
                    
                        new CompressionPlugin({
                            test:/\.js$|\.html$|.\css/.// Match the file name
                            threshold: 10240.// Compress data over 10K
                            deleteOriginalAssets: false // Do not delete the source file}}},}Copy the code
  4. Delete moment language package

    Delete moment zh-CN language package except zh-CN language package, no need to manually import zh-CN language package in the code.

    const webpack = require("webpack");
    
    module.exports = {
      chainWebpack: config= > {
        config
          .plugin("ignore")
          .use(
            new webpack.ContextReplacementPlugin(/moment[/\\]locale$/./zh-cn$/));returnconfig; }};Copy the code
  5. Configure externals to import CDN resources

    If you want to import some resources with a CDN, you can configure externals to import CDN resources to prevent importing some imported packages into the bundle and obtain these external dependencies at runtime:

    module.exports = {
      configureWebpack: config= > {
        config.externals = {
          vue: "Vue"."element-ui": "ELEMENT"."vue-router": "VueRouter".vuex: "Vuex".axios: "axios"
        };
      },
      chainWebpack: config= > {
        const cdn = {
          / / https://unpkg.com/element-ui/lib/theme-chalk/index.css for the latest version
          css: ["/ / unpkg.com/[email protected]/lib/theme-chalk/index.css"].js: [
            "/ / unpkg.com/[email protected]/dist/vue.min.js"./ / https://unpkg.com/vue/dist/vue.min.js for the latest version
            "/ / unpkg.com/[email protected]/dist/vue-router.min.js"."/ / unpkg.com/[email protected]/dist/vuex.min.js"."/ / unpkg.com/[email protected]/dist/axios.min.js"."/ / unpkg.com/[email protected]/lib/index.js"]};// If you are using multi-page packaging, use vue inspect --plugins to see if the HTML is in the result array
        config.plugin("html").tap(args= > {
          // Add CDN to HTML
          args[0].cdn = cdn;
          returnargs; }); }};Copy the code
  6. SplitChunks subcontract

    Webpack CommonsChunkPlugin 4 removed and replaced by two new configuration items (optimization) splitChunks and optimization) runtimeChunk), The WebPack Common mode has now been optimized for general use for most users. If necessary, it is best to try to manually tune these parameters in the context of practical testing, as described in the article: Step-by-step Guide to WebPack4’s splitChunk plug-in.

    Common parameters:

    • MinSize (default 30000) : The minimum size to form a new code block
    • MinChunks (default: 1) : The minimum number of times that a chunk of code should be referred to before it is split.
    • MaxInitialRequests (3 by default) : Maximum number of parallel requests for an entry
    • MaxAsyncRequests (default: 5) : Maximum number of parallel requests that can be loaded on demand.
    • Chunks (async by default) : Initial, Async, and all
    • Test: Used to control which modules are matched by this cache group. When passed intact, it will select all modules by default. Types of values that can be passed: RegExp, String, and Function
    • Name (the name of the packaged chunks) : string or function (the function can be named according to the condition)
    • Priority: priority of cache group packaging.
    module.exports = {
      configureWebpack: config= > {
        if (progress.env.NODE_ENV === 'production') {
          config.optimization = {
            splitChunks: {
              cacheGroups: {
                common: {
                  name: "chunk-common".chunks: "initial".minChunks: 2.maxInitialRequests: 5.minSize: 0.priority: 1.reuseExistingChunk: true.enforce: true
                },
                vendors: {
                  name: "chunk-vendors".test: /[\\/]node_modules[\\/]/,
                  chunks: "initial".priority: 2.reuseExistingChunk: true.enforce: true
                },
                elementUI: {
                  name: "chunk-hui".test: /[\\/]node_modules[\\/]hui[\\/]/,
                  chunks: "all".priority: 3.reuseExistingChunk: true.enforce: true
                },
                echarts: {
                  name: "chunk-echarts".test: /[\\/]node_modules[\\/](vue-)? echarts[\\/]/,
                  chunks: "all".priority: 4.reuseExistingChunk: true.enforce: true}}}}; }},chainWebpack: config= > {
        if (progress.env.NODE_ENV === 'production') {
          config.optimization.delete("splitChunks");
        }
        returnconfig; }};Copy the code
  7. About DLLS and AutoDllPlugin

    If you read some webPack optimization articles, there is a good chance that AutoDllPlugin or DLL dynamically linked libraries will appear. The concept of a DLL is to cache:

    The so-called dynamic link is to make some commonly shared code into A DLL file. When the executable file calls the function in the DLL file, the Windows operating system will load the DLL file into the memory. The STRUCTURE of the DLL file itself is the executable file, and the function will be linked when the program needs it. Through dynamic linking, memory waste can be greatly reduced.

    The AutoDllPlugin simplifies the configuration of DLLS to a large extent. However, because WebPack 4 has better packaging performance than DLLS, Vue and React have both abandoned the use of the autoDLL-webpack-plugin, which will not be expanded here.

  8. HardSourceWebpackPlugin

    DLL acceleration is not obvious, is there a better alternative? In the README of AutoDllPlugin, HardSourceWebpackPlugin is recommended. The initial configuration is simpler and requires only one line of code:

    const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
    module.exports = {
      plugins: [
        new HardSourceWebpackPlugin() // <- just add this line of code]}Copy the code

    However, webpack5 will come with HardSource built in, so it is recommended to wait for the webpack5 update if the project needs are not strong.

  9. About the parallel

As with the DLLS and AutoDllPlugin mentioned above, Parallel like the one below often appears in webPack optimization articles.

module.exports = {
  parallel: require("os").cpus().length > 1};Copy the code

Parallel can be configured in the vue.config.js file as follows:

Whether thread-loader is used for Babel or TypeScript. This option is automatically enabled when the system CPU has more than one kernel and only applies to production builds.

But by reading the source code, we can see that this is redundant and unsafe. See [Vue CLI 3] for configuration analysis of PARALLEL.