阔别两年,Webpack 5 正式发布了!

技术漫谈

共 16146字,需浏览 33分钟

 ·

2020-10-14 02:56

HI,继 Vue 3 和 React 17 之后,我又来啦!印记中文已经完成了 webpack v5 中文文档的同步及翻译工作,大家可以无缝进行阅读哦。

文档地址请认准:https://webpack.docschina.org

文档地址请认准:https://webpack.docschina.org

文档地址请认准:https://webpack.docschina.org

重要的事说三遍,我们的文档隶属于官方,我们没有其他的域名哦,并且是与官方进行实时同步。

2020 年 10 月 10 日,webpack 升级至 5.0 版本,并且为官网添加了博客目录。我们及时的进行了同步,此文是我们阅读后总结归纳的版本。话不多说开始正文。

自从 2018 年 2 月,webpack4 发布以来,webpack 就暂时没有更进一步的重大更新,为了保持 API 的一致性,旧的架构没有做太多改变,遗留了很多的包袱。阔别 2 年多后,2020 年 10 月 10 日,webpack 5 正式发布,并带来了诸多重大的变更,将会使前端工程师的构建效率与质量大为提升。

本次重大发布的整体发展方向如下:

  • 尝试用持久性缓存来提高构建性能。
  • 尝试用更好的算法和默认值来改进长期缓存。
  • 尝试用更好的 Tree Shaking 和代码生成来改善包大小。
  • 尝试改善与网络平台的兼容性。
  • 尝试在不引入任何破坏性变化的情况下,
    • 清理那些在实现 v4 功能时处于奇怪状态的内部结构。
  • 试图通过现在引入突破性的变化来为未来的功能做准备,
    • 尽可能长时间地保持在 v5 版本上。

webpack 5Release Note 非常长,本文尝试摘出最简练的信息。

功能清除

清理已弃用的功能

所有在 webpack 4 标记即将过期的功能,都已在该版移除。因此在迁移到 webpack 5 之前,请确保你在 webpack 4 运行的构建不会有任何的功能过期警告。

不再为 Node.js 模块 自动引用 Polyfills

不再为 Node.js 内置模块自动添加 Polyfills。任何项目中有引用 Node.js 内置模块,在 webpack 4 或之前的版本中会自动添加 Polyfills。但 webpack 5 将不会再这样做,webpack会投入更多的精力到前端模块的兼容性工作中。

如果你的代码中有引用这些 Node.js 的模块,要升级到 webpack 5, 将尽量使用前端的模块,或者自行手动添加适合的 Polyfills

而针对那些类库的开发者,请在 package.json 中定义 browser 字段,使类库在前端能适用。

针对长期缓存的优化

确定的 Chunk、模块 ID 和导出名称

新增了长期缓存的算法。这些算法在生产模式下是默认启用的。

chunkIds: "deterministic"moduleIds: "deterministic"mangleExports: "deterministic"

该算法以确定性的方式为模块和分块分配短的(3 或 5 位)数字 ID,这是包大小和长期缓存之间的一种权衡。由于这些配置将使用确定的 ID 和名称,这意味着生成的缓存失效不再更频繁。

真正的内容哈希

当使用[contenthash]时,Webpack 5 将使用真正的文件内容哈希值。之前它 "只 "使用内部结构的哈希值。当只有注释被修改或变量被重命名时,这对长期缓存会有积极影响。这些变化在压缩后是不可见的。

更好的开发支持

命名代码块 ID

在开发模式下,默认启用的新命名代码块 ID 算法为模块(和文件名)提供了人类可读的名称。模块 ID 由其路径决定,相对于 context。代码块 ID 由代码块的内容决定。

所以你不再需要使用import(/* webpackChunkName: "name" */ "module")来调试。但如果你想控制生产环境的文件名,还是有意义的。

可以在生产环境中使用 chunkIds: "named" 在生产环境中使用,但要确保不要不小心暴露模块名的敏感信息。

迁移:如果你不喜欢在开发中改变文件名,你可以通过 chunkIds: "natural" 来使用旧的数字模式。

模块联邦

Webpack 5 增加了一个新的功能 "模块联邦",它允许多个 webpack 构建一起工作。从运行时的角度来看,多个构建的模块将表现得像一个巨大的连接模块图。从开发者的角度来看,模块可以从指定的远程构建中导入,并以最小的限制来使用。

支持崭新的 Web 平台功能

对于 Web 平台的的一些支持 ,Webpack 5 也做了更好的完善更新。

JSON 模块

比如对 JSON 模块,会与现在的提案保持一致,并且要求进行默认的导出,否则会有警告信息。即使使用默认导出,未使用的属性也会被 optimization.usedExports 优化丢弃,属性会被 optimization.mangleExports 优化打乱。

如果想用自定义的 JSON 解析器,可以在 Rule.parser.parse 中指定一个自定义的 JSON 解析器来导入类似 JSON 的文件(例如针对 toml、yaml、json5 等)。

资源模块

Webpack 5 现在已经对表示资源的模块提供了内置支持。这些模块可以向输出文件夹发送一个文件,或者向 javascript 包注入一个 DataURI。无论哪种方式,它们都会给出一个 URL 来工作。

它们可以通过多种方式被使用:

  • import url from "./image.png" 和 在module.rule 中设置 type: "asset"当匹配这样的导入时。(老方法)
  • new URL("./image.png", import.meta.url) (新方式)

选择 "新的方式 "语法是为了允许在没有打包工具的情况下运行代码。这种语法也可以在浏览器中的原生 ECMAScript 模块中使用。

原生 Worker 支持

当把资源的 new URLnew Worker/new SharedWorker/navigator.serviceWorker.register 结合起来时,webpack 会自动为 web worker 创建一个新的入口点(entrypoint)。

new Worker(new URL("./worker.js", import.meta.url))

选择这种语法也是为了允许在没有打包工具的情况下运行代码。这种语法在浏览器的原生 ECMAScript 模块中也可以使用。

URIs

Webpack 5 支持在请求中处理协议。

  • 支持data:。支持 Base64 或原始编码。Mimetype 可以在module.rule中被映射到加载器和模块类型。例如:import x from "data:text/javascript,export default 42"
  • 支持file:
  • 支持http(s):,但需要通过new webpack.experiments.s schemesHttp(s)UriPlugin()选择加入。
    • 默认情况下,当目标为 "web "时,这些 URI 会导致对外部资源的请求(它们是外部资源)。

支持请求中的片段。例如:./file.js#fragment

异步模块

Webpack 5 支持所谓的 "异步模块"。这些模块并不是同步解析的,而是基于异步和 Promise 的。

通过 "import "导入它们会被自动处理,不需要额外的语法,而且几乎看不出区别。

通过require()导入它们会返回一个解析到导出的 Promise。

在 webpack 中,有多种方式来拥有异步模块。

  • 异步的外部资源(async externals)
  • 新规范中的 WebAssembly 模块
  • 使用顶层 Await 的 ECMAScript 模块。

外部资源

Webpack 5 增加了更多的外部类型来覆盖更多的应用:

promise: 一个评估为 Promise 的表达式。外部模块是一个异步模块,解析值作为模块导出使用。

import。原生的 import() 用于加载指定的请求,外部模块是一个异步模块,解析值作为模块导出。外部模块是一个异步模块。

module: 尚未实现,但计划通过 import x from "..." 加载模块。

script: 通过