关于前端:Webpack-5-正式发布

4次阅读

共计 13995 个字符,预计需要花费 35 分钟才能阅读完成。

Webpack 简介

随着前端倒退如日冲天,前端我的项目也越来越简单,得益于 Nodejs 的倒退,前端模块化、组件化、工程化也大势所趋。随同着前端的模块化和工程化,Grunt、Gulp 到 Webpack 等我的项目构建和打包工具也随之呈现。

前端工程化的晚期,次要是解决反复工作的问题。Grunt、Gulp 就是其中代表,他们的次要性能是实现文件压缩、编译 less、sass、地址增加 hash、替换等。不过,随着前端工程化的倒退,Webpack 呈现了,与其说是一个工程构建工具,Webpack 更像是一套前端工程化解决方案。

依据官网材料介绍,Webpack 是一个前端资源加载和打包工具。所谓的模块就是在平时的前端开发中,用到一些动态资源,如 JavaScript、CSS、图片等文件,Webpack 就将这些动态资源文件称之为模块。Webpack 反对 AMD 和 CommonJS,以及其余的一些模块零碎,并且兼容多种 JS 书写标准,能够解决模块间的依赖关系,所以具备更弱小的 JS 模块化的性能,它能对动态资源进行对立的治理以及打包公布。作为一款 Grunt 和 Gulp 的代替产品,Webpack 受到大多数开发者的青睐,因为它可能编译打包 CSS,做 CSS 预处理,对 JS 的方言进行编译,打包图片,代码压缩等等。

Webpack 5

自 2018 年 2 月 Webpack4 公布以来,Webpack 就始终没有更进一步的重大更新,为了放弃 API 的一致性,旧的架构没有做太多扭转,遗留了很多的包袱。或者是寂静太久,2020 年 10 月 10 日,Webpack 正式公布了 5.0 版本。Webpack 5 带来了哪些新的个性呢?

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

上面就让咱们来看一下,Webpack 5 带来的一些新的个性。

1,革除过期性能

1.1 清理已弃用的性能

所有在 Webpack 4 标记行将过期的性能,都已在该版移除。因而在迁徙到 Webpack 5 之前,请确保你在 Webpack 4 运行的构建不会有任何的性能过期正告,否则迁徙到 Webpack 5 之后就会报错。

1.2 不再为 Node.js 模块主动援用 Polyfills

在 Webpack 4 或之前的版本中,任何我的项目援用 Node.js 内置模块都会主动增加 Polyfills,Polyfills 是一个语法查看的模版工具。不过,Webpack 5 不再为 Node.js 内置模块主动增加 Polyfills,Webpack 5 会投入更多的精力到前端模块的兼容性工作中。

如果你的代码中有援用这些 Node.js 的模块,当须要降级到 Webpack 5 版本时,请将尽量应用前端的模块,或者自行手动增加适宜的 Polyfills。

2. 针对长期缓存的优化

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

Webpack 5 新增了长期缓存的算法,这些算法在生产模式下是默认启用的,语法格局如下。

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

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

2.2 真正的内容哈希

当应用 [contenthash] 时,Webpack 5 将应用真正的文件内容哈希值。之前它 “ 只 “ 应用内部结构的哈希值。当只有正文被批改或变量被重命名时,这对长期缓存会有踊跃影响。这些变动在压缩后是不可见的。

3. 更好的开发反对

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

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

能够在生产环境中应用 chunkIds: "named" 在生产环境中应用,但要确保不要不小心裸露模块名的敏感信息。如果你不喜爱在开发中扭转文件名,你能够通过 chunkIds: "natural" 来应用旧的数字模式。

3.2 模块联邦

Webpack 5 减少了一个新的性能 “ 模块联邦 ”,它容许多个 Webpack 一起工作。从运行时的角度来看,多个构建的模块将体现得像一个微小的连贯模块图。从开发者的角度来看,模块能够从指定的近程构建中导入,并以最小的限度来应用。

4. 对 Web 平台性能的全新反对

4.1 JSON 模块

比方对 JSON 模块,会与当初的提案保持一致,并且要求进行默认的导出,否则会有正告信息。即便应用默认导出,未应用的属性也会被 optimization.usedExports 优化抛弃,属性会被 optimization.mangleExports 优化打乱。

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

4.2 资源模块

