One, foreword

It takes about 2.5 minutes to read this article.

  • You can learn from this article

    1. vue-cliWhat optimizations are made by default?
    2. What optimizations can we do based on the CLI?
    3. vue.config.jsHow to configure some commonpluginandloader
  • Vue-cli has saved us the time to configure Webpack. In other words, a person who doesn’t know webPack can start development directly. For example, file-loader, url-loader is configured for us in advance.

  • In terms of performance, vue-CLI also does as many optimizations as possible by default, such as cache-loader is pre-configured in the project. We can view the basic configuration predefined by the CLI in the webpack.config.js file by typing vue inspect > webpack.config.js in the console. Today we will talk about the points that can be optimized based on vue-CLI built projects.

Second, the project source code

The project source code used in this article

3. Quantitative indicators

1. The build time

speed-measure-webpack-pluginThe plugin can see the time taken by the Webpack loader and plugin at build time, and the configuration is very simple. As follows:

// vue.config.js
module.exports = {
chainWebpackconfig= > {
   config.plugin('speed')
   .use(SpeedMeasureWebpackPlugin)
 }
}
Copy the code

Look at the effect, by the way

2. Size and number of packages after build

webpack-bundle-analyzerPlug-ins help us visualize the size and dependencies of each package at build time. Vue-cli also made the default configuration for us, I just need to add a parameter –report at the end of build.

// package.json
{
  "name""dll-vue"."version""0.1.0 from"."private"true."scripts": {
    "serve""vue-cli-service serve"."build""vue-cli-service build"."report""vue-cli-service build --report",}}Copy the code

npm run reportAfter that, we have a report. HTML file in the dist directory. We open this file in our browser and take a look

Fourth, start optimization

1. include/exclude

We usually configure include and exclude to make the Loader process only matched files, like this

