• webpack 打包优化 - splitChunks


    打包时会遇到的问题:

    1. 打包文件过大,首屏加载时间过长,js阻塞页面渲染导致白屏
    2. 改动业务代码后,对于第三方库也会一并重新打包到一个出口文件,浏览器无法利用缓存来减少请求和加载的时间

    针对以上两个问题,利用splitChunks可以将各个模块进行分割,并提取出相同部分代码,从而缓解一个js过大、不能缓存第三方库的问题。

    webpack 从 4.x 开始支持了零配置的特性,同时对块打包也做了优化,CommonsChunkPlugin已经被移除了,现在是使用optimization.splitChunks代替。(webpack5 splitChunks 配置和 webpack4 大体上一样)

    概念区分 - module、bundle、chunk都是什么?

    在说SplitChunks前,先来了解几个概念,module、bundle、chunk都是什么?

    module:模块,在webpack中任何文件都可以作为一个模块,借用官网的图片,左侧的这些类型文件,都可以认为是一个模块,只是需要配置不同的loader,将文件转换成webpack可以支持打包的文件。

    chunk:编译完成准备输出时,webpack 将module 按特定规则组成的一个个 chunk

    bundle:webpack 处理好chunk文件后,生成运行在浏览器中的代码

    SplitChunks 插件是什么呢

    简单的来说就是 Webpack 中一个提取或分离代码的插件,主要作用是提取公共代码,防止代码被重复打包,拆分过大的js文件,合并零散的js文件。

    提到前端优化,提取公共代码是必不可少的手段。
    在 Webpack 出现前,提取公共代码是人为去处理,而 SplitChunks 插件的作用就是通过配置让 Webpack 去帮你提取公共代码。SplitChunksPlugin 默认配置适用大部分场景。

    打包默认情况下只会影响按需加载模块,因为对初始块也进行优化打包会影响 HTML 中的 script 标签数,增加请求数。

    默认情况(webpack 的默认配置)下 webpack 会根据下述条件自动进行代码块分割:

    • 共享模块(至少被引用 2次)或者 node_modules 模块
    • 新代码块大于 20kb(min+gziped之前的体积)
    • 按需加载块时的最大并行请求数将低于或等于 30
    • 初始页面加载时的最大并行请求数将低于或等于 30

    SplitChunks插件配置选项

    • 同步加载的模块:通过 import xxx 或 require(‘xxx’) 加载的模块。
    • 异步加载的模块:通过 import(‘xxx’) 或 require([‘xxx’],() =>{}) 加载的模块。
    • chunks: 表示哪些代码需要优化,有三个可选值:initial(初始块)、async(按需加载块)、all(全部块),chunks 选项,决定要提取哪些模块
      • 默认是 async :只提取异步加载的模块出来打包到一个文件中。
      • initial 模块下只优化初始模块,也就是说 webpack 只会对初始模块做打包优化。如果 xxx 在项目中异步加载了,也同步加载了,那么 xxx 这个模块会被提取两次,分别打包到不同的文件中。
      • all 模块下同时对初始模块和异步模块做打包优化,不管异步加载还是同步加载的模块都提取出来,打包到一个文件中。
    • minSize: 规定被提取的模块在压缩前的大小最小值,单位为字节。表示在压缩前的最小模块大小,默认为 20000
    • minChunks: 表示被引用次数,默认为 1
    • maxAsyncRequests: 按需加载时候最大的并行请求数,默认为 30
    • maxInitialRequests: 一个入口最大的并行请求数,默认为 30
    • enforceSizeThreshold:强制执行拆分的体积阈值
    • cacheGroups: 缓存组。缓存组的属性除上面所有属性外,还有 test, priority, reuseExistingChunk
      • test: 用于控制哪些模块被这个缓存组匹配到
      • priority: 缓存组打包的先后优先级
      • reuseExistingChunk: 如果当前代码块包含的模块已经有了,就不在产生一个新的代码块

    实际使用情景:

    1. 设置 chunks: initial || all 都可以提取出第三方库。但是它是把所有第三库提取出来,所以我们在只提取 react 和 react-dom 的情况下,需要自定义一个 cacheGroup。

    1. // webpack.config.js
    2. optimization: {
    3. splitChunks: {
    4. chunks: 'all',
    5. cacheGroups: {
    6. react: {
    7. name: 'react',
    8. test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
    9. }
    10. }
    11. }
    12. }

    安装  webpack-bundle-analyzer, 可以查看打包体积情况,在package.json 中,npm run build 的地方写一个 --report 就会在打包文件中生成一个 report.html, 打开可以看到打包体积情况。  "build": "vue-cli-service build --report"

    2. 比如发现chunk-vendors.js的大小有点大了,有1.91MB,还是项目初始化时需要加载的 js 文件,大小过大会导致首屏加载时间过长。

    要优化一下,两种方法:可以用SplitChunks优化。

    例如要把element从chunk-vendors.js提取出来,就在cacheGroups 进行对应配置:

    1. chainWebpack(config) {
    2. config.when(process.env.NODE_ENV != 'development',
    3. config => {
    4. config.optimization.splitChunks({
    5. chunks: 'all',
    6. cacheGroups: {
    7. // 第三方组件
    8. libs: {
    9. // 指定chunks名称
    10. name: 'chunk-libs',
    11. //符合组的要求就给构建venders
    12. test: /[\\/]node_modules[\\/]/,
    13. //priority:优先级:数字越大优先级越高,因为默认值为0,所以自定义的一般是负数形式,决定cacheGroups中相同条件下每个组执行的优先顺序。
    14. priority: 10,
    15. // 仅限于最初依赖的第三方
    16. chunks: 'all'
    17. },
    18. elementUI: {
    19. // 将elementUI拆分为单个包
    20. name: 'chunk-elementUI',
    21. // 重量需要大于libs和app,否则将打包到libs或app中
    22. priority: 20,
    23. // 为了适应cnpm
    24. test: /[\\/]node_modules[\\/]_?element-ui(.*)/
    25. },
    26. //公共组件
    27. // commons: {
    28. // name: 'chunk-commons',
    29. // // can customize your rules
    30. // test: resolve('src/components'),
    31. // minChunks: 3,
    32. // priority: 30,
    33. // //这个的作用是当前的chunk如果包含了从main里面分离出来的模块,则重用这个模块,这样的问题是会影响chunk的名称。
    34. // reuseExistingChunk: true,
    35. // //最大初始化加载次数,一个入口文件可以并行加载的最大文件数量,默认3
    36. // maxInitialRequests: 3,
    37. // //表示在分离前的最小模块大小,默认为0,最小为30000
    38. // minSize: 0
    39. // },
    40. }
    41. })
    42. })
    43. }

    总结:

    webpack5 默认情况下只对异步模块做打包优化,额外的打包必须满足 4 个条件(webpack 的默认配置,可修改)。根据需求可调整为只对初始模块做打包优化,或者初始和异步模块一起优化。同时可配置自己的打包规则。

    简而言之:chunks 控制打包作用范围,其他控制打包规则。

    webpack5 的 splitChunks 功能是比较强大的,不过推荐还是使用默认模式,或者提取一下第三方库。

  • 相关阅读:
    C++中&&的作用
    39页智慧粮库解决方案
    今日研究-数据结构与算法中排序方法都有哪些
    Nodejs操作缓存数据库-Redis
    STM32、ESP8266与MQTT连接阿里云物联网的串口通信异常解析
    Vue2 解决computed返回值未能渲染到DOM的问题
    Acwing 143. 最大异或对
    03- ROS 常用指令
    BN、CBN、CmBN 的对比与总结
    SQL学习--SQL函数基础用法
  • 原文地址:https://blog.csdn.net/weixin_54714100/article/details/137955610