webpack打包后引用cdn的js_webpack模块抽取详解

本文详细介绍了webpack的基本概念,包括模块、块和资源的定义,以及入口文件和异步文件的区别。接着探讨了webpack的打包原理,强调了模块抽取对于优化打包速度和页面加载速度的重要性。通过分析打包后的输出文件,作者推荐使用webpack-bundle-analyzer进行分析,并解释了如何通过配置实现公用模块的抽取,以减少文件体积并提高缓存效率。最后,列举了模块抽取的几个关键配置选项,如minChunks、minSize等,帮助读者理解如何进行更有效的模块管理。
摘要由CSDN通过智能技术生成
推荐一个测试分块的工具:链接

webpack是一个模块打包工具。它会先从配置的入口开始,然后处理相关的依赖,并转换相关文件,最终输出的一些文件。为什么要研究分块呢,他能让我们更好的掌握webpack的输出规则,并且有助于提升打包速度和页面加载速度。像我之前,每次打包项目的时候6G内存都不够用,时常会在打包的过程中异常退出。后来我发现一个图表库被多个页面引用,每个页面都会打包一份,并且很多库也是一样。解决之后打包的体积小了很多,并且构建速度加快了不少。

基本概念

模块(module)、块(chunk)、资源(asset):

  • 模块:一个文件即为一个模块
  • 块:通常由一个及以上的模块构成
  • 资源:最终输出的文件

入口文件、异步文件

入口文件:通常是配置的入口文件,在首次进入页面时会加载

异步文件:通过import函数导入的文件,只有执行到时会加载

打包原理

webpack会先从入口文件开始分析依赖。入口配置可以是字符串、数组、对象,当入口的配置是字符串或者数组时,最终也会转为对象的形式,也就是会转为以main命名块的对象形式。入口配置对象的每一个属性,都会生成对应的文件。这个文件包含了直接导入(不包含按需加载的模块)进来的所有模块文件,每个入口都含有webpack的运行时,都可以独立运行。然后每碰到按需加载的文件,都会生成对应的文件。这个文件包含所有非异步引用的模块,并且会剔除已经存在入口文件的模块。

示例:

//one.js
import A from './A'
import(/* webpackChunkName: "B" */ './B');
import(/* webpackChunkName: "C" */ './C')
//B.js
import A from './A'
import D from './D'
import E from './E'
//C.js
import A from './A'
import D from './D'

//如果关闭所有模块抽取优化,最终生成的文件如下
one.js
//包含webpack运行时代码,one文件的代码,A文件的代码
B.chunk.js
//包含B文件的代码,还有D和E文件的代码
C.chunk.js
//包含C文件的代码,还有D文件的代码

我们推荐使用webpack-bundle-analyzer来分析最终的输出文件,上面的输出如下:

7ebb215f7385876cfc1e67df19351c3b.png

抽取模块

为什么要抽取公用模块呢?我们明显看到上面的B和C文件都包含了D文件,如果这个文件比较大或者这个文件被多个文件引用,那么我们应该把这个文件单独抽个文件,这样打包后文件体积会减少,并且有助于单独缓存,减少加载一些重复的代码。

现在试想下用什么样的策略来抽取模块呢?我们看下webpack中关于分块的配置。

module.exports = {
  //...
  optimization: {
    splitChunks: {
      //选择那些块进行优化,入口块或者异步块或者全部
      chunks: 'async',
      //生成块的最小尺寸
      minSize: 30000,
      //生成块的最大尺寸。如果生成块尺寸太大,会拆分成小的块,方便浏览器缓存更小的模块
      maxSize: 0,
      //拆分前必须共享模块的最小数
      minChunks: 1,
      //异步加载最大并行请求数
      maxAsyncRequests: 5,
      //入口加载最大并行请求数
      maxInitialRequests: 3,
      //默认使用来源和名称生成抽取后的模块名称(例如vendors~main.js),此选项用来指定定界符。
      automaticNameDelimiter: '~',
      //拆分块的名称
      name: true,
      //抽取模块就是根据此来拆分的,可以继承和/或覆盖splitChunks.*中的部分选项
      cacheGroups: {
        default: {
          //优先级
          priority: -20,
          //控制此缓存组选择的模块
          test:/D/,
          //仅在初始块时覆盖文件名
          filename:'default',
          //为true后会忽略minSize、minChunks、maxAsyncRequest、maxInitialRequests的规则
          enforce:true,
          //是否重用模块,例如编译完成后有一个异步的a.js,如果一个缓存组抽取的模块与该文件相同
          //此时设置为true会放弃生成新的模块,继续保持a.js,这会影响最终的文件名称
          reuseExistingChunk: true
        }
      }
    }
  }
};

webpack中首先遍历每个模块,然后用每个模块去逐个匹配缓存组(会从高优先级开始),如果能匹配到,然后判断能不能满足一些规则生成新的文件。下面是一些规则:

  1. 该模块是否满足chunks设置。比如他是异步加载的模块,当前的缓存组设置了只需要对入口加载的文件做优化,那他就不满足了
  2. 该模块是否满足minChunks设置。比如一个模块,我设置的最小共享块数是2,但它只被一个模块引用,那他就不满足
  3. 生成的模块是否满足minSize设置。比如我抽取的模块最终尺寸很小,那就没必要单独抽取一个模块
  4. 生成的模块是否满足maxInitialRequests设置。比如生成的模块属于入口加载的文件,也要控制一次不要加载过多的文件
  5. 生成的模块是否满足maxAsyncRequest设置。比如生成的模块属于按需加载的文件,也要控制一次不要加载过多的文件

而对于上面的实例,如果我们需要吧D模块单独抽个文件,那应该这样配置:

 splitChunks:{
    cacheGroups:{
      "common":{
        minSize:1,
        minChunks:2,
        test:/D/
      }
    }
  }

942dd945848c50e32c9eaa19f254953d.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值