You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Loaders are transformations that are applied to the source code of a module.
Plugins are the backbone of webpack. Webpack itself is built on the same plugin system that you use in your webpack configuration!
|- a-loader `pitch`|- b-loader `pitch`|- c-loader `pitch`|- requested module is picked up as a dependency
|- c-loader normal execution
|- b-loader normal execution
|- a-loader normal execution
{// define a custom backendbackend?: ((compiler: Compiler,callback: (err?: Error,api?: BackendApi)=>void)=>void)|((compiler: Compiler)=>Promise<BackendApi>)|{/** * A custom client. */client?: string;/** * Specify where to listen to from the server. */listen?: number|ListenOptions|((server: typeofServer)=>void);/** * Specify the protocol the client should use to connect to the server. */protocol?: "http"|"https";/** * Specify how to create the server handling the EventSource requests. */server?: ServerOptionsImport|ServerOptionsHttps|(()=>typeofServer);},entries?: boolean,imports?: boolean,test?: string|RegExp|((module: Module)=>boolean)}
module.exports={optimization: {minimize: true,minimizer: [newTerserPlugin({minify: TerserPlugin.swcMinify,// `terserOptions` options will be passed to `swc` (`@swc/core`)// Link to options - https://swc.rs/docs/config-js-minifyterserOptions: {},minify: TerserPlugin.esbuildMinify,// `terserOptions` options will be passed to `esbuild`// Link to options - https://esbuild.github.io/api/#minify// Note: the `minify` options is true by default (and override other `minify*` options), so if you want to disable the `minifyIdentifiers` option (or other `minify*` options) please use:// terserOptions: {// minify: false,// minifyWhitespace: true,// minifyIdentifiers: false,// minifySyntax: true,// },}),],},};
从功能核心来说,webpack 是JS应用的打包工具(static module bundler)。webpack 会从入口(entry point)开始处理你的应用,构建依赖图,把多个模块(module)合并到一个或多个包(bundle)。
webpack 本身只能处理 JS/JSON 文件,它依赖各种 loader、plugin 来共同完成对复杂应用的支持。
(一)核心概念
loader vs plugin
loader 就是转换模块代码的工具函数,允许你预处理你要加载的文件。
plugin 是 webpack 的基石,而 webpack 也是基于同样的插件系统打造。plugin 本质是注册webpack的生命周期事件来做到 loader 做不到的事。
loader 顺序
loader 是洋葱型顺序,pitch 从左到右,loader 本身从右到左执行。
module vs chunk
模块化编程中,完整的程序可以被分成完成特定功能的模块。在 webpack 里,一个文件就是一个模块。
chunk 有两种形式:
SplitChunksPlugin
时产生。(二)优化构建效率
总的来说,想要提高打包/构建效率,要么是减少打包工作量,要么是提高打包速度。相关措施可以总结为:
持久化缓存,提高二次构建性能
如果不想变更一个模块导致打包过程(可能几百个模块)重复一遍,那么我们需要利用缓存持久化来避免不必要的工作。
配置缓存很简单,配置
cache
即可:cache.type
:默认为memory
,这在watch
模式下很有用,但是如果想持久化,方便中断后下次打包使用,可以设置为filesystem
;cache.cacheDirectory
:缓存文件存放的路径,默认为node_modules/.cache/webpack
;cache.maxAge
:缓存失效时间,默认为5184000000
;cache.buildDependencies
:额外的依赖文件,当这些文件内容变化时,缓存会完全失效而执行完整的编译构建,通常可设置为项目配置文件。配置完缓存后,测试的两次编译时间为
2047ms
和417 ms
,效果显著。关于 dll
dll 动态链接库本质也是缓存,即不经常改变的代码抽取成一个共享的库,然后直接使用。
通常:
[name].manifest.json
;由于从 webpack@4 开始,webpack 打包性能已经足够好,dll 模式被弃用。
减少编译查找路径、编译范围(减少查找时间,减少需要编译的文件)
除了缓存,还可以缩减编译查找步骤、范围来减小工作量。
1. Rule 的 exclude/include/issuer 等多种方式减少查找范围
2. noParse 跳过编译
使用 noParse 让 webpack 不要去解析特地文件,对忽略一些大型类库,可以节省很多时间。
3. 配置 resolve 减少查找范围
尽量减少webpack的查找范围。
提升编译性能(通过跳过不必要的编译步骤等)
1. 开发阶段禁止产物优化
usedExports: false
)除了压缩强烈建议开发阶段关闭,其它几项看个人需要。
2. 合适的 sourcemap 配置
eval/eval-source-map/(none)
;source-map
。3. 减少 watch 文件范围
4.
experiments.lazyCompilation
需要时再编译多线程/多进程处理
利用更高性能的 swc/esbuild 来压缩
两者通过 Rust/Go 提高了性能。
(三)优化
webpack caching (长期缓存)
理解 hash/chunkhash/contenthash
首先了解 webpack 中 hash 相关概念: https://webpack.js.org/configuration/output/#template-strings
hash/fullhash,Compilation-level,本次编译(compilation)的 hash。可以理解为项目级别的,任意改动基本都会导致 hash 变更。
chunkhash,Chunk-level,chunk 的 hash。不同 chunk 之间互不影响。
contenthash,Module-level,模块相关内容的 hash。
cache 第一步:Output FileNames
推荐使用
contenthash
来防止有改动但缓存未失效的问题(用户页面没访问最新内容)。cache 第二步:拆出模板代码(Extracting Boilerplate)
optimization.runtimeChunk
设置为"single"
会为所有生成的 chunk 创建一个共用的 runtime。如果设置为false
则会在每个 chunk 里面嵌入 runtime。以上两步让公共包和runtime可以不因为业务代码变更而缓存失效。
cache 第三步:Module Identifiers
假设这样一个情况:新增一个文件
'./src/print.js'
并被'./src/index.js'
(main)作为依赖引入使用。重新编译:module.id
was changed.我们发现 main/vendors/runtime 文件名(hash)都变了。理论上 vendors 应该不变。
引入
optimization.moduleIds="deterministic"
可以解决这类问题:natural
:基于使用顺序的数字 id。模块增减会导致id变更。deterministic
:模块名hash得出的数字id(默认3位)。跟顺序无关,解决了模块增减导致其它chunk的module的id(natural)也变化的问题。另外
optimization.chunkIds="deterministic"
也是 production 模式默认的。Concatenate Module(Scope Hoisting)
optimization.concatenateModules允许webpack去查找可以安全串联的模块来串联/合并到一个模块。
webpack之前会把每个module都放入单独的wrapper function,但这会拖慢执行速度。concatenateModules 可以像 RollupJS 之类尽可能把module安全合并,合并到同一个闭包下面。
对 Concatenate Module 而言:
The text was updated successfully, but these errors were encountered: