- webpack概述
- 入口起点(Entry Points)
- 输出(Output)
- 模块(Mode)
- 加载器(Loaders)
- 插件(Plugins)
- 配置(Configuration)
- 模块(Modules)
- 模块解析(Module Resolution)
- 依赖图表(Dependency Graph)
- 文件清单(Manifest)
- 构建目标(Targets)
- 模块热替换(Hot Module Replacement)
- 第二部分:配置
- 使用不同语言进行配置(Configuration Languages)
- 多种配置类型
- 入口和上下文(Entry and Context)
- 输出(Output)
- 模块(Module)
- 解析(Resolve)
- 插件(Plugins)
- 开发中 Server(DevServer)
- 开发工具(Devtool)
- 构建目标(Targets)
- Watch 和 WatchOptions
- 外部扩展(Externals)
- 性能(Performance)
- Node
- 统计(Stats)
- 其它选项(Other Options)
- 第三部分:API
- 命令行接口(CLI)
- 包含统计数据的文件(stats data)
- Node.js API
- 模块热替换(Hot Module Replacement)
- 加载器 API
- 模块方法(module methods)
- 模块变量(module variables)
- Plugin API
- compiler 钩子
- compilation 钩子
- resolver
- parser
- 第四部分:指南
- 安装
- 起步
- 管理资源
- 管理输出
- 开发
- 模块热替换
- Tree shaking
- 生产环境构建
- 代码拆分(Code Splitting)
- 懒加载(Lazy Loading)
- 缓存(Caching)
- 创建库 (Library)
- Shimming
- 渐进式网络应用程序
- TypeScript
- 迁移到新版本
- 使用环境变量
- 构建性能
- 内容安全策略
- 开发 - Vagrant
- 管理依赖
- Public Path(公共路径)
- 集成(Integrations)
- 第五部分:加载器
- babel-loader
- yaml-frontmatter-loader
- cache-loader
- coffee-loader
- coffee-redux-loader
- coverjs-loader
- css-loader
- exports-loader
- expose-loader
- extract-loader
- file-loader
- gzip-loader
- html-loader
- i18n-loader
- imports-loader
- istanbul-instrumenter-loader
- jshint-loader
- json-loader
- json5-loader
- less-loader
- bundle-loader
- multi-loader
- node-loader
- null-loader
- polymer-webpack-loader
- postcss-loader
- raw-loader
- react-proxy-loader
- restyle-loader
- sass-loader
- script-loader
- source-map-loader
- style-loader
- svg-inline-loader
- thread-loader
- transform-loader
- url-loader
- val-loader
- worker-loader
- mocha-loader
- 第六部分:插件
- AggressiveSplittingPlugin
- ZopfliWebpackPlugin
- BannerPlugin
- ClosureWebpackPlugin
- CommonsChunkPlugin
- ComponentWebpackPlugin
- CompressionWebpackPlugin
- ContextReplacementPlugin
- CopyWebpackPlugin
- DefinePlugin
- DllPlugin
- EnvironmentPlugin
- EvalSourceMapDevToolPlugin
- ExtractTextWebpackPlugin
- HashedModuleIdsPlugin
- HotModuleReplacementPlugin
- HtmlWebpackPlugin
- BabelMinifyWebpackPlugin
- IgnorePlugin
- LoaderOptionsPlugin
- MinChunkSizePlugin
- ModuleConcatenationPlugin
- NamedModulesPlugin
- NormalModuleReplacementPlugin
- NpmInstallWebpackPlugin
- PrefetchPlugin
- ProfilingPlugin
- ProvidePlugin
- SourceMapDevToolPlugin
- SplitChunksPlugin
- UglifyjsWebpackPlugin
- WatchIgnorePlugin
- I18nWebpackPlugin
SplitChunksPlugin
Originally, chunks (and modules imported inside them) were connected by a parent-child relationship in the internal webpack graph. The CommonsChunkPlugin
was used to avoid duplicated dependencies across them, but further optimizations where not possible
Since version 4 the CommonsChunkPlugin
was removed in favor of optimization.splitChunks
and optimization.runtimeChunk
options. Here is how the new flow works.
Defaults
Out of the box SplitChunksPlugin
should work great for most users.
By default it only affects on-demand chunks because changing initial chunks would affect the script tags the HTML file should include to run the project.
webpack will automatically split chunks based on these conditions:
- New chunk can be shared OR modules are from the
node_modules
folder - New chunk would be bigger than 30kb (before min+gz)
- Maximum number of parallel requests when loading chunks on demand would be lower or equal to 5
- Maximum number of parallel requests at initial page load would be lower or equal to 3
When trying to fulfill the last two conditions, bigger chunks are preferred.
Let's take a look at some examples.
Defaults: Example 1
// index.js
// dynamically import a.js
import("./a");
// a.js
import "react";
// ...
Result: A separate chunk would be created containing react
. At the import call this chunk is loaded in parallel to the original chunk containing ./a
.
Why:
- Condition 1: The chunk contains modules from
node_modules
- Condition 2:
react
is bigger than 30kb - Condition 3: Number of parallel requests at the import call is 2
- Condition 4: Doesn't affect request at initial page load
What's the reasoning behind this? react
probably won't change as often as your application code. By moving it into a separate chunk this chunk can be cached separately from your app code (assuming you are using chunkhash, records, Cache-Control or other long term cache approach).
Defaults: Example 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
// ...
Result: A separate chunk would be created containing ./helpers
and all dependencies of it. At the import calls this chunk is loaded in parallel to the original chunks.
Why:
- Condition 1: The chunk is shared between both import calls
- Condition 2:
helpers
is bigger than 30kb - Condition 3: Number of parallel requests at the import calls is 2
- Condition 4: Doesn't affect request at initial page load
Putting the content of helpers
into each chunk will result into its code being downloaded twice. By using a separate chunk this will only happen once. We pay the cost of an additional request, which could be considered a tradeoff. That's why there is a minimum size of 30kb.
Configuration
For developers that want to have more control over this functionality, webpack provides a set of options to better fit your needs.
If you are manually changing the split configuration, measure the impact of the changes to see and make sure there's a real benefit.
W> Default configuration was chosen to fit web performance best practices but the optimum strategy for your project might defer depending on the nature of it.
Configuring cache groups
The defaults assign all modules from node_modules
to a cache group called vendors
and all modules duplicated in at least 2 chunks to a cache group default
.
A module can be assigned to multiple cache groups. The optimization then prefers the cache group with the higher priority
(priority
option) or that one that forms bigger chunks.
Conditions
Modules from the same chunks and cache group will form a new chunk when all conditions are fulfilled.
There are 4 options to configure the conditions:
minSize
(default: 30000) Minimum size for a chunk.minChunks
(default: 1) Minimum number of chunks that share a module before splittingmaxInitialRequests
(default 3) Maximum number of parallel requests at an entrypointmaxAsyncRequests
(default 5) Maximum number of parallel requests at on-demand loading
Naming
To control the chunk name of the split chunk the name
option can be used.
W> When assigning equal names to different split chunks, all vendor modules are placed into a single shared chunk, though it's not recommend since it can result in more code downloaded.
The magic value true
automatically chooses a name based on chunks and cache group key, otherwise a string or function can be passed.
When the name matches an entry point name, the entry point is removed.
optimization.splitChunks.automaticNameDelimiter
By default webpack will generate names using origin and name of the chunk, like vendors~main.js
.
If your project has a conflict with the ~
character, it can be changed by setting this option to any other value that works for your project: automaticNameDelimiter: "-"
.
Then the resulting names will look like vendors-main.js
.
Select modules
The test
option controls which modules are selected by this cache group. Omitting it selects all modules. It can be a RegExp, string or function.
It can match the absolute module resource path or chunk names. When a chunk name is matched, all modules in this chunk are selected.
Select chunks
With the chunks
option the selected chunks can be configured.
There are 3 values possible "initial"
, "async"
and "all"
. When configured the optimization only selects initial chunks, on-demand chunks or all chunks.
The option reuseExistingChunk
allows to reuse existing chunks instead of creating a new one when modules match exactly.
This can be controlled per cache group.
optimization.splitChunks.chunks: all
As it was mentioned before this plugin will affect dynamic imported modules. Setting the optimization.splitChunks.chunks
option to "all"
initial chunks will get affected by it (even the ones not imported dynamically). This way chunks can even be shared between entry points and on-demand loading.
This is the recommended configuration.
T> You can combine this configuration with the HtmlWebpackPlugin, it will inject all the generated vendor chunks for you.
optimization.splitChunks
This configuration object represents the default behavior of the 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
}
}
}
By default cache groups inherit options from splitChunks.*
, but test
, priority
and reuseExistingChunk
can only be configured on cache group level.
cacheGroups
is an object where keys are the cache group names. All options from the ones listed above are possible: chunks
, minSize
, minChunks
, maxAsyncRequests
, maxInitialRequests
, name
.
You can set optimization.splitChunks.cacheGroups.default
to false
to disable the default cache group, same for vendors
cache group.
The priority of the default groups are negative to allow any custom cache group to take higher priority (the default value is 0
).
Here are some examples and their effect:
Split Chunks: Example 1
Create a commons
chunk, which includes all code shared between entry points.
splitChunks: {
cacheGroups: {
commons: {
name: "commons",
chunks: "initial",
minChunks: 2
}
}
}
W> This configuration can enlarge your initial bundles, it is recommended to use dynamic imports when a module is not immediately needed.
Split Chunks: Example 2
Create a vendors
chunk, which includes all code from node_modules
in the whole application.
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: "vendors",
chunks: "all"
}
}
}
W> This might result in a large chunk containing all external packages. It is recommended to only include your core frameworks and utilities and dynamically load the rest of the dependencies.
optimization.runtimeChunk
Setting optimization.runtimeChunk
to true
adds an additonal chunk to each entrypoint containing only the runtime.
The value single
instead creates a runtime file to be shared for all generated chunks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论