原文首发于 blog.flqin.com。若有错误,请联系笔者。分析码字不易,转载请代表出处,谢谢!css
前面一至十一章,介绍了在 development
的模式下,整个完整了构建主流程。在了解构建流程的基础上,本章整理一些与 webpack
优化相关的知识点。html
咱们参考 production
模式里,里面已经作了大部分的优化,如压缩,Scope Hoisting
, tree-shaking
等给予咱们启发,接下来具体分析各个点。webpack
FlagDependencyUsagePlugin
compilation.hooks.optimizeDependencies
module.usedExports
里。用于 Tree shaking
。optimization.usedExports:true
FlagIncludedChunksPlugin
compilation.hooks.optimizeChunkId
chunk
添加了 ids
,用于判断避免加载没必要要的 chunk
ModuleConcatenationPlugin
compilation.hooks.optimizeChunkModules
esm
语法能够做用域提高(Scope Hoisting
)或预编译全部模块到一个闭包中,提高代码在浏览器中的执行速度optimization.concatenateModules:true
NoEmitOnErrorsPlugin
compiler.hooks.shouldEmit
,compilation.hooks.shouldRecord
compilation
编译时有 error
,则不执行 Record
相关的钩子,而且抛错和不编译资源OccurrenceOrderModuleIdsPlugin
,OccurrenceOrderChunkIdsPlugin
SideEffectsFlagPlugin
normalModuleFactory.hooks.module
,compilation.hooks.optimizeDependencies
normalModuleFactory.hooks.module
钩子里读取 package.json
里的 sideEffects
字段和读取 module.rule
里的 sideEffects
赋给 module.factoryMeta
(纯的 ES2015
模块);compilation.hooks.optimizeDependencies
钩子里根据 sideEffects
配置,删除未用到的 export
导出optimization.sideEffects:true
(默认)TerserPlugin
template.hooks.hashForChunk
,compilation.hooks.optimizeChunkAssets
template.hooks.hashForChunk
钩子即在 chunks
生成 hash
阶段会把压缩相关的信息也打入到里面compilation.hooks.optimizeChunkAssets
钩子触发资源压缩事件optimization.minimize
是否开启压缩optimization.minimizer
定制 Terser
另:development
模式单独启用的插件:git
NamedChunksPlugin
compilation.hooks.beforeChunkIds
chunk id
optimization.chunkIds
NamedModulesPlugin
compilation.hooks.beforeModuleIds
module id
optimization.moduleIds
在更新部署页面资源时,不管是先部署页面,仍是先部署其余静态资源,都会由于新老资源替换后的缓存缘由,或者部署间隔缘由,都会致使资源不对应而引发页面错误。github
持久化缓存方案就是在各静态资源的名字后面加惟一的 hash
值,这样在每次修改文件后生成的不一样的 hash
值,而后在增量式发布文件时,就能够避免覆盖掉以前旧的文件。获取到新文件的用户就能够访问新的资源,而浏览器有缓存等状况的用户则继续访问老资源,保证新老资源同时存在且互不影响不出错。web
html
:不开启缓存,把 html
放到单独的服务器上并关闭服务器的缓存,须要保证每次的 html
都为最新js
,css
,img
等其余静态资源:开启缓存,将静态资源上传到 cdn
,对资源开启长期缓存,由于有惟一 hash
的缘故因此不会致使资源被覆盖,用户在初次访问能够将这些长效缓存下载到本地,而后在后续的访问能够直接从缓存里读,节约网络资源。js
使用 chunkhash
,对 css
应用 mini-css-extract-plugin
插件并使用 contenthash
optimization.moduleIds
属性设置 module id
moduleIds
设为 named
即便用 NamedModulesPlugin
(相对路径为 key
)来固化 module id
,moduleIds
设为 hashed
即便用 HashedModuleIdsPlugin
(将路径转换为 hash
为 key
)来固化 module id
,保证在某一模块增删后,不会影响其余模块的 module id
optimization.chunkIds
属性设置为 named
或 optimization.namedChunks
属性设置为 true
(经过将 chunk name
复制到 chunk id
)固化 chunk id
,该属性会启用 NamedChunksPlugin
NamedChunksPlugin
插件里能够自定义 nameResolver
设置 name
splitChunks.cacheGroups[].name
也能够设置 chunk name
import(/* webpackChunkName: "my-chunk-name" */ 'module')
optimization.splitChunks
属性抽离库 vendor
,业务公共代码 common
optimization.runtimeChunk
属性抽离运行时 runtime
,其中 runtime
也能够经过 script-ext-html-webpack-plugin
插件嵌入到 html
Tree Sharing
是一个术语,一般用于描述移除 JavaScript
上下文中的未引用代码(dead-code
)。由 rollup 普及,在 webpack
里由 TerserPlugin
实现。json
ES6
的模块引入是静态分析的,故而能够在编译时正确判断到底加载了什么代码若是咱们引入的模块被标记为 sideEffects: false
,只要它任意一个导出都没有被其余模块引用到,那么无论它是否真的有反作用,整个模块都会被完整的移除。api
"
side effect
(反作用)" 的定义是,在导入时会执行特殊行为的代码,而不是仅仅暴露一个export
或多个export
。举例说明,例如polyfill
,它影响全局做用域,而且一般不提供export
。浏览器
tree shaking
须要知足ES2015
模块语法(即 import
和 export
),目的是为了供程序静态分析compiler
将 ES2015
模块语法转换为 CommonJS
模块(设置 babel.config.js
presets: [['@babel/env', { modules: false }]]
)package.json
或者 module.rule
设置 sideEffects : false
,告诉 webpack
该项目或者该文件没有反作用production
,其中会启用 FlagDependencyUsagePlugin
,TerserPlugin
完成 tree shaking
Scope Hoisting
即 做用域提高,可让 webpack
打包出来的代码文件更小,运行更快。缓存
ES6
的静态模块分析,分析出模块之间的依赖关系,按照引用顺序尽量地把模块放到同一个函数做用域中,而后适当的重命名一些变量以防止变量名冲突。
异步
import()
不会启用Scope Hoisting
ES2015
模块语法(即 import
和 export
)mode
选项设置为 production
,其中会启用 ModuleConcatenationPlugin
插件完成 Scope Hoisting
如下列举部分我用过优化相关的插件及 loader
:
css
样式到单独文件HtmlWebpackPlugin
,将 css
内联到 html
里HtmlWebpackPlugin
,将 js
内联到 html
里css
DataURL
,减小请求数各插件随着时间推移,有的可能废弃,有的可能被更好的所替代,已社区流行为准。
从 webpack
源码开始,到后面打包结果分析,watch
, webpack
优化总结等,前先后后花了一个月的时间,但收获也颇多。因为对 webpack
底层有了认知,海量配置也清楚具体实现,不用死记硬背了;因为对 webpack
底层有了认知,因此遇到的各类构建问题都能定位到是构建的哪一步;因为对 webpack
底层有了认知,也可以很快速的根据业务写一些针对性的 loader
和 plugin
;最重要的是经过对源码分析,大型工程的组织架构,扩展性,健壮性等给人带来一些新的思路和启发。
本系列到此结束,后续会不断的更新优化。对 webpack
源码的分析解除了我心中不少的构建相关的疑惑,整我的都升华了。因此每一个人精力、时间都有限,选择作本身喜欢的事情,方为上策。
若有错误,请联系笔者。分析码字不易,转载请代表出处,谢谢!