★webpack 团队于北京时间 10 月 12 日凌晨发布了
v5.0.0-beta.0
版本,本文译自webpack/changelog-v5
。此部分主要面向非插件开发的 webpack 使用者。 ”
此版本重点关注以下内容:
=> 查阅迁移指南[1] <=
v4 中所有废弃的代码均已删除。
迁移:以确保你的 webapck 4 不打印弃用警告。
以下是已删除但在 v4 中没有弃用警告的内容:
早期,webpack 的目的是允许在浏览器中运行大多数 node.js 模块,但是模块整体格局发生了变化,现在许多模块的主要用途是以编写前端为目的。webpack <= 4 附带了许多 Node.js 核心模块的 polyfil,一旦模块中使用了任何核心模块(即 ”crypto“ 模块),这些模块就会被自动启用。
虽然这使得为 Node.js 编写模块变得简单,但它会将超大的 polyfill 添加到 package 中。在许多情况下,这些 polyfill 并非必要。
webpack 5 会停止自动 polyfill 这些核心模块,并专注于与前端兼容的模块。
迁移:
package.json
中使用 browser
字段,以使得 package 与前端代码兼容。为 borwser 提供可选的 implementations/dependencies。反馈:无论是否喜欢上述修改,请都向我们提出反馈。我们并不确定是否会纳入最终版本。
添加了用于长效缓存的新算法。在生产模式下,默认启用这些功能。
chunkIds: "deterministic", moduleIds: "deterministic"
此算法采用确定性的方式将短数字 ID(3 或 4 个字符)分配给 modules 和 chunks。这是基于 bundle 大小和长效缓存间的折中方案。
迁移:最好使用 chunkIds
和 moduleIds
的默认值。你还可以选择使用旧的默认值,chunkIds: "size", modules: "size"
,这将生成较小的 bundle,但这会使得它们频繁地进行缓存。
添加了新算法来处理 export 的名称。默认情况下启用。
如果可能,它将以确定性方式破坏 export 的名称。
迁移:不需要进行任何操作。
在开发模式下默认启用,以新的算法为 chunk id 命名,给 chunk(以及文件名)提供易于理解的名称。module ID 由其相对于 context
的路径决定。chunk ID 由 chunk 的内容决定。
因此,你不再需要使用 import(/* webpackChunkName: "name" */ "module")
进行调试。但是,如果你要控制生产环境的文件名,那仍可使用。
可以在生产中使用 chunkIds: "named"
,但要确保在使用时不会意外地泄露有关模块名称的敏感信息。
迁移:如果你不喜欢在开发中更改文件名,则可以传递 chunkIds: "natural"
以使用旧的数字模式。
JSON 模块现在符合规范,并会在使用非默认导出时发出警告。
迁移:使用默认导出。
(自 alpha.16 起)
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 起)
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
。
此方式可以分析以下符号:
export default
或带有变量声明(variable declarations)的/*#__PURE__*/
表达式反馈:如果您发现此分析中缺少某些内容,请反馈 issues,我们考虑将其添加。
此优化也称为深度作用域分析(Deep Scope Analysis)。
(自 alpha.24 起)
现在需要再使用编译器(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 起)
与之前展示单个数值相比,模块现在以更好的方式展示其 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 起)
目前,仅允许启动单个文件 target(如 node,WebWorker,electron main)支持在运行时自动加载引导程序所需的相关代码片段。
这允许对带有 chunks: "all"
的 target 使用 splitChunks
。
值得注意的是,由于 chunk 加载是异步的,因此这也会使初始估算也为异步操作。当使用 output.library
时,这可能会出现问题,因为导出的值的类型目前为 Promise。从 alpha.14 开始,这将不适用于 target: "node"
,因为 chunk 加载在此 target 下为同步。
(自 alpha.3 起)
enhanced-resolve
已更新至 v5。具体改进如下:
false
(自 alpha.18 起)
不包含 JS 代码的 chunk 将不再生成 JS 文件。
(自 alpha.14 起)
并非所有特性从开始就文档。在 webpack 4 中,我们添加了实验性功能,并在 changelog 中指出它们是实验性的,但是从配置中并不能很清楚的了解这些功能是实验性的。
在 webpack 5 中,有一个新的 experiments
配置项,允许启用实验性功能。这样可以清楚地了解启用/使用了哪些实验特性。
虽然 webpack 遵循语义版本控制,但是实验性功能将成为例外。它可能包含 webpack 次要版本的破坏性更改。发生这种情况时,我们将在 changelog 中添加清晰的注释。这促使我们可以更快地迭代实验性功能,同时还可以使用我们在主要版本上停留更长时间以获得稳定的功能。
以下实验性功能将随 webpack 5 一同发布:
.mjs
提供支持(experiments.mjs
)experiments.syncWebAssembly
)experiments.asyncWebAssembly
)experiments.topLevelAwait
)await
使模块成为异步模块import
引入异步模块(experiments.importAsync
)import await
引入异步模块(experiments.importAwait
)asset
模块类似类似于 file-loader
(experiments.asset
)(自 alpha.19 起)experiments.outputModule
)(自 alpha.31 起)<script type="module">
进行懒加载,并在 module
模式下将其进行压缩请注意,这也意味着针对 .mjs
的支持和 WebAssembly 的支持将被默认禁用。
(自 alpha.15 起)
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 的最低支持版本从 6 变更为 8。
迁移:升级到最新的 node.js 可用版本。
cache: Object
:不能设置为内存缓存对象cache.type
:可以设置为 "memory"
或 "filesystem"
cache.type = "filesystem"
添加新配置项:cache.cacheDirectory
cache.name
cache.version
cache.store
cache.hashAlgorithm
cache.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.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"
optimization.hashedModuleIds
optimization.namedChunks
(NamedChunksPlugin
与之相同)optimization.namedModules
(NamedModulesPlugin
与之相同)optimization.occurrenceOrder
chunkIds
或 moduleIds
optimization.splitChunks
test
不在匹配 chunk 名(module, { chunkGraph }) => chunkGraph.getModuleChunks(module).some(chunk => chunk.name === "name")
optimization.splitChunks
中添加 minRemainingSize
(自 alpha.13 起)optimization.splitChunks
filename
可以赋值函数 (since alpha.17)optimization.splitChunks
sizes 可以为每个源类型的 size 对象minSize
minRemainingSize
maxSize
maxAsyncSize
(自 alpha.13 起)maxInitialSize
optimization.splitChunks
中添加 maxAsyncSize
和 maxInitialSize
:允许为初始和异步 chunk 指定不同的最大 size。optimization.splitChunks
中的 name: true
:不再支持自动命名chunkIds: "named"
将为你的文件提供有用的名称以便于调试optimization.splitChunks.cacheGroups[].idHint
:将提示如何命名 chunk idoptimization.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]
代替[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
默认为 false
optimization.splitChunks
中的 minRemainingSize
默认为 minSize
(自 alpha.13 起)cache
时,resolve(Loader).cache
默认为 true
resolve(Loader).cacheWithContext
默认为 false
node.global
默认为 false
~(自 alpha.4 起被移除)resolveLoader.extensions
移除 .json
(自 alpha.8 起)target
时,node.global
中的 node.__filename
和 node.__dirname
默认为 false
(自 alpha.14 起)[1]
查阅迁移指南: 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