Webpack 5 当初曾经对示意资源的模块提供了内置反对。这些模块能够向输入文件夹发送一个文件,或者向 Javascript 包注入一个 DataURI。无论哪种形式,它们都会给出一个 URL 来让程序失常工作。

import url from "./image.png" // 老办法
new URL("./image.png", import.meta.url)  // 新办法

抉择 “ 新的形式 “ 语法是为了容许在没有打包工具的状况下运行代码。这种语法也能够在浏览器中的原生 ECMAScript 模块中应用。

4.3 原生 Worker 反对

当把资源的 new URLnew Worker/new SharedWorker/navigator.serviceWorker.register 联合起来时,Webpack 会主动为 Web Worker 创立一个新的入口点(entrypoint),如下所示。

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

抉择这种语法也是为了容许在没有打包工具的状况下运行代码。这种语法在浏览器的原生 ECMAScript 模块中也能够应用。

4.4 URIs

Webpack 5 反对在申请中解决网络协议,比方:

  • 反对 data:反对 Base64 或原始编码。Mimetype 能够在 module.rule 中被映射到加载器和模块类型。例如:import x from “data:text/javascript,export default 42″。
  • 反对 file:反对 file 文件类型。

反对 http(s):须要通过 new webpack.experiments.s schemesHttp(s)UriPlugin() 抉择退出。

4.5 异步模块

Webpack 5 反对所谓的 “ 异步模块 ”。这些模块并不是同步解析的,而是基于异步和 Promise 的。通过 import 导入它们会被主动解决,不须要额定的语法,而且简直看不出区别。通过require() 导入它们会返回一个解析到导出的 Promise。在 Webpack 中,有多种形式来领有异步模块,常见的形式如下:

  • 异步的内部资源(async externals)
  • 新标准中的 WebAssembly 模块
  • 应用顶层 Await 的 ECMAScript 模块。

4.6 内部资源

Webpack 5 减少了更多的内部类型来反对更多的利用。
promise: 一个评估为 Promise 的表达式,内部模块是一个异步模块,解析值作为模块导出应用。
import:原生的 import() 用于加载指定的申请,内部模块是一个异步模块,解析值作为模块导出,内部模块是一个异步模块。
module:尚未实现,但打算通过 import x from “…” 加载模块。
script:通过 <script> 标签加载一个 url,并从一个全局变量(以及它的可选属性)中获取输入。内部模块是一个异步模块。

5. 开发体验上的晋升

5.1 通过优化的构建指标(target)

Webpack 5 容许传递一个指标列表,并且反对指标的版本。例如:

target: "node14" 
target: ["web", "es2020"]。

这是一个简略的办法,为 webpack 提供它须要确定的所有信息:代码块加载机制,以及反对的语法,如箭头函数。

5.2 统计格局

改良了统计测试格局的可读性和冗余性。改良了默认值,使其不那么简短,也适宜大型构建。

5.3 进度

ProgressPlugin插件也做了一些优化,当初不仅能够统计模块编译的进度,也能够统计 入口 和 依赖。并且,之前展现进度可能会对构建性能有肯定的影响,这次的降级也做了一些性能方面的优化。

5.4 主动增加惟一命名

在 Webpack 4 中,多个 Webpack 同时运行时可能会在同一个 HTML 页面上发生冲突,因为它们应用同一个全局变量进行代码块加载。为了解决这个问题,须要为 output.jsonpFunction 配置提供一个自定义的名称。

同时,Webpack 5 会从 package.json name 中主动推断出一个惟一的构建名称,并将其作为 output.uniqueName 的默认值。因为 package.json 中有惟一的名称,可将 output.jsonpFunction删除。

5.5 主动增加公共门路

Webpack 5 会在可能的状况下主动确定 output.publicPath,无需开发者手动确认。

5.6 Typescript 类型

Webpack 5 能够从源码中生成 typescript 类型,并通过 npm 包裸露它们。如果要迁徙到 Webpack 5 版本,须要删除 @types/webpack

6. 构建优化

6.1 嵌套的 tree-shaking

当初,Webpack 可能跟踪对导出的嵌套属性的拜访,因而能够改善从新导出命名空间对象时的 Tree Shaking(革除未应用的导出和混同导出),如下所示。

// inner.js
export const a = 1;
export const b = 2;

