webpack分包工具SplitChunksPlugin

学习webpack时官网推荐文档使用CommonsChunkPlugin,但The CommonsChunkPlugin 已经从
webpack v4 legato 中移除.借鉴其余写的文章加上原文进行总结.
参考: 没有了CommonsChunkPlugin,咱拿什么来分包 [1]:
https://blog.csdn.net/songluy...

起初,chunks(代码块)和导入他们中的模块经过webpack内部的父子关系图链接.CommonsChunkPlugin被用来避免他们之间的依赖重复,可是没有更多的优化.html

从4.0版本开始CommonsChunkPlugin被移除且被optimization.splitChunks和optimization.runtimeChunk配置项代替.下面展现它们将如何工做.node

Defaults

SplitChunksPlugin 拆箱即用 对于大多数的用户很好用.
默认状况下它将只会影响按需加载的代码块,由于改变初始化的代码块将会影响html中运行项目须要包含的script标签.react

webpack将会基于如下条件自动分割代码块:webpack

  • 新的代码块被共享或者来自node_modules文件夹
  • 新的代码块大于30kb(在min+giz以前)
  • 按需加载代码块的请求数量应该<=5
  • 页面初始化时加载代码块的请求数量应该<=3

为了知足以上最后两个条件,倾向于更大的代码块.
让咱们看一些简单的例子.web

Defaults: 例子1

// index.js

// dynamically import a.js
import("./a");
// a.js
import "react";

// ...

结果:一个包含react的单独代码块将会被建立.由于index.js在import '/a.js'时和a.js中都会记载这个代码块.浏览器

缘由:缓存

  • 条件1:代码块包含来自node_modules的模块
  • 条件2:react>30kb
  • 条件3:代码块的引用数量是2
  • 条件4:不影响初始页面加载

这样作的理由是? react 不会像你的应用代码同样常常改变.经过将它放到一个单独的代码块中能够与你本身的代码分离开来,从而被独立缓存(假设你正在用chunkhash, records, Cache-Control等长期缓存策略).框架

Defaults: 例子 2

// entry.js

// dynamically import a.js and b.js
import("./a");
import("./b");
// a.js
import "./helpers"; // helpers is 40kb in size

// ...
// b.js
import "./helpers";
import "./more-helpers"; // more-helpers is also 40kb in size

// ...

结果:一个包含'./helpers'和全部关于它的依赖的代码块将会被建立.当调用import时,这个代码块一块儿被加载进原始代码块.async

缘由:模块化

  • 条件1:这个代码块被两个import调用共享
  • 条件2:helpers>30kb
  • 条件3:import同时请求为数量2
  • 条件4:不影响页面初始化加载

将helpers的内容放进各个代码块将会致使helpers的代码被下载两次.经过使用分离的代码块将会只下载一次.咱们将会多发起一块儿请求helpers的请求,若是代码块太小则不值得多发起一次请求,折中的建议是代码块超过30kb再进行分离.

配置(Configuration)

为了让开发者们对这个功能有更多的控制,webpack提供了一些配置项来更好的知足你的需求.

在人为改变分割配置时,请肯定自定义配置带来了实实在在的好处.

默认配置便是咱们推荐的web最佳实践,可是你项目的最佳策略根据项目类型可能会有所不一样

配置缓存组(Configuring cache groups)

默认将全部来源于node_modules的模块分配到叫作'venders'的缓存组,全部引用超过两次的模块分配到'default'缓存组.

一个模块能够被分配到多个缓存组.这个优化能够经过选择更高优先级的缓存组或者造成代码块更大的缓存组来完成.

条件(Conditions)

当知足下列全部条件时,来自同一个代码块和缓存组的模块将会造成一个新的代码块.
下面条件的4个配置项:

  • minSize (default: 30000) 代码块的最小尺寸
  • minChunks (default: 1) 在分割以前模块的被引用次数
  • maxInitialRequests (default 3) 一个入口的最大并行请求数量
  • maxAsyncRequests (default 5) 按需加载最大并行请求数量

命名(Naming)

能够经过'name'配置项来控制切割以后代码块的命名.

