The original address

Usually we use vuE-CLI to develop multiple pages, I wonder if you notice a problem?

Default: WebPack packs the multi-portal common component libraries, etc., into a vendor chunk JS

Now suppose there are two pages:

The admin entry uses the Element-UI component library and the Echarts chart library, and the Index entry uses the iView component library

I. Problem description and solution

1. Problems of multiple entrances

Then there’s the problem:

  1. Play outchunk-vendor.xxxx.jsWill containelement-uiandechartsandiviewComponent library, so JS volume can be very large
  2. chunk-vendor.xxxx.jsDefault is allnode_modulesThe following collection of libraries
  3. The index entry just uses the iView because it needs to be loadedchunk-vendor.xxxx.js, causing unnecessary loading
  4. The admin entry will also introduce an additional iView

2. My expected effect

So what should we expect for the above problems?

  1. Index entry and Admin are individually packaged and imported into their respective libraries as needed
  2. Libraries common to index and admin are packaged only once

3. Feasible solutions

In view of the above requirements, I have explored the following two schemes:

  1. Delete default splitChunk configuration, add common chunks, separate UI libraries (subtracting)
  2. Delete default splitChunk configuration, extract common resources (add)

2. Solution 1: Make common chunks and separate their UI libraries

Solution 1: Delete the default splitChunk configuration, add common chunks, and separate their UI libraries

Delete the default splitChunk configuration to remove the default webpack configuration, because the default webpack configuration is to package the libraries used in node_modules into a chunk-vendor.xxxx.js.

It is mainly divided into three steps:

  • Step 1: Delete the default splitChunk configuration
  • Step 2: Separate splitChunk
  • The third part: multi-entry, individually configured chunks

The detailed configuration is as follows:

let pages = {
  index: {
    entry: "src/main.js".template: "public/index.html".// Special note: since each entry separates chunks separately, the names of the chunks need to be listed
    chunks: [
      "index".// Note: this is the chunk of the page name. The following chunk names need to match the corresponding name of splitChunk
      "chunk-vendors".// This is chunk under node_modules
      "chunk-common".// This is the chunk shared by admin and Index entries
      "chunk-iview" // Single chunk of index]},admin: {
    entry: "src/admin.js".template: "public/admin.html".// Special note: since each entry separates chunks separately, the names of the chunks need to be listed
    chunks: [
      "admin".// Note: this is the chunk of the page name. The following chunk names need to match the corresponding name of splitChunk
      "chunk-vendors".// This is chunk under node_modules
      "chunk-common".// This is the chunk shared by admin and Index entries
      "chunk-element-ui".//a single chunk of admin
      "chunk-echarts".//a single chunk of admin
      "zrender" // Echarts uses zrender]}};module.exports = {
  pages,
  publicPath: process.env.BASE_URL,
  outputDir: "dist".assetsDir: "assets".runtimeCompiler: true.productionSourceMap: false.parallel: true.css: {
    // Whether to extract the CSS production environment Can be set to true
    extract: true
  },
  chainWebpack: config= > {
    if (process.env.NODE_ENV === "production") {
      // Delete the default splitChunk
      config.optimization.delete("splitChunks"); }},configureWebpack: config= > {
    // Add hash to the output js name
    config.output.filename = "[name].[hash].js";
    config.output.chunkFilename = "[name].[hash].js";

    config.optimization = {
      splitChunks: {
        cacheGroups: {
          // Remove the public resource from all entries into a chunk
          common: {
            name: "chunk-common".chunks: "initial".minChunks: 2.maxInitialRequests: 5.minSize: 0.priority: 1.reuseExistingChunk: true.enforce: true
          },
          // Remove the library from node_modules to a chunk
          vendors: {
            name: "chunk-vendors".test: /[\\/]node_modules[\\/]/.chunks: "initial".priority: 2.reuseExistingChunk: true.enforce: true
          },
          // Since the Index entry uses iView, iView should be handled separately so that the admin entry does not use this js
          iview: {
            name: "chunk-iview".test: /[\\/]node_modules[\\/]iview[\\/]/.chunks: "all".priority: 3.reuseExistingChunk: true.enforce: true
          },
          // Since the admin entry uses elemental-ui, we can handle it separately so that the index entry does not use this js
          element: {
            name: "chunk-element-ui".test: /[\\/]node_modules[\\/]element-ui[\\/]/.chunks: "all".priority: 3.reuseExistingChunk: true.enforce: true
          },
          // Since the admin entry uses echarts, we should separate echarts so that the index entry does not use this js
          echarts: {
            name: "chunk-echarts".test: /[\\/]node_modules[\\/](vue-)? echarts[\\/]/.chunks: "all".priority: 4.reuseExistingChunk: true.enforce: true
          },
          // Since Echarts uses the Zrender library, it needs to be pulled out so that it is not placed in the public chunk
          zrender: {
            name: "zrender".test: /[\\/]node_modules[\\/]zrender[\\/]/.chunks: "all".priority: 3.reuseExistingChunk: true.enforce: true}}}}; }};Copy the code

3. Solution 2: Delete the default splitChunk configuration and extract public resources

If webpack is multi-portal, delete the default splitChunk configuration and the multi-portal will be packaged separately, but the common resources will not be extracted.

In view of the above situation, we can achieve the purpose of optimization through the following three steps:

  • Step 1: Delete the default splitChunk
  • Step 2: Pull away from common entry resources
  • Step 3: Configure chunks individually for each entry

The detailed configuration is as follows

const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;
let pages = {
  index: {
    entry: "src/main.js".template: "public/index.html".chunks: ["index"."chunk-common"] // The name of the entry, i.e. the key value, and the name of the public chunk
  },
  admin: {
    entry: "src/admin.js".template: "public/admin.html".chunks: ["admin"."chunk-common"] // The name of the entry, i.e. the key value, and the name of the public chunk}};module.exports = {
  pages,
  publicPath: process.env.BASE_URL,
  outputDir: "dist".assetsDir: "assets".runtimeCompiler: true.productionSourceMap: false.parallel: true.css: {
    // Whether to extract the CSS production environment Can be set to true
    extract: true
  },

  chainWebpack: config= > {
    // Delete the default splitChunk
    config.optimization.delete("splitChunks");
  },
  configureWebpack: config= > {
    // js output config
    config.output.filename = "[name].[hash].js";
    config.output.chunkFilename = "[name].[hash].js";

    config.optimization = {
      splitChunks: {
        cacheGroups: {
          common: {
            // Extract the public chunk required by all entry pages
            name: "chunk-common".chunks: "initial".minChunks: 2.maxInitialRequests: 5.minSize: 0.priority: 1.reuseExistingChunk: true.enforce: true}}}}; }};Copy the code

Iv. Comparison of schemes

  1. Option 1: Delete the default splitChunk configuration, add common chunks, and separate their UI libraries (subtraction)

Advantages: Separate each chunk without processing the common chunk. Disadvantages: If multiple portals use a large number of libraries, separate them

Applicable scenario

Suitable for: multiple entry pages are highly coupled (that is, multiple entry pages use more common resources), with only a few component libraries

  1. Delete default splitChunk configuration, extract common resources (add)

Advantages: It is not necessary to separate each chunk, but only need to process the common chunk. Disadvantages: If the multi-entry common library is used more, the extraction needs to be more detailed

Applicable scenario

Suitable for: multiple entry pages with low coupling (that is, multiple entries use less common resources, usually multiple entries have no relationship)

The original address