// module.js
export * as inner from './inner';
// 或 
import * as inner from './inner'; export {inner};

// user.js
import * as module from './module';
console.log(module.inner.a);

6.2 外部模块 tree-shaking

Webpack 4 没有剖析模块的导出和援用之间的依赖关系,Webpack 5 有一个新的选项 optimization.innerGraph,在生产模式下是默认启用的,它能够对模块中的标记进行剖析,找出导出和援用之间的依赖关系。

import {something} from './something';

function usingSomething() {return something;}

export function test() {return usingSomething();
}

外部依赖图算法会找出 something 只有在应用 test 导出时才会应用。这容许将更多的进口标记为未应用,并从代码包中省略更多的代码。

当设置 "sideEffects": false 时,能够省略更多的模块。在这个例子中,当 test 导出未被应用时,./something 将被省略。要取得未应用的导出信息,须要应用 optimization.unusedExports。要删除无副作用的模块,须要应用 optimization.sideEffects。能够剖析以下标记:

  • 函数申明
  • 类申明
  • 默认导出 export default 或定义变量以下的
    1,函数表达式

2,类表达式
3,程序表达式
4,/#__PURE__/ 表达式
5,局部变量
6,引入的捆绑(bindings)

应用 eval() 将为一个模块放弃这个优化,因为通过 eval 的代码能够援用范畴内的任何标记。这种优化也被称为深度范畴剖析。

6.3 CommonJs Tree Shaking

已经,Webpack 不反对对 CommonJs 进行 导出和 require() 调用时的导出应用剖析。当初,Webpack 5 减少了对一些 CommonJs 结构的反对,容许打消未应用的 CommonJs 导出,并从 require() 调用中跟踪援用的导出名称。

反对的结构如下:

  • exports|this|module.exports.xxx = …
  • exports|this|module.exports = require(“…”) (reexport)
  • exports|this|module.exports.xxx = require(“…”).xxx (reexport)
  • Object.defineProperty(exports|this|module.exports, “xxx”, …)
  • require(“abc”).xxx
  • require(“abc”).xxx()
  • 从 ESM 导入
  • require() 一个 ESM 模块
  • 被标记的导出类型 (对非严格 ESM 导入做非凡解决)
  • 将来打算反对更多的结构

6.4 开发与生产的一致性问题

Webpack 正在通过改善开发模式很晚生产模式的相似性,并在开发模式上晋升构建性能,防止仅在生产模式的产生的问题之间找到一个很好的平衡点。

Webpack 5 默认在两种模式下都启用了 "sideEffects"优化。在 Webpack 4 中,因为 package.json 中的 ”sideEffects” 标记不正确,这种优化导致了一些只在生产模式下呈现的谬误。r 如果在开发过程中启用这个优化,能够更快更容易地发现这些问题。

在很多状况下,开发和生产都是在不同的操作系统上进行的,文件系统的大小写敏感度不同,所以 Webpack 5 减少了一些奇怪的大小写的正告 / 谬误。

6.5 改良 target 配置

在 Webpack 4 中,”target “ 是在 “web” 和 “node” 之间的一个粗略的抉择(还有一些其余的)。Webpack 5 给开发者留下了更多的抉择。target 选项当初比以前影响了更多对于生成代码的事件,比方代码块加载办法、代码块的格局、externals 是否默认被启用等等。

此外,对于其中的一些状况,在 “web” 和 “node” 之间的抉择过于粗略,咱们须要更多的信息。因而,咱们容许指定最低版本,例如 “node10.13″,并推断出更多对于指标环境的属性。

当初 Webpack 也容许用一个数组组合多个指标,webpack 将确定所有指标的最小属性。应用数组也很有用,当应用像 “web” 或 “node” 这样没有提供残缺信息的指标时(没有版本号)。例如,[“web”, “es2020”] 联合了这两个局部指标。

有一个指标 “browserslist”,它将应用 browserslist 类库的数据来确定环境的属性。当我的项目中存在可用的 browserslist 配置时,这个指标也会被默认应用。当没有可用的配置时,默认应用 “web” 指标。

6.6 代码块拆分与模块大小

当初,Webpack 反对对模块依照大小进行拆分。SplitChunksPlugin 插件晓得如何解决这些不同模块的大小,并为它们设置 minSize 和 maxSize,如下所示。