给多个分割以后的代码块分配相同的名称,全部的vendor 模块被放进一个共享的代码块中,不过这会致使多余的代码被下载因此并不推荐

神奇的true值将会自动根据切割以前的代码块和缓存组键值(key)自动分配命名,不然就须要传入一个String或者function.

命名与入口名称相同时,入口将会被移除.

optimization.splitChunks.automaticNameDelimiter

默认webpack将会使用入口名和代码块的名称生成命名,好比 'vendors~main.js'
若是你的工程和"~"冲突,能够经过设置automaticNameDelimiter:'-'解决.
以后最终的命名将会是'vendors-main.js'

模块选择(Select modules)

test配置项控制这个缓存组所选择的的模块.忽略它选择全部模块.这个配置能够是正则,字符串或者是函数.

能够匹配绝对资源路径或者是代码块名.当一个代码块名称被匹配,全部在这个代码块中的模块都会被选则.

代码块选择(Select chunks)

能够用chunks配置项来指定代码块会被切割.
可用值:"initial","async","all".配置以后只会选择对应于初始化代码块,按需加载代码块,或者是全部代码块中的一个.
当模块彻底匹配时,reuseExistingChunk 配置项容许重用已经存在的代码块而不是建立一个新的代码块.
每个缓存组均可以使用这个配置项来控制.

optimization.splitChunks.chunks: all
就像以前提到的这个插件会影响动态导入的模块.设置chunks配置项为all将会影响初始化的代码块(即便不是动态导入的代码块).这种代码块将会被入口和按需加载共享.

下面是建议的配置:

这个配置能够配合HtmlWebpackPlugin插件使用,这将为你注入全部生成的vendor代码块.

optimization.splitChunks

下面的配置对象表明了splitChunksPlugin的默认行为.

splitChunks: {
    chunks: "async",
    minSize: 30000,
    minChunks: 1,
    maxAsyncRequests: 5,
    maxInitialRequests: 3,
    automaticNameDelimiter: '~',
    name: true,
    cacheGroups: {
        vendors: {
            test: /[\\/]node_modules[\\/]/,
            priority: -10
        },
    default: {
            minChunks: 2,
            priority: -20,
            reuseExistingChunk: true
        }
    }
}

缓存组默认继承splitChunks的配置项,可是test,priority和reuseExistingChunk只能在缓存组中被配置.
缓存组是一个是缓存组名字做为键值的对象.除了上述代码块中列举的配置项还有:chunks, minSize, minChunks, maxAsyncRequests, maxInitialRequests, name.
你能够设置optimization.splitChunks.cacheGroups.default = false来禁用默认缓存组,
vendors也能够一样禁用.
为了可以让自定义缓存组有更高的优先级(默认0),默认缓存组的priority属性为负值.

下面是一些例子和他们的影响:

Split Chunks: Example 1

建立名为"commons"的代码块,它包含了入口之间共享的全部代码.

splitChunks: {
    cacheGroups: {
        commons: {
            name: "commons",
            chunks: "initial",
            minChunks: 2
        }
    }
}

这个配置会增大你的初始化包,当一个模块不是当即被须要建议采用动态导入.

Split Chunks: Example 2

建立一个vendor代码块,它包含了整个应用中全部来自node_modules的代码.

splitChunks: {
    cacheGroups: {
        commons: {
            test: /[\\/]node_modules[\\/]/,
            name: "vendors",
            chunks: "all"
        }
    }
}
这会致使一个包含全部外部包的大代码块.建议只包括你的核心框架和功能,而且动态加载剩余的依赖.

注意:这可能会致使下载额外的代码。

optimization.runtimeChunk

设置optimization.runtimeChunk=true ,将每个入口添加一个只包含runtime的额外代码块.
然而设置值为single,只会为全部生成的代码块建立一个共享的runtime文件.

runtime:链接模块化应用程序的全部代码.
runtime包含:在模块交互时,链接模块所需的加载和解析逻辑。包括浏览器中的已加载模块的链接,以及懒加载模块的执行逻辑.
相关文章
相关标签/搜索