codeSplitting

webpack4.0(三):codeSplitting

代码分离是 webpack 中最引人注目的特性之一。此特性能够把代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件。代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间。

当我们在做项目的时候,都会引入一些第三方的库来帮助我们开发,例如:lodash、underscore等等,但是这些库在我们打包的时候,会被默认打包到bundle.js中,极大的增加了js的体积,如下图:
image.png
直接把我们的js体积提升到了2.4M,这时我们需要将其从main.js中分割出来,减小main.js的体积。

常见的有三种方式进行代码分割:

  • 在entry手动的配置代码分割。
  • 使用SplitChunksPlugin进行公共代码提取和分割。
  • 动态导入。

entry手动分割

entry: {
    index:'./index.js',
    math:'./math.js'
},

执行打包之后,会被打包成不同的文件。
缺点:

  1. 如果不同的模块中引入有重复的模块,那么重复的模块就会被多次打包。
  2. 不够灵活,不能将核心逻辑进行动态的拆分。

SplitChunksPlugin

SplitChunksPlugin插件可以将相同的模块提取到一起,并且还可以将我们使用的第三方插件单独提取出来,优化打包之后的bundle.js的体积。
具体使用:具体配置请查看官方文档

optimization: {
  splitChunks: {
    chunks: "all",//进行代码分割的时候,all:针对所有的导入  async:只针对异步导入 initial:针对同步代码导入。
    minSize: 30000,//设置最小阀值,只有大于该阀值,才会进行代码分割。
    minChunks: 1,//在分割模块之前共享一个模块的最小块数(设置代码最少被引用次数)
    maxAsyncRequests: 5,//按需加载时的最大并行请求数 超过就不会在做代码分割打包
    maxInitialRequests: 3,//一个入口点的最大并行请求数  超过就不会做代码分割
    automaticNameDelimiter: '~',//打包生成之后,默认情况下,webpack将使用块的来源和名称来生成名称,比如vendor ~main.js。
    name: true,//使得cacheGroups中打包生成的文件名称
    cacheGroups: {//缓存组 打包分组
      vendors: {//配置同步导入 
        test: /[\\/]node_modules[\\/]/,//只有node_module中的才会进入
        priority: -10,//值越大 优先级越高
        filename: 'vendors.js'
      },
      default: {
        // minChunks: 2,
        priority: 0,
        reuseExistingChunk: true,// 如果模块已经被打包了,在此遇到的时候 直接忽略,直接使用以打包好的模块。
        filename:'default.js'
      }
          }
    }
}

动态导入

动态导入有两种方式:

  • 使用ECMAScript提案的import()语法
  • 使用webpack特定的语法:require.ensure()

第一种方式:使用webpackChunkName

function getComponent(){
    return import(/* webpackChunkName:"lodash" */ "lodash").then(({ default:_ }) => {
        let div = document.createElement('div');
        div.innerHTML = _.join(['hello','world','lodash']);
        return div;
    })
};

getComponent().then((ele) => {
    document.body.appendChild(ele)
})

打包之后,会在dist目录下生成一个vendors~lodash.js文件,表示它是vendors下面的一个文件。之所以前面会带一个vendors,这是因为cacheGroup有一个默认配置,如果想要去除,将vendors和default配置为false即可。
由于 import() 会返回一个 promise,因此它可以和 async 函数一起使用。但是,需要使用像 Babel 这样的预处理器和Syntax Dynamic Import Babel Plugin

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!