module.exports = {
  optimization: {
    splitChunks: {
      minSize: {
        javascript: 30000,
        webassembly: 50000,
      },
    },
  },
};

7. 性能优化

7.1 长久缓存

当初有一个文件系统缓存,它是可选的,能够通过以下配置启用。

module.exports = {
  cache: {
    // 1. 将缓存类型设置为文件系统
    type: 'filesystem',

    buildDependencies: {
      // 2. 将你的 config 增加为 buildDependency,以便在扭转 config 时取得缓存
      config: [__filename],
      // 3. 如果有其余的货色须要被构建依赖,能够在这里增加它们
      // 留神,webpack、加载器和所有从你的配置中援用的模块都会被主动增加
    },
  },
};

阐明:
默认状况下,Webpack 假设 Webpack 所在的 node_modules 目录只被包管理器批改,对 node_modules 来说,哈希值和工夫戳会被跳过。出于性能思考,只应用包名和版本。只有不指定 resolve.symlinks: falseSymlinks(即 npm/yarn link) 就没有问题 (无论如何都要防止)。不要间接编辑 node_modules 中的文件,除非你用 snapshot.managedPaths: [] 以剔除该优化。当应用 Yarn PnP 时,webpack 假如 yarn 缓存是不可扭转的(通常是这样),此时能够应用 snapshot.immutablePaths: [] 来退出这个优化。

缓存将默认存储在 node_modules/.cache/webpack(当应用 node_modules 时)或 .yarn/.cache/webpack(当应用 Yarn PnP 时)中。当所有的插件都正确处理缓存时,你可能永远都不须要手动删除它。

许多外部插件也会应用持久性缓存。例如 SourceMapDevToolPlugin (缓存 SourceMap 的生成)或 ProgressPlugin (缓存模块数量)

持久性缓存将依据应用状况主动创立多个缓存文件,以优化对缓存的读写访问。默认状况下,工夫戳将用于开发模式的快照,而文件哈希将用于生产模式。文件哈希也容许在 CI 中应用持久性缓存。

7.2 编译器闲置和敞开

编译器当初须要在应用后敞开。编译器当初会进入和来到闲暇状态,并且有这些状态的钩子。插件可能会应用这些钩子来做不重要的工作。(行将长久缓存迟缓地将缓存存储到磁盘上)。在编译器敞开时 – 所有残余的工作应该尽可能快地实现。一个回调标记着敞开实现。

插件和它们各自的作者应该预料到,有些用户可能会遗记敞开编译器。所以,所有的工作最终也应该在闲暇状态下实现。当工作正在进行时,应该避免过程退出。webpack() 用法在被传递回调时主动调用 close。

7.3 文件生成

Webpack 过来总是在第一次构建时收回所有的输入文件,但在增量(察看)构建时跳过了写入未更改的文件。假如在 Webpack 运行时,没有任何其余货色扭转输入文件。
减少了持久性缓存后,即便在重启 Webpack 过程时,也会有相似监听的体验。所以,当初 Webpack 会查看输入目录中现有的文件,并将其内容与内存中的输入文件进行比拟,只有当文件被扭转时,它才会执行写入文件操作。
这只在第一次构建时进行。任何增量构建都会在运行中的 webpack 过程中生成新的资产时写入文件。

8. 重大问题

8.1 繁多文件指标的代码宰割

只容许启动单个文件的指标(如 node、WebWorker、electron main)当初反对运行时主动加载疏导所需的依赖代码片段。因而,容许对这些指标应用 chunks: "all"optimization.runtimeChunk
请留神,如果指标的代码块加载是异步的,这使得初始评估也是异步的。当应用 output.library 时,这可能是一个问题,因为当初导出的值是一个 Promise 解决后的值。

8.2 新的解析器

enhanced-resolve 更新到了 v5,有以下改良:

  • 追踪更多的依赖关系,比方失落的文件。
  • 别名可能有多种抉择
  • 当初能够别名为 false 了。
  • 反对 exports 和 imports 字段等性能。
  • 性能进步

8.3 没有 JS 的代码块

不蕴含 JS 代码的块,将不再生成 JS 文件。这就容许有只蕴含 CSS 的代码块。

9. 将来打算

9.1 试验个性

