webpack系统学习(五)webpack和Code Solitting 代码分割

观察下面的代码:

//index.js
import _ from 'lodash';//大小为1mb

console.log(_.join(['a', 'b', 'c'],'-'))//这一行的大小为1mb

我们假设lodash包的大小为1mb,index.js中的console.log(_.join(['a', 'b', 'c'],'-')) 也需要1mb的大小。这样打包之后,我们发现:

  1. 打包后生成的main.js文件较大(2mb左右),加载时间会很长;
  2. 一般情况下,我们不会更改lodash包中的内容,但是index.js中的代码我们可能会随着业务需求的改变而修改,所以当我们改变了index.js 的内容之后,用户需要重新加载一次main.js,响应时间较长,浪费了网络资源。
    有没有方法能够使lodash和业务代码分开打包呢?
    这其实就是代码分割

手写代码分割:

我们新建一个lodash.js

import _ from 'lodash';

window._ = _

lodash.js文件中单独引入lodash,并将lodash挂载到window上面。
修改index.js

console.log(_.join(['a', 'b', 'c'],'-'))

然后修改webpack.config.js:

...
  entry: {
    lodash: './src/js/lodash.js',//添加新的入口文件,并且lodash.js应该在main的上面
    main: './src/js/index.js'
  },
...

现在再次打包,我们发现打包后生成了两个文件,分别是main.js(1mb)lodash.js(1mb),如果此时我们的业务逻辑发生了变更修改了main.js,用户就只需要再次加载main.js就行了,而不需要加载没有发生改变的lodash.jslodash.js可以直接从缓存中进行加载。

注意: 这两种方式下的第一次加载都需要加载接近2mb的文件,但是代码分割后的打包文件有两个,浏览器可以并行加载(并不是一定会并行加载),加载的时间也有可能减少。但是第二次加载时,如果业务代码发生了改变,代码分割的优势就出来了。

webpack中的Code Splitting

手动进行代码分割是十分麻烦的,而webpack中的一些插件可以帮助我们自动进行代码分割。
修改webpack.config.js:

  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  }
//index.js
import _ from 'lodash';

console.log(_.join(['a', 'b', 'c'],'-'))

再次打包,最后仍然可以生成两个打包文件:
在这里插入图片描述
这里的index.js中是同步代码,如果我们异步引入lodash,即使不配置 splitChunks: { chunks: 'all' },webpack依然会进行代码分割,因为其具有默认配置项 splitChunks: { chunks: 'async' },表示webpack默认会对异步引入的包进行代码分割,例如下面的index.js

//index.js
function getComponent(){
  return import('lodash').then(({default: _ })=>{
    var ele = document.createElement('div')
    ele.innerHTML = _.join(['Niall','August'],' ')
    return ele
  })
}

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

打包后:
在这里插入图片描述
其中的0.js就包含了异步引入的lodash包,而main.js中仍然只包含了业务代码。
这里还可以使用webpack的魔法注释修改0.js为自己想命名的名字:

//index.js
function getComponent(){
  return import(/* webpackChunkName:"lodash" */'lodash').then(({default: _ })=>{
    var ele = document.createElement('div')
    ele.innerHTML = _.join(['Niall','August'],' ')
    return ele
  })
}

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

打包后:
在这里插入图片描述

SplitChunksPlugin 配置参数详解

如果我们没有配置SplitChunksPlugin,那么webpack将使用一下的默认配置项:

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks: 'async',
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true//复用已被打包的模块
        }
      }
    }
  }
};
配置项取值作用
chunksall对所用的代码进行代码分割
chunksasync仅仅对异步的代码进行代码分割
cacheGroups.group一个对象,如vendors:{……}打包的文件如何分组分组打包的判断依据,详情可见后文
minSizeint当文件大小小于该值(以字节为大小单位)的时候,不进行代码分割
maxSizeint当打包后的代码文件大小大于该值时,对其再进行一次代码分割(一般不使用)
minChunksint当该模块的引入次数大于该值时才对该模块进行代码分割
maxAsyncRequestsint最多将打包文件分割为该值个文件,例如,当值为5的时候,前四个需要分割打包的group会分别形成js文件,之后的group全部加入到第五个js文件(一般情况下不需要改变)
maxInitialRequestsint和maxAsyncRequests 类似,但是仅对入口文件起效(一般情况下不需要改变)
automaticNameDelimiter任意字符文件名中的连接符,默认是‘~’
nameboolean是否启用自定义文件名(一般不需要改变)

vendors表示一个打包组,它的配置项表明了那些文件可以分到vendors下, vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }test 后面是一个正则表达式,当文件资源路径符合该正则表达式时,就将该文件归于vendors,当某一文件符合多个cacheGroups.group的要求时,根据cacheGroups.group.priority来决定其归于哪一个cacheGroups.group

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值