★webpack 团队于北京时间 10 月 12 日凌晨发布了
”v5.0.0-beta.0版本,本文译自webpack/changelog-v5。此部分主要面向非插件开发的 webpack 使用者。
简要说明
此版本重点关注以下内容:
我们尝试通过持久化存储优化构建性能。
我们尝试采用更好的算法与 defalut 来改善长效缓存。
我们尝试通过更好的 Tree Shaking 和代码生成来改善 bundle 的大小。
我们尝试清除内部结构中奇怪的代码,同时在不影响 v4 功能基础上实现了新特性。
我们目前尝试通过引入破坏性更改来为新特性做准备,以便于我们能尽可能长期地使用 v5。
迁移指南
=> 查阅迁移指南[1] <=
主要更改
移除废弃的代码
v4 中所有废弃的代码均已删除。
迁移:以确保你的 webapck 4 不打印弃用警告。
以下是已删除但在 v4 中没有弃用警告的内容:
现在必须为 IgnorePlugin 和 BannerPlugin 传递一个 options 对象。
自动移除 Node.js Polyfills
早期,webpack 的目的是允许在浏览器中运行大多数 node.js 模块,但是模块整体格局发生了变化,现在许多模块的主要用途是以编写前端为目的。webpack <= 4 附带了许多 Node.js 核心模块的 polyfil,一旦模块中使用了任何核心模块(即 ”crypto“ 模块),这些模块就会被自动启用。
虽然这使得为 Node.js 编写模块变得简单,但它会将超大的 polyfill 添加到 package 中。在许多情况下,这些 polyfill 并非必要。
webpack 5 会停止自动 polyfill 这些核心模块,并专注于与前端兼容的模块。
迁移:
尽可能尝试使用与前端兼容的模块。
可以为 Node.js 核心模块手动添加 polyfill。错误信息将提示如何进行此操作。
package 作者:在
package.json中使用browser字段,以使得 package 与前端代码兼容。为 borwser 提供可选的 implementations/dependencies。
反馈:无论是否喜欢上述修改,请都向我们提出反馈。我们并不确定是否会纳入最终版本。
采用新算法生成 chunk ID 以及 module ID
添加了用于长效缓存的新算法。在生产模式下,默认启用这些功能。
chunkIds: "deterministic", moduleIds: "deterministic"
此算法采用确定性的方式将短数字 ID(3 或 4 个字符)分配给 modules 和 chunks。这是基于 bundle 大小和长效缓存间的折中方案。
迁移:最好使用 chunkIds 和 moduleIds 的默认值。你还可以选择使用旧的默认值,chunkIds: "size", modules: "size",这将生成较小的 bundle,但这会使得它们频繁地进行缓存。
以新算法混淆 export 名称
添加了新算法来处理 export 的名称。默认情况下启用。
如果可能,它将以确定性方式破坏 export 的名称。
迁移:不需要进行任何操作。
为 chunk IDs 命名
在开发模式下默认启用,以新的算法为 chunk id 命名,给 chunk(以及文件名)提供易于理解的名称。module ID 由其相对于 context 的路径决定。chunk ID 由 chunk 的内容决定。
因此,你不再需要使用 import(/* webpackChunkName: "name" */ "module") 进行调试。但是,如果你要控制生产环境的文件名,那仍可使用。
可以在生产中使用 chunkIds: "named",但要确保在使用时不会意外地泄露有关模块名称的敏感信息。
迁移:如果你不喜欢在开发中更改文件名,则可以传递 chunkIds: "natural" 以使用旧的数字模式。
JSON 模块
JSON 模块现在符合规范,并会在使用非默认导出时发出警告。
迁移:使用默认导出。
(自 alpha.16 起)
嵌套 tree-shaking
webpack 现在可以追踪对 exports 嵌套属性的访问。重新导出 namespace 对象,这可以改善 Tree Shaking 操作(未使用 export elimination 和 export mangling)。
// inner.js
export const a = 1;
export const b = 2;
// module.js
import * as inner from "./inner";
export { inner }
// user.js
import * as module from "./module";
console.log(module.inner.a);
在此示例中,可以在生成模式下移除 export b。
(从 alpha.15 起)
内部模块(inner-module) tree-shaking
webpack 4 没有分析模块 export 与 import 之间的依赖关系。webpack 5 有一个新的选项 optimization.innerGraph,该选项在生产模式下默认启用,它对模块中的符号进行分析以找出从 export 到 import 的依赖关系。
如下述模块所示:
import { something } from "./something";
function usingSomething() {
return something;
}
export function test() {
return usingSomething();
}
内部图算法将确定仅在使用 export 的 test 时使用 something。这样可以将更多 export 标记为未使用,并从 bundle 中删除更多的代码。
如果设置了 "sideEffects": false,则可以省略更多模块。在此示例中,当未使用 export 的 test 时,将忽略 ./something。
如需获取有关未使用的 export 的信息,需使用 optimization.unusedExports。如需删除无副作用的模块,需使用 optimization.sideEffects。
此方式可以分析以下符号:
函数声明(function declarations)
class 声明(class declarations)
带有
export default或带有变量声明(variable declarations)的函数表达式(function expressions)
class 语句(class expressions)
/*#__PURE__*/表达式局部变量(local variables)
imported bindings
反馈:如果您发现此分析中缺少某些内容,请反馈 issues,我们考虑将其添加。
此优化也称为深度作用域分析(Deep Scope Analysis)。
(自 alpha.24 起)
编译器空闲并关闭(idle and close)
现在需要再使用编译器(compilers)后将其关闭。编译器具有 enter 和 leave 空闲状态,并具有这些状态的 hook。插件可以使用这些 hook 执行不重要的工作。(即,持久化缓存将延迟存储到磁盘)。在编译器关闭时,所有剩余工作应尽快完成。回调执行时,表明关闭已完成。
插件及其各自的作者应该会期望某些用户可能会忘记关闭编译器。因此,所有工作最终也应该在空闲时完成。当工作完成时,应防止进程退出。
当传递 callback 时,webpack() 实例会自动调用 close。
迁移:使用 node.js API 时,请确保在完成后调用 Complier.close。
改进代码生成
此版本添加了新的选项 output.ecmaVersion。它允许为 webpack 生成的运行时代码指定最大 EcmaScript 版本。
webpack 4 仅能于生成 ES5 的代码。webpack 5 现支持 ES5 或 ES2015 的代码。
默认配置将生成 ES2015 的代码。如果你需要支持旧版浏览器(例如,IE11),则可以将其降为 output.ecmaVersion: 5。
设置为 output.ecmaVersion: 2015 将使用箭头函数生成较短的代码,以及更多符合规范的代码,使用 const 声明(TDZ)作为 export default。
(自 alpha.23 起)
生产模式中的默认压缩(default minimizing)也使用 ecmaVersion 选项生成较小的代码。(自 alpha.31 起)
chunk 分割以及 module size
与之前展示单个数值相比,模块现在以更好的方式展示其 size。除此之外,现在也拥有了不同类型的 size。
目前,SplitChunksPlugin 已知道如何处理这些不同的 size,并将它们应用于 minSize 和 maxSize。默认情况下,仅处理 javascript 的 size,但你可以传递多个参数来管理它们:
minSize: {
javascript: 30000,
style: 50000,
}
迁移:检查构建中使用了哪些类型的 size,并在 splitChunks.minSize和可选的 splitChunks.maxSize 中进行配置。
持久化缓存
目前包含文件系统缓存。它是可选的,可以通过以下配置启用:
cache: {
// 1. 设置缓存类型为 filesystem
type: "filesystem",
buildDependencies: {
// 2. 将你的配置添加为 buildDependency 以在更改配置时,使得缓存失效。
config: [__filename]
// 3. 如果你还有其他需要构建的内容,可以在此处添加它们
// 请注意,loader 和所有模块中配置中引用的内容会自动添加
}
}
重要内容:
默认情况下,webpack 会假定其所处的 node_modules 目录仅由包管理器修改。针对 node_modules 目录,将跳过哈希和时间戳处理。出于性能方面考虑,仅使用 package 的名称和版本。symlinks(例如,npm/yarn link)很友好。除非你使用 cache.managedPaths: [] 选项取消此优化,否则请不要直接在 node_modules 中编辑文件。
默认情况下,缓存将分别存储在 node_modules/.cache/webpack 中(当使用 node_modules 时)和 .pnp/.cache/webpack(当使用 Yarn PnP 时,自 alpha.21 起)。你可能永远不必手动删除它。
(自 alpha.20 起)
当使用 Yarn PnP webpack 时,如果 yarn 的缓存不可变(通常不会发生变化)。你可以通过 cache.immutablePaths: [] 退出此优化。
(自 alpha.21 起)
用于 single-file-target 的 chunk 分割
目前,仅允许启动单个文件 target(如 node,WebWorker,electron main)支持在运行时自动加载引导程序所需的相关代码片段。
这允许对带有 chunks: "all" 的 target 使用 splitChunks。
值得注意的是,由于 chunk 加载是异步的,因此这也会使初始估算也为异步操作。当使用 output.library 时,这可能会出现问题,因为导出的值的类型目前为 Promise。从 alpha.14 开始,这将不适用于 target: "node",因为 chunk 加载在此 target 下为同步。
(自 alpha.3 起)
更新解析器
enhanced-resolve 已更新至 v5。具体改进如下:
当使用 Yarn PnP 时,解析器将直接处理无需其他插件
此 resolve 可追踪更多的依赖项,例如文件缺失
别名(aliasing)可能包含多种选择
可以设置别名(aliasing)为
false性能提升
(自 alpha.18 起)
不包含 JS 的 chunk
不包含 JS 代码的 chunk 将不再生成 JS 文件。
(自 alpha.14 起)
实验阶段特性
并非所有特性从开始就文档。在 webpack 4 中,我们添加了实验性功能,并在 changelog 中指出它们是实验性的,但是从配置中并不能很清楚的了解这些功能是实验性的。
在 webpack 5 中,有一个新的 experiments 配置项,允许启用实验性功能。这样可以清楚地了解启用/使用了哪些实验特性。
虽然 webpack 遵循语义版本控制,但是实验性功能将成为例外。它可能包含 webpack 次要版本的破坏性更改。发生这种情况时,我们将在 changelog 中添加清晰的注释。这促使我们可以更快地迭代实验性功能,同时还可以使用我们在主要版本上停留更长时间以获得稳定的功能。
以下实验性功能将随 webpack 5 一同发布:
像 webpack 4 一样对
.mjs提供支持(experiments.mjs)像 webpack 4 一样对旧版 WebAssembly 提供支持(
experiments.syncWebAssembly)根据更新规范[2] 对新版 WebAssembly 提供支持(
experiments.asyncWebAssembly)这使得 WebAssembly 模块成为异步模块
Top Level Await[3] Stage 3 阶段提案(
experiments.topLevelAwait)在顶层使用
await使模块成为异步模块
使用
import引入异步模块(experiments.importAsync)使用
import await引入异步模块(experiments.importAwait)asset模块类似类似于file-loader(experiments.asset)(自 alpha.19 起)导出 bundle 作为模块(
experiments.outputModule)(自 alpha.31 起)这将从 bundle 中移除 IIFE 的包装器,强制执行严格模式,通过
<script type="module">进行懒加载,并在module模式下将其进行压缩
请注意,这也意味着针对 .mjs 的支持和 WebAssembly 的支持将被默认禁用。
(自 alpha.15 起)
Stats
chunk 间关系默认情况下是隐藏的。可以使用 stats.chunkRelations进行切换。
(自 alpha.1 起)
Stats 现阶段可以区分 files 和 auxiliaryFiles。
(自 alpha.19 起)
默认情况下,Stats 会隐藏模块和 chunk id。可以使用 stats.ids 进行切换。
所有模块的列表均按照到 entrypoint 的距离排序。可以使用 stats.modulesSort 进行切换。
chunk 模块列表和 chunk 根模块列表分别根据模块名进行排序。可以分别使用 stats.chunkModulesSort 和 stats.chunkRootModulesSort进行更改。
在串联模块中,嵌套模块列表进行拓扑排序。可以通过 stats.nestedModulesSort 进行更改。
chunks 和 assets 会显示 chunk id 的提示。
(自 alpha.31 起)
最低 Node.js 版本
Node.js 的最低支持版本从 6 变更为 8。
迁移:升级到最新的 node.js 可用版本。
配置变更
结构变更
移除
cache: Object:不能设置为内存缓存对象添加
cache.type:可以设置为"memory"或"filesystem"为
cache.type = "filesystem"添加新配置项:cache.cacheDirectorycache.namecache.versioncache.store`cache.loglevel`(自 alpha.20 起被移除)
cache.hashAlgorithmcache.idleTimeout(自 alpha.8 起)cache.idleTimeoutForIntialStore(自 alpha.8 起)cache.managedPaths(自 alpha.20 起)cache.immutablePaths(自 alpha.21 起)cache.buildDependencies(自 alpha.20 起)
添加
resolve.cache:允许禁用/启用安全 resolve 缓存移除
resolve.concord移除用于原生 node.js 模块自动的 polyfill
移除
node.Buffer移除
node.console移除
node.process移除
node.*(node.js 原生模块)迁移:使用
resolve.alias和ProvidePlugin。发生错误会给出提示。
output.filename可以赋值函数(自 alpha.17 起)添加
output.assetModuleFilename(自 alpha.19 起)resolve.alias的值可以为数组或false(自 alpha.18 起)添加
optimization.chunkIds: "deterministic"添加
optimization.moduleIds: "deterministic"添加
optimization.moduleIds: "hashed"添加
optimization.moduleIds: "total-size"移除 module 和 chunk id 的相关的弃用选项
移除
optimization.hashedModuleIds移除
optimization.namedChunks(NamedChunksPlugin与之相同)移除
optimization.namedModules(NamedModulesPlugin与之相同)移除
optimization.occurrenceOrder迁移:使用
chunkIds或moduleIds
optimization.splitChunkstest不在匹配 chunk 名迁移:使用 test 函数
(module, { chunkGraph }) => chunkGraph.getModuleChunks(module).some(chunk => chunk.name === "name")
在
optimization.splitChunks中添加minRemainingSize(自 alpha.13 起)optimization.splitChunksfilename可以赋值函数 (since alpha.17)optimization.splitChunkssizes 可以为每个源类型的 size 对象minSizeminRemainingSizemaxSizemaxAsyncSize(自 alpha.13 起)maxInitialSize
在
optimization.splitChunks中添加maxAsyncSize和maxInitialSize:允许为初始和异步 chunk 指定不同的最大 size。移除
optimization.splitChunks中的name: true:不再支持自动命名迁移:使用默认值。
chunkIds: "named"将为你的文件提供有用的名称以便于调试
添加
optimization.splitChunks.cacheGroups[].idHint:将提示如何命名 chunk id移除
optimization.splitChunks中的automaticNamePrefix迁移:使用
idHint替代
optimization.splitChunks中的filename不再局限于初始 chunk(自 alpha.11 起)添加
optimization.mangleExports(自 alpha.10 起)移除
output.devtoolLineToLine迁移:无替代方式
output.hotUpdateChunkFilename: Function现在被禁止:不会生效。output.hotUpdateMainFilename: Function现在被禁止:不会生效。module.rules中的resolve和parser将以不同的方式合并(对象会进行深度合并,数组将采用"..."进行展开以获取之前的值)(自 alpha.13 起)module.rules中的query和loaders已被移除(自 alpha.13 起)添加
stats.chunkRootModules:展示 chunk 的根模块添加
stats.orphanModules:展示未触发的模块。添加
stats.runtime:展示 runtime 模块添加
stats.chunkRelations:显示 parent/children/sibling chunk(自 alpha.1 起)添加
stats.preset:选择 preset(自 alpha.1 起)BannerPlugin.banner签名变更移除
data.basename移除
data.query迁移:从
filename中进行提取
移除
SourceMapDevToolPlugin中的lineToLine迁移:无替代方式
[hash]不支持完整编译的 hash迁移:使用
[fullhash]或采用更好的 hash 选项
[modulehash]被废弃迁移:使用
[hash]代替
[moduleid]被废弃迁移:使用
[id]代替
移除
[filebase]迁移:使用
[base]代替
基于文件模板的新占位符(即 SourceMapDevToolPlugin)
[name][base][path][ext]
当向
externals传递一个函数时,它将具有不同的函数签名({ context, request }, callback)迁移:更改函数签名
添加
experiments(请参阅上述实验部分,自 alpha.19 起)添加
watchOptions.followSymlinks(自 alpha.19 起)
默认值变更
默认情况下,仅对
node_modules启用module.unsafeCache在生产模式下,
optimization.moduleIds的默认值从size替换为deterministic在生产模式下,
optimization.chunkIds的默认值从total-size替换为deterministic在
none模式下,optimization.nodeEnv默认为falseoptimization.splitChunks中的minRemainingSize默认为minSize(自 alpha.13 起)如果剩余部分过小,这将减少创建 chunk 的数量
当使用
cache时,resolve(Loader).cache默认为trueresolve(Loader).cacheWithContext默认为false~
node.global默认为false~(自 alpha.4 起被移除)resolveLoader.extensions移除.json(自 alpha.8 起)当 node-
target时,node.global中的node.__filename和node.__dirname默认为false(自 alpha.14 起)
参考资料
查阅迁移指南: https://github.com/webpack/changelog-v5/blob/master/MIGRATION%20GUIDE.md
[2]更新规范: https://github.com/WebAssembly/esm-integration
[3]Top Level Await: https://github.com/tc39/proposal-top-level-await
勘误
如对译文有疑问,欢迎评论或点击阅读原文,也可扫描下方二维码留言。

Webpack团队发布v5.0.0-beta.0版本,重点优化构建性能,改善长效缓存,增强TreeShaking,清理内部结构,引入破坏性更改为新特性做准备。此版本移除了废弃代码,改变了chunk和module ID生成算法,改进了代码生成,支持ES2015,更新了解析器,并引入了实验性特性。
626

被折叠的 条评论
为什么被折叠?