在 webpack 5 中,有一个新的 experiments 配置选项,容许启用试验性功能。这使得哪些性能被启用 / 应用变得很分明。

尽管 webpack 遵循语义版本化,但它会对试验性功能进行例外解决。试验性功能可能会在 webpack 的主要版本中蕴含破坏性的变动。当这种状况产生时,咱们会在变更日志中增加一个明确的正文。这将使咱们可能更快地迭代试验性功能,同时也使咱们可能在次要版本上为稳固的性能停留更长时间。

并且,以下的试验性能也会随 Webpack 5 一起公布。

  • 旧的 WebAssembly 反对,就像 Webpack 4 一样 (experiments.syncWebAssembly)
  • 依据更新的标准(experiments.asyncWebAssembly),新增 WebAssembly 反对。这使得一个 WebAssembly 模块成为一个异步模块。
  • 顶层的 Await 第三阶段提案 (experiments.topLevelAwait) 在顶层应用 await 使该模块成为一个异步模块。
  • 以模块的模式生成代码包 (experiments.outputModule)这就从代码包中移除了包装器 IIFE,执行严格模式,通过 <script type="module"> 进行懈怠加载,并在模块模式下最小化压缩。

9.2 最小 Node.js 版本

最低反对的 Node.js 版本从 6 减少到 10.13.0(LTS)。

10. 外部架构变更

上面是一些 Webpack 5 架构方面的变更:

10.1 新的插件运行程序

当初 webpack 5 中的插件在利用配置默认值之前就会被利用。这使得插件能够利用本人的默认值,或者作为配置预设。但这也是一个突破性的变动,因为插件在利用时不能依赖配置值的设置。
迁徙:只在插件钩子中拜访配置。或者最好完全避免拜访配置,并通过构造函数获取选项。

10.2 运行时模块

大部分的运行时代码被移到了所谓的 ” 运行时模块 ” 中。这些非凡模块负责增加运行时代码。它们能够被增加到任何块中,但目前总是被增加到运行时块中。
“ 运行时需要 ” 管制哪些运行时模块(或外围运行时部件)被增加到代码包中。这确保了只有应用的运行时代码才会被增加到代码包中。将来,运行时模块也能够增加到按需加载的块中,以便在须要时加载运行时代码。

在大多数状况下,外围运行代码时容许内联入口模块,而不是用 __webpack_require__ 来调用它。如果代码包中没有其余模块,则基本不须要应用__webpack_require__。这与模块合并很好地联合在一起,即多个模块被合并成一个模块。在最好的状况下,基本不须要运行时代码。

迁徙:如果你在插件中注入运行时代码到 Webpack 运行时,能够思考应用 RuntimeModules 来代替。

10.3 序列化

咱们增加了一个序列化机制,以容许在 webpack 中对简单对象进行序列化。它有一个可选的语义,所以那些应该被序列化的类须要被明确地标记进去(并且实现它们的序列化)。大多数模块、所有的依赖关系和一些谬误都曾经这样做了。

迁徙:当应用自定义模块或依赖关系时,倡议将它们实现成可序列化的,以便从长久化缓存中获益。

10.4 用于缓存的插件

减少了一个带有插件接口的 Cache 类。该类可用于写入和读取缓存。依据配置的不同,不同的插件能够为缓存增加性能。MemoryCachePlugin 减少了内存缓存性能。FileCachePlugin 减少了持久性(文件系统)缓存。FileCachePlugin 应用序列化机制将缓存我的项目长久化到磁盘上或从磁盘上复原。

10.5 Tapable 插件降级

Webpack 3 插件的 compat 层曾经被移除,并且它在 Webpack 4 中曾经被勾销了,一些较少应用的 tapable API 被删除或废除。

10.6 Main/Chunk/ModuleTemplate 废除

打包模板曾经重构。MainTemplate/ChunkTemplate/ModuleTemplate 被废除,当初 JavascriptModulesPlugin 负责 JS 模板。

在那次重构之前,JS 输入由 Main/ChunkTemplate 解决,而另一个输入(即 WASM、CSS)则由插件解决。重构后这一点被扭转了,所有的输入都由他们的插件解决。

仍然能够侵入局部模板。钩子当初在 JavascriptModulesPlugin 中,而不是 Main/ChunkTemplate 中。(是的,插件也能够有钩子,我称之为附加钩子。)有一个兼容层,所以 Main/Chunk/ModuleTemplate 依然存在,但只是将 tap 调用委托给新的钩子地位。

