6

webpack的chunk生成逻辑 - SegmentFault 思否

 2 years ago
source link: https://segmentfault.com/a/1190000040955485
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

webpack的chunk生成逻辑

发布于 今天 15:34

刚接触webpack时,使用webpack打包后只会生成一个被称为bundle的文件,在慢慢熟悉webpack后,如果同时对于前端优化有一定的了解,就会尝试将臃肿的bundle拆分成多个小文件并按需加载。

本文希望通过对webpack的部分配置进行说明,让读者对相关的操作有一定了解和掌握。以下操作均是在webpack@4环境下的说明。

webpack中通过配置的optimization.splitChunks来实现这样的效果,该配置也是SplitChunksPlugins插件的配置。

webpack为optimization.splitChunks提供了默认值,让我们来看看:

// 
// ** 默认的splitChunks内容 **
//
{
  chunks: 'async',
  minSize: 30000,
  maxSize: 0,
  minChunks: 1,
  maxAsyncRequests: 5,
  maxInitialRequests: 3,
  automaticNameDelimiter: '~',
  automaticNameMaxLength: 30,
  name: true,
  cacheGroups: {
    vendors: {
      test: /[\\/]node_modules[\\/]/,
      priority: -10
    },
    default: {
      minChunks: 2,
      priority: -20,
      reuseExistingChunk: true
    }
  }
};

让我们来仔细看看其中的配置

chunks

通过配置该项,开发者可以选择需要进行优化的chunk,被选中的chunk,其中的modules将被分析,并按照一定的策略生成新的chunk。

允许allasyncinitial(chunkname) => boolean四种值,具体效果如下:

  • initial: 所有的立即加载的chunk(例如bundle文件)将被检查
  • async: 所有延迟加载的chunk将被检查
  • all: 等价于initial + async效果,所有的chunk都将被检查
  • (chunkname) => boolean: 函数形式可以提供更细粒度的控制

默认情况为async,所以我们的bundle不会被优化,这里可以尝试修改为initial之后再进行一次编译。

{
  chunks: 'initial',
}

除了生成bundle之外,可能还会有名为vendors~xxx.js的文件。(如果没有生成的话,可以尝试在代码中引入node_modules中的包,再重新编译后查看结果。)

两次编译结果的变化,即chunksasync变为initial后,bundle文件因作为一个立即加载的chunk而被优化了。

minSize、maxSize

见名知意,minSizemaxSize限定了新生成的chunk的文件的最小/最大尺寸。只有当准备生成的chunk的最大和最小文件尺寸,只有在这个尺寸内的chunk文件才会被生成,否则代码会保持原样。

minSize=30000表示chunk最小应该有30000bytes。
maxSize=0表示不限制chunk的最大尺寸。如果设置为一个其他的合理值,例如150000,生成的chunk超过了maxSize的情况下,该chunk将被进一步拆分成更小的chunk。

cacheGroups

cacheGroups是splitChunks配置的一个关键配置,其决定了module应该如何合并成一个新的chunk。

{
  vendors: {
    test: /[\\/]node_modules[\\/]/,
    priority: -10
  },
}

cacheGroups配置下的每一个对象,都可以认为是一个cacheGroup,例如上面的代码中是key为vendors的对象。

cacheGroup.test

test用于对所有的module进行筛选,筛选过的module将被放入这个cacheGroup所对应的chunk文件中。上例中通过[\\/]node_modules[\\/]对于module的路径进行测试,最终所有的node_modules路径下的模块都将放在vendors这个chunk下,这也是上面生成vendors~xxx.js的原因。

cacheGroup.priority

定义cacheGroup的优先级。因为对于每个module来说,有可能同时匹配了多个cacheGrouptest规则,此时就需要根据优先级来决定需要放到哪个cacheGroup中。

name决定了生成的chunk文件的名字。默认为true情况下,生成的名字格式为为cacheGroup名字~chunk1名字~chunk2名字.js,其中chunk1名字chunk2名字是因为这个cacheGroup中包含了这两个chunk相关的代码,如果有更多的chunk的话以此类推。

automaticNameDelimiter

可能有细心的读者会注意到上一小节中用于连接chunk名称的~,其实是automaticNameDelimiter这个配置项设置的。开发者可以通过该配置项来设置自己想用的连接符。

automaticNameMaxLength

默认情况下,会限制name小节中的chunk1名字~chunk2名字部分长度,超出了限制情况下将进行截断。

例如:设为3情况下,vendors-chunk1名字~chunk2名字.js将变成vendors~chu~21737d60.js,仅仅保留了长度=3的chu部分。在出现截断情况下,会在后面补充一段额外的字符,可能是一种避免文件名重复的机制。

minChunks

当和一个cacheGroup相关的chunk数量超过minChunks时,新的chunk文件才可以生成。

例如,在默认配置中:

{
  default: {
    minChunks: 2,
    priority: -20,
    reuseExistingChunk: true
  }
}

可能有细心的读者又会问了:现在说的不是splitChunks.minChunks吗,和cacheGroup.minChunks有什么关系呢?

其实在splitChunks下的所有配置,在cacheGroup中都会继承或者覆盖。所以对于key为vendors的cacheGroup来说,其minChunks为1,基本就是不限制,所以node_modules文件夹下的内容都会被放入到vendors这个chunk。

所以我们知道,key为default的cacheGroup,其中会放入至少两个chunk所引用的module。如果需要尝试的,可以通过在两个entry所生成的bundle文件中,引用相同的module,之后再打包,应该就会发现该module被放到了名为default~chunk1名字~chunk2名字这样的文件中。

(至此希望大家已经对于chunk的生成逻辑有了大致的了解。)


一些关于webpack的其他文章:

  1. webpack的加载

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK