webpack5分离chunk的一些方式

301 阅读2分钟

1. 将多入口之间公用的模块分离出来

  • 如果入口 chunk 之间包含一些重复的模块,那么这些重复模块会被引入到各个 bundle 中。

解决方式1: 使用入口依赖的方式,在入口entry配置中配置 dependOn 选项,以在多个 chunk 之间共享模块:

entry: {
      index: {
        import:  './src/index.js',
        dependOn: 'shared',
      },
      other: {
        import: './src/other.js',
        dependOn: 'shared',
      },
      shared: 'lodash',
    },

解决方式2:使用SplitChunksPlugin 插件的 optimization.splitChunks 配置选项

splitChunks: {
        // include all types of chunks
        chunks: 'all',
      },  

测试脚本

入口文件index.js

import { throttle } from 'lodash'
import { test } from "./src/test";

test()

function run() {
    for (let i = 0; i < 1000; i++) {
        throttle(() => {
            console.log(i, '66666')
        }, 10)
        
    }
}
run()

入口文件other.js

import { test } from "./src/test";
import { debounce } from 'lodash'

test()

function run() {
    for (let i = 0; i < 1000; i++) {
        debounce(() => {
            console.log(i)
        }, 10)
    }        
}

run()

入口文件index.js和other.js都使用了lodash库,通过上述方式1/2会将lodash库单独生成一个chunk。下面截图中标红的文件就是单独生成的lodash库的chunk。

image.png

optimization.splitChunks官方介绍:webpack.docschina.org/plugins/spl…

2. 将runtime脚本分离出去

  • webpack配置如下:
 optimization: {
      runtimeChunk: 'single',   
 },

使用 optimization.runtimeChunk 选项将 runtime 代码拆分为一个单独的 chunk。将其设置为 single 以便为所有 chunk 创建一个 runtime bundle

  • 打包截图如下:

image.png

runtime生成单独的chunk。

3. 将第三方库提取到单独的 vendor chunk 中

  • 配置如下
   optimization: {
      splitChunks: {
        cacheGroups: {
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            name: 'vendors',
            chunks: 'all',
          },
        }, 
      },  
    },  
  • 测试脚本
import { throttle } from 'lodash'
import { createApp, h } from 'vue'

import { test } from "./src/test";
test()


function run() {
    for (let i = 0; i < 1000; i++) {
        throttle(() => {
            console.log(i, '66666')
        }, 10)
        
    }
}
run()

// 
function createVueRootElement() {
    let root = document.createElement('div')
    root.setAttribute('id', 'app')
    document.body.appendChild(root)
}

function createVueApp() {
    createVueRootElement()
    let app = createApp({
        render() {
            return h('div', { innerHTML: "hello vue"})
        }
    })
    app.mount('#app')
}
createVueApp()

在上述脚本中使用了第三方库lodash和vue,打包后第三方库lodash和vue的代码单独生成一个chunk

image.png

4. 将第三方包单独打包

optimization: {
        usedExports: true,
        splitChunks: {
            chunks: 'all',
            cacheGroups: {
                lodash: {
                    name: 'lodash-es', //生成后的文件名称
                    test: /[\\/]node_modules[\\/]lodash-es/,
                    priority: -10
                },
               
            }
        }
    },

5. 异步加载的模块默认分离

string.js文件

class String {

    contact(arr) {
        return ''.concat(...arr)
    }
}

export default String

index.js文件中异步加载string.js

  let String = import('./src/string')
 
 let s = new String()
 s.contact('a', 'b')

打包结果如下 image.png

6. DllPlugin 和 DllReferencePlugin 用某种方法实现了拆分 bundles,同时还大幅度提升了构建的速度

官方介绍:webpack.docschina.org/plugins/dll…