10.7 入口文件的新增配置

在 Webpack 5 中,入口文件除了字符串、字符串数组,也能够应用描述符进行配置了,如下所示。

module.exports = {
  entry: {
    catalog: {import: './catalog.js',},
  },
};

此外,咱们也能够定义输入的文件名,之前都是通过 output.filename 进行定义的,如下所示。

module.exports = {
  entry: {about: { import: './about.js', filename: 'pages/[name][ext]' },
  },
};

另外,入口文件的配置,新增了文件依赖定义、生成类库的格局类型(commonjs 或 amd),也能够设置运行时的名字,以及代码块加载的形式,更多细节能够参考残缺的公布记录。

10.8 排序与 ID

Webpack 已经在编译阶段以特定的形式对模块和代码块进行排序,以递增的形式调配 ID。当初不再是这样了。程序将不再用于 ID 的生成,取而代之的是,ID 的生成齐全由插件进行管制,并且优化模块和代码块程序的钩子曾经被移除。

10.9 从数组到汇合(Set)

  • Compilation.modules 当初是一个汇合
  • Compilation.chunks 当初是一个汇合
  • Chunk.files 当初是一个汇合

10.10 文件系统与信息变更

在 Webpack 5 中,一个是须要应用 Compilation.fileSystemInfo 代替 file/contextTimestamps,获取文件的工夫戳信息,另一个是新增 Compiler.modifiedFiles 以便更容易援用更改后的文件。
另外,还新增了一个相似于 compiler.inputFileSystemcompiler.outputFileSystem 的新 API compiler.intermediateFileSystem,用于所有不被认为是输出或输入的 fs 操作,如写入 records,缓存或输入 profiling。

10.11 模块热替换

HMR 运行时已被重构为运行时模块。HotUpdateChunkTemplate 已被合并入 ChunkTemplate 中。ChunkTemplates 和 plugins 也应解决 HotUpdateChunk 了。

HMR 运行时的 Javascript 局部已从外围 HMR 运行时钟拆散了进去。其余模块类型当初也能够应用它们本人的形式解决 HMR。在将来,这将使得 HMR 解决诸如 mini-css-extract-plugin 或 WASM 模块。

迁徙:此为新性能,无需迁徙。
import.meta.webpackHot 公开了与 module.hot 雷同的 API。当然能够在 ESM 模块(.mjs,package.json 中的 type: “module”)中应用,这些模块不能拜访 module。

10.12 工作队列

Webpack 已经通过函数调用函数的模式来进行模块解决,还有一个 semaphore 选项限度并行性。Compilation.semaphore 已被移除,当初能够应用异步队列解决,每个步骤都有独立的队列:

  • Compilation.factorizeQueue:为一组 dependencies 调用模块工厂。
  • Compilation.addModuleQueue:将模块增加到编译队列中(能够应用缓存复原模块)
  • Compilation.buildQueue:必要时构建模块(可将模块存储到缓存中)
  • Compilation.rebuildQueue:如需手动触发,则会从新构建模块
  • Compilation.processDependenciesQueue:解决模块的 dependencies。

这些队列会有一些 hook 来监听并拦挡工作的过程。将来,多个编译器会同时工作,能够通过拦挡这些队列来进行编译工作的编排。

10.13 模块和 chunk 图

Webpack 已经在依赖关系中存储了已解析的模块,并在 chunk 中存储引入的模块。但现已发生变化。所有对于模块在模块图中如何连贯的信息,当初都存储在 ModulGraph 的 class 中。所有对于模块与 chunk 如何连贯的信息当初都已存储在 ChunkGraph 的 class 中。依赖于 chunk 图的信息也存储在相干的 class 中。

以下列举一些模块的信息已被挪动的例子:

  • Module connections -> ModuleGraph
  • Module issuer -> ModuleGraph
  • Module optimization bailout -> ModuleGraph (TODO: check if it should ChunkGraph instead)

当从缓存中复原模块时,Webpack 会将模块从图中断开。当初已无需这么做。一个模块不存储图形的任何信息,技术上能够在多个图形中应用。这会使得缓存变得更加容易。这部分变动中大多数都有一个适配层,当应用时,它会打印一个弃用正告。

