purpose

Vue is packaged in a single file. The size of vendor is too large, which affects page performance. Vue related (vue, vuex, vue-Router), element-ui, echarts (echarts, zrender) are extracted as separate JS files to reduce vendor size. At the same time, pulling out modules that are less likely to change also has some benefit for version iteration of the project (avoiding unnecessary file hash changes that result in re-requests for data).

Begin to dig a hole

Vue scaffolding default commonsChunkPlugin configuration:

// ./build/webpack.prod.conf.js
const webpackConfig = merge(baseWebpackConfig, {
  ...
  plugins: [
    ...
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks (module) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '.. /node_modules'= = =))0)}}),new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest'.minChunks: Infinity
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'app'.async: 'vendor-async'.children: true.minChunks: 3}),... ] });Copy the code

The default configuration here is to remove all public plug-ins from vendor and webpack-related runtime modules from manifest from a single entry: App (Entry Chunk).

The initial renovation is as follows:

// Remove required module data from vendor
new webpack.optimize.CommonsChunkPlugin({
  name: 'echarts'.chunks: ['vendor'],
  minChunks (module) {
    // any required modules inside node_modules are extracted to vendor
    return (
      module.resource &&
      /echarts|zrender/.test(module.resource)
    )
  }
}),
new webpack.optimize.CommonsChunkPlugin({
  name: 'element-ui'.chunks: ['vendor'],
  minChunks (module) {
    // any required modules inside node_modules are extracted to vendor
    return (
      module.resource &&
      /element-ui/.test(module.resource)
    )
  }
}),
new webpack.optimize.CommonsChunkPlugin({
  name: 'vue'.chunks: ['vendor'],
  minChunks (module) {
    // any required modules inside node_modules are extracted to vendor
    return (
      module.resource &&
      /vue/.test(module.resource)
    )
  }
}),
Copy the code

With the above code, packaging does take the element- UI, Echarts, and Vue out of the equation:

The webpackJsonp is not defined, as you can imagine, the running environment after the WebPack is packaged is faulty, according to the official website

The CommonsChunkPlugin is used to run the webpack. The code is split into the manifest.

  1. The manifest packaging error
  2. Not Defined is common in normal development work, and the runtime webpackJsonp is not defined

In conjecture 1, since only the chunk corresponding to the regular is removed from the vendor, it hardly affects the pulling out of the running environment of Webpack, so obviously the probability of error is very small.

Most likely a guess 2 question, check out the packaged index.html file

Compare this to the index.html in our other (normal) environment

Obviously, the order of script calls to manifest.js has changed so that webpackJsonp is not defined, so we need to change the order in which chunks are written to index.html

Writing chunks is the job of the HtmlWebpackPlugin

Vue scaffolding out, default configuration:

// webpack.prod.conf.js
new HtmlWebpackPlugin({
  ...
  // necessary to consistently work with multiple chunks via CommonsChunkPlugin
  chunksSortMode: 'dependency'
}),
Copy the code

ChunksSortMode: allows controlling the ordering of chunks before inserting HTML

Allows to control how chunks should be sorted before they are included to the HTML. Allowed values are 'dependency' | 'none' | 'auto' | 'manual' | {Function}
Copy the code

‘dependency’ : sorting by file dependencies, not available above version 4.0 ‘auto’ : default ‘none’ ‘manual’ : custom sorting

ChunksSortMode: ‘dependency’ : / / dependency = ‘dependency’; / / dependency = ‘dependency’;

Note that app.js depends on other plug-ins and library files, so it must be loaded last, otherwise it will cause a lot of not defined errors

// webpack.prod.conf.js
new HtmlWebpackPlugin({
  ...
  // necessary to consistently work with multiple chunks via CommonsChunkPlugin
  chunksSortMode: 'manual'.chunks: ['manifest'.'vendor'.'vue'.'element-ui'.'echarts'.'app']}),Copy the code

The packed files are in order:

Then put into the test environment, it can run normally….

Doubts point

What is a bit odd is that, on the day before, I put it into the test environment according to the above configuration, there will be the following error (the chart here is a screenshot of a similar error, which are both ‘call’ of underpay ‘in the manifester.js)

I added the following code because I thought the manifest chunks were incomplete

new webpack.optimize.CommonsChunkPlugin({
  name: 'manifest'.chunks: ['vendor'.'vue'.'element-ui'.'echarts'.'app'].minChunks: Infinity
}),
Copy the code

Magically no problem QAQ

Then the next day to remove the code and repackage, but without the above problem, you big guys have any good ideas?

Compare splitChunks briefly

The default configuration of VUE-CLI3 for splitChunks is:

// code splitting
if(process.env.NODE_ENV ! = ='test') {
  webpackConfig
    .optimization.splitChunks({
      cacheGroups: {
        vendors: {
          name: `chunk-vendors`.test: /[\\/]node_modules[\\/]/.priority: - 10.chunks: 'initial'
        },
        common: {
          name: `chunk-common`.minChunks: 2.priority: - 20.chunks: 'initial'.reuseExistingChunk: true}}})}Copy the code

In vue. Config. js, the separation of element-UI and vue is very simple, mainly dealing with priority

module.exports = {
  ...
  chainWebpack: config= > {
    // code splitting
    config.optimization.splitChunks({
      cacheGroups: {
        vendors: {
          name: `chunk-vendors`.test: /[\\/]node_modules[\\/]/.priority: - 10.chunks: 'initial'
        },
        common: {
          name: `chunk-common`.minChunks: 2.priority: - 20.chunks: 'initial'.reuseExistingChunk: true
        },
        // Separate out the element-ui
        element: {
          name: `element-ui`.test: /element-ui/.priority: 10.chunks: 'all'
        },
        // Separate vUe-related items
        vue: {
          name: `vue`.test: /vue/.priority: 20.chunks: 'all'}}}); }};Copy the code

The CommonsChunkPlugin is very simple.

The above is just a little opinion, if there is a mistake, don’t hesitate to give advice !!!!!