preface

Vue-cli3 provides project scaffolding out of the box, with a webpack configuration that has been optimized. However, when the project is getting bigger and bigger, it currently takes three or four minutes to pack my project, and the home page is also slow to load. Therefore, we hope to optimize Webpack to further improve packaging efficiency.

However, all kinds of information on the web are either for the configuration of webpackage 4 before, or the default configuration of VUE-CLI3 has been included. In the end, I mainly used the following plug-ins: Webpack-bundle-Analyzer to analyze package size, DllPlugin to pack in advance, and GZIP code to compress. As my level is limited, there are incorrect places welcome correction.

Vue-cli3 has been optimized

First, some of the default configurations are available through configuration references in the official documentation. The vue-inspect command allows you to view the default Webpack configuration. For example, babel-loader, if exclude is configured and cacheDirecorty is enabled, you do not need to optimize the loader.

Second, from the vuE-CLI official documentation, note that the PARALLEL configuration is described 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.

HappyPack, the multithreaded packaging plugin used in many tutorials on the web, is no longer needed.

In addition, in webpack4, code compression and Tree Shaking are automatically turned on when mode is production.

Further optimization

Since vuE-CLI3 already offers these optimizations, there is not much that can be done, so I went further in terms of pre-packing and enabling gzip compression.

Packaging in advance

Notice that in the packaged project, there is a particularly large, 1.8m vendors.js file, which is related to the imported third-party libraries. My project has introduced many third-party libraries, such as Ant-Design-Vue, ANTV, LoDash, etc. These library files are usually not changed, so by packaging in advance, can shorten the packaging time?

Next, look at third-party libraries. Since I use third-party libraries to import on demand, I do not know which libraries are more bulky, so I need to use the plugin Webpack-bundle-Analyzer, which shows the size and relationship of modules in each package in the form of a rectangular tree. Introduced by means of plug-ins

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

module.exports = {
    configureWebpack: config= > {
        if (process.ENV.NODE_ENV === 'production') {
            config.plugins = [
                ...config.plugins,
                new BundleAnalyzerPlugin()
            ]
        }
    }
}
Copy the code

After running NPM run build, open localhost:8888 and see my project structure below

ant-design-vue
moment
antv
quill
lodash

Create webpack.dll.conf.js in the project root directory

const path = require('path')
const webpack = require('webpack')

// Directory for storing DLL files
const dllPath = 'dll/'

const libs = {
    'ui': ['ant-design-vue'].'frame': ['vue'.'vuex'.'vue-router'.'moment'.'quill'].'chart': ['@antv/g2'.'@antv/data-set']}module.exports = {
  entry: {
    // The library file to extract. libs },output: {
    path: path.join(__dirname, dllPath),
    filename: '[name].dll.js'.// Global variable name exposed in vendor.dll.js
    // Keep the same name as webpack.dllPlugin
    library: '[name]_[hash]'
  },
  plugins: [
    // manifest.json describes what the dynamic link library contains
    new webpack.DllPlugin({
      path: path.join(__dirname, dllPath, '[name]-manifest.json'),
      // keep the same name as output.library
      name: '[name]_[hash]'.context: process.cwd()
    })
  ]
}
Copy the code

Add to package.json and run the NPM Run DLL

"scripts": {..."dll": "webpack -p --progress --config ./webpack.dll.conf.js"
},`
Copy the code

Add the following configuration to vue.config.js

config.plugins = [
    ...config.plugins,
    new webpack.DllReferencePlugin({
        context: process.cwd(),
        manifest: require('./dll/ui-manifest.json')}),new webpack.DllReferencePlugin({
        context: process.cwd(),
        manifest: require('./dll/frame-manifest.json')}),new webpack.DllReferencePlugin({
        context: process.cwd(),
        manifest: require('./dll/chart-manifest.json')})]Copy the code

The packaging is complete, but Webpack does not automatically import these separately packaged third-party libraries, so we need the add-asset-html-webpack-plugin.

const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin')

config.plugins = [
    ...config.plugins,
    new AddAssetHtmlPlugin({
        filepath: path.resolve(__dirname, './dll/*.js'), // DLL file location
        publicPath: './js'.// DLL reference path
        outputPath: './js' // DLL final output directory})]Copy the code

Enable Gzip compression

Gzip compressed packets can be reduced by about 2/3, which significantly improves network transmission. Enabling gzip requires the cooperation of the server. For example, add gzip to nginx.conf

server: {
    ...
    
    gzip on; Whether to enable gzip
    gzip_buffers 32 4K; How many blocks do you compress in memory? How big is each block?
    gzip_comp_level 6; # Recommendation 6 Compression level (the higher the compression level, the less pressure, the more WASTED CPU computing resources)
    gzip_min_length 100; # Minimum length of compression to begin with
    gzip_types application/javascript text/css text/xml; # Which types of files to use compression such as TXT, XML, HTML, CSS
    gzip_disable "MSIE [1-6]\."; # Configure to disable gzip condition, support regex. Gzip is not enabled in IE6 and below (because it is not supported in earlier versions of IE)
    gzip_vary on; Whether to transmit the Gzip compression flag
}
Copy the code

This way, when the client requests the file, the server automatically compresses the file. However, server compression requires CPU overhead. In order to save CPU resources, we can package a copy of GZIP at the same time with the following configuration

const CompresssionPlugin = require('compression-webpack-plugin')

config.plugins = [
    ...config.plugins,
    new CompressionPlugin({
        test: /\.js$|\.html$|\.css$/.deleteOriginalAssets: false // Whether to delete the original file})]Copy the code

The results of

After optimization, the minimum package time of the project is more than 90s, but sometimes it still exceeds three minutes. I’m not sure why. The loading time of the home page has been shortened from 8s to 5s, which has been significantly improved.

Thank you for reading this article, if there is any incorrect, welcome correction and discussion.