10.14 模块 Source Types

当初,模块必须通过 Module.getSourceTypes() 来定义它们反对的源码类型。依据这一点,不同的插件会用这些类型调用 source()。对于源类型为 Javascript 的 JavascriptModulesPlugin 会将源代码嵌入到 bundle 中。源类型 Webassembly 的 WebAssemblyModulesPlugin 会 emit 一个 wasm 文件。同时,也反对自定义源类型,例如,mini-css-extract-plugin 会应用源类型为 stylesheet 将源码嵌入到 css 文件中。

模块类型与源类型间没有关系。即便模块类型为 Json,也能够应用源类型为 Javascript 和模块类型为 webassembly/experimental 的 Javascript 和 Webassembly。

10.15 全新的观察者

Webpack 所应用的观察者已重构。它之前应用的是 chokidar 和原生依赖 fsevents(仅在 OSX 上)。当初它在只基于原生的 Node.js 中的 fs,这意味着在 webpack 中曾经没有原生依赖了。

它还能在监听时捕获更多对于文件系统的信息。目前,它还能够捕捉 mtimes 和监督事件工夫,以及失落文件的信息。为此,WatchFileSystem API 做了一点小改变。在批改的同时,咱们还将 Arrays 转换为 Sets,Objects 转换为 Maps。

10.16 SizeOnlySource after emit

Webpack 当初应用 SizeOnlySource 替换 Compilation.assets 中的 Sources,以缩小内存占用状况。

10.17 ExportsInfo

重构了模块导出信息的存储形式。ModuleGraph 当初为每个 Module 提供了一个 ExportsInfo,它用于存储每个 export 的信息。如果模块仅以副作用的形式应用,它还存储了对于未知 export 的信息,并且每个 export 都会存储以下信息:

  • 是否应用 export? 是否应用并不确定。
  • 是否提供 export? 是否提供并不确定。
  • 是否重命名 export 名? 是否重命名,也不确定
  • 如果 export 已重新命名,则为新名称。
  • 嵌套的 ExportsInfo,如果 export 是一个含有附加信息的对象,那么它自身就是一个对象。

10.18 代码生成阶段

编译的代码生成性能作为独自的编译阶段。它不再暗藏在 Module.source() 和 Module.getRuntimeRequirements() 中运行了。这应该会使得流程更加简洁。它还运行报告该阶段的进度。并使得代码生成在分析时更加清晰可见。

迁徙时,Module.source()Module.getRuntimeRequirements() 已弃用,而后应用 Module.codeGeneration() 代替。

10.19 依赖关系参考

Webpack 已经有一个繁多的办法和类型来示意依赖关系的援用(Compilation.getDependencyReference 会返回一个 DependencyReference)该类型用于引入对于该援用的所有信息,如 被援用的模块,曾经引入了哪些 export,如果是弱援用,还须要订阅一些相干信息。把所有这些信息构建在一起,拿到参考的老本就很高,而且很频繁(每次有人须要一个信息)。

在 Webpack5 中,这部分代码库被重构了,办法进行了拆分:

  • 援用的模块能够从 ModuleGraphConnection 中读取
  • 引入的导出名,能够通过 Dependency.getReferencedExports() 获取
  • Dependency 的 class 上会有一个 weak 的 flag
  • 排序只与 HarmonyImportDependencies 相干,能够通过 sourceOrder 属性获取

10.20 Presentational Dependencies

这是 NormalModules 的一种新 Dependencies 类型:Presentational Dependencies。这些 dependencies 只在代码生成阶段应用,但在模块图构建过程中未应用。所以它们永远不能引用模块或影响导出 / 导入。这些依赖关系的解决老本较低,Webpack 会尽可能地应用它们。

10.21 弃用 loaders

null-loader 已被弃用,能够应用上面的写法进行替换。

module.exports = {
  resolve: {
    alias: {xyz$: false,},
  },
};
// 或者应用绝对路径
module.exports = {
  resolve: {
    alias: {[path.resolve(__dirname, '....')]: false,
    },
  },
};

总的来说,Webpack 5 的大部分工作都围绕优化进行开展,去除了 Webpck 4 中有废除的内容,新增了长期缓存,优化了内核等内容。

参考文档:中文文档:webpack.docschina.org

正文完
 0