// webpack.config.js
module.exports = {
  module: { 
      rules: [{test: /\.js[x]? $/, 
              use: ['babel-loader'].include: [path.resolve(__dirname, 'src']}]},}Copy the code

The transpileDependencies property of Vue ignores all files in node_modules by default, which satisfies most of our requirements.

2. resolve

Resolve: configurationwebpackImport * from ‘XXX’. XXX modules should be found from node_modules firstvue inspect > webpack.config.jsThe modules field in the exported file clearly shows that node_modules has been set as the preferred module to find

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

3. happypack-plugin/thread-loader

In general, we can enable multi-threaded packaging via happack-plugin or thread-loader. Vue – cliparallelProperty means whether it is used by Babel or TypeScriptthread-loaderThe default value is the number of CPU cores, which means that if you have a 3-core CPU, the build will automatically start 3 threads for babel-loader and TS-loader execution. If you want to try your own configuration, you can do something like this. (I tried configuring it myself, but it didn’t seem to work. Maybe I configured the wrong, welcome to correct)

config.module.rule('vue')
          .use('thread-loader')
          .loader('thread-loader')
          .before('vue-loader')
Copy the code

4. noParse

This can be used if some third-party modules do not have AMD/CommonJS specification versionsnoParseTo identify the module, like thisWebpackThese modules are introduced, but not transformed and parsed, and thus promotedWebpackBuild performance, for example:jquery 、lodash.vue.config.jsCan be configured as follows:

// vue.config.js
module.exports = {
   / /...
   configureWebpack:{
    module: {
      noParse: /^(lodash|moment)$/
    }
  }
  / /...
}
Copy the code

5. ContextReplacementPlugin

For example, the moment language pack is usually enough, so we can configure it like this:

// vue.config.js
module.exports = {
   / /...
   configureWebpack: {plugins: [
           new webpack.ContextReplacementPlugin(/moment[/\\]locale$/./zh-cn/)]}/ /...
}
Copy the code

Let’s take a look at a picture of the effect of removing the language pack on the left

6. externals

In general, third-party packages like jQuery, we introduce them in a CDN way, like this

<-- public/index.html -->
<script src="Https://code.jquery.com/jquery-3.6.0.min. > js"></script>
Copy the code

When we use it, we want to import it as an import, like this

// App.vue\
import $ from 'jquery'
$('.today').text = 'today'
Copy the code

This causes a problem, as jquery is packaged again during build and we can configure itexternalsIgnore the specified dependencies when reaching build

// vue.config.js
module.exports = {
   / /...
   configureWebpack:{
    config.externals = {
      jquery: 'jQuery'}}/ /...
}
Copy the code

7. uglifyjs-webpack-plugin

You can compress the size of your code during build time, but there are several common configurations that can be mentioned separately, such as removing console.log and doing multi-process compression. It can go like this:

// vue.config.js
module.exports = {
   / /...
   configureWebpack:{
    config.optimization.minimizer = [
      new UglifyJsPlugin({
       uglifyOptions: {
        compress: {
         drop_console: true./ / remove the console
        }
        parallel: true.// Default number of concurrent runs: os.cpus().length -1}}})]/ /...
}
Copy the code

8. compression-webpack-plugin

We can compress the code into a.gz file, and the browser will recognize it. You can configure it like this

//vue.config.js
module.exports = {
   / /...
   configureWebpack: {plugins: [
        new CompressionWebpackPlugin()
    ]
  }
  / /...
}
Copy the code

9. DllPlugin and DllReferencePlugin

  • For some third-party packages that have little chance of change, it is not necessary to pack them at the time of build. You can separate these third-party packages and pack them in advance.
  • Webpack itself is meant to represent dependencies between modules, and when we pull some packages out, we need to maintain the previous dependenciesmanifest.jsonThis file. Let’s learn it from the next field trip.

<1> Create a new configuration file, webpack.dll.config.js

// webpack.dll.config.js
module.exports = {
  mode'production'.entry: {
    vue_vendor: ['vue/dist/vue.runtime.esm.js'.'vuex'.'vue-router'.'element-ui'].other_vendor: ['lodash'.'moment']},output: {
    filename'[name].dll.js'.path: path.resolve(__dirname, './public/dll'),
    library'[name]_[hash]'}, \plugins: [
    new webpack.DllPlugin({
      name'[name]_[hash]'.path: path.resolve(__dirname, '[name].manifest.json')]}})Copy the code

<2> For convenience, we write the commands to read this configuration file into package.json, like this. (Need to install Webpack – CLI)

// package.json{..."scripts": {..."dll""webpack --config ./webpack.dll.config.js"}... }Copy the code

< 3 > implementationnpm run dllThen you can see that two manifest files are generated, like this

<4> Modify vue.config.js to introduce dependent files and automatically insert files under DLLS into index.html (here we introduce a plug-inadd-asset-html-webpack-plugin)

module.exports = {
  chainWebpackconfig= > {
    // Multiple manifest.json files can be written multiple times
    config.plugin('vendorDll1')
    .use(webpack.DllReferencePlugin, [
      {
        context: __dirname,
        manifestrequire('./public/manifest/other_vendor.manifest.json')
      }
    ])

    config.plugin('vendorDll2')
    .use(webpack.DllReferencePlugin, [
      {
        context: __dirname,
        manifestrequire('./public/manifest/vue_vendor.manifest.json')})// Automatically insert files under DLL into index.html
    config.plugin('asset')
    .use(AddAssetHtmlWebpackPlugin, [
      [
        {
          filepath: path.resolve(__dirname, 'public/dll/vue_vendor.dll.js'),
          outputPath'dll'.publicPath'/dll'
        },
        {
          filepath: path.resolve(__dirname, 'public/dll/other_vendor.dll.js'),
          outputPath'dll'.publicPath'/dll'}]])}}Copy the code

10. optimization.splitChunks

SplitChunks can be configured to separate common code to prevent duplication, which I haven’t used in my own projects,

//vue.config.js
module.exports = {
   / /...
   chainWebpack: config= > {
      config.optimization.splitChunks({
          chunks: 'all'.cacheGroups: {}})}/ /...
}
Copy the code

5. Effect display

Add several optimization points that do not need to be configured

1. extensions

When importing a module, if no suffix is specified and the file format is expected to match preferentially, we go straight to the vuE-CLI default configurationextensions: ['.mjs', '.js', '.jsx', '.vue', '.json', '.wasm']

2. tree-shaking

We import it, and WebPack automatically removes unused module code

3. Scope hosting

Scope enhancement: for example

let a = 1
let b = 2
let c = a + b

// Webpack automatically optimizes to
c = 3
Copy the code

4. Lazy route loading

To implement lazy route loading, run () => import(‘ XXX ‘) to import routes

Six, summarized

  • This article is a summary of recent improvements to team project Webpack packaging speed.

  • If there is something wrong, please correct it in the discussion section

  • Welcome to our official account:The front small card

  • If you find it helpful, please give it a thumbs up