🗒️module
1. modules
1.1 模块类型
webpack 特性之一就是能通过 import 导入任何类型的模块,它支持的模块类型:
- CommonJS 模块 
- AMD 模块 
- Assets 模块,即资源文件(比如字体/图标),不用配置额外的 loader 
- WebAssembly 模块 
webpack 还支持使用多种语言编写的 module 及其相应的 loader 预处理器。
loader 向 webpack 描述如何处理 non-native 的 module 以及如何将这些 dependencies 包含到我们的 bundles 里。webpack 社区已经为各种流行的语言和语言处理器构建了 loaders(常见的如下),更多详见 loader 列表和自定义 loader。
- ESNext (Babel) / TypeScript / CoffeeScript 
- Sass / Less / Stylus 
- Elm 
每个 module 都有其对应的 loader
1.2 模块依赖关系
webpack modules 能以各种方式表达它们的依赖关系,比如:
- ES6 - import语句
- CommonJS - require()语句
- AMD - define和- require语句
- css/sass/less 文件里的 - @import语句
- 图片的 url 地址:样式表 - url(...), HTML- <img src=...>
1.3 模块打包
为了更好地理解 module bundlers 背后的思想及其底层原理,可以进一步阅读:
2. 模块解析
resolver 是一个库,可以通过 module 的绝对路径来定位 module。
一个 module 可以依赖另一个 module。所依赖的 module 可以是来自应用程序的代码,也可以来自第三方库。
import foo from 'path/to/module';
// or
require('path/to/module');resolver 会帮 webpack 为每个这样的 require/import 语句找到要包含在 bundle 中的 module 代码。在打包模块(bundle modules)时,webpack 使用 enhanced-resolve 来解析文件路径。
2.1 解析规则
使用 enhanced-resolve,webpack 可以解析三种文件路径:
// 1. 绝对路径
import '/home/me/file';
import 'C:\\Users\\me\\file';
// 2. 相对路径
import '../src/file1';
import './file2';
// 3. 模块路径
import 'module';
import 'module/lib/file';重点介绍下模块路径。
- 解析路径 - 在 - resolve.modules指定的所有目录中搜索 modules,也可以使用- resolve.alias选项将原始模块路径替换为备用路径
- 按顺序查找 - resolve.exportsFields指定的字段,package.json 中的第一个此类字段决定可用的 exports(根据 package exports guideline)
 
- resolver 检查路径是文件还是文件夹: - 如果路径指向文件 - 如果有扩展名,则直接打包该文件 
- 否则就使用 - resolve.extensions指定的扩展名来解析,例如- .js,- .jsx
 
- 如果路径指向文件夹,则根据以下步骤找到具有正确扩展名的正确文件 - 按顺序查找 - resolve.mainFields指定的字段,package.json 中的第一个此类字段决定文件路径
- 如果没有 - package.json或- resolve.mainFields不是有效路径,则按顺序查找- resolve.mainFiles指定的文件名,看在该目录下是否存在匹配的文件名
- 解析文件扩展名,用类似 - resolve.extensions的方式
 
 
webpack 会根据我们的构建目标为这些选项提供合理的默认值,详见 Configuration/Resolve。
2.2 解析 loader
loader 的解析规则和文件解析的规则相同。只是 resolveLoader 配置选项可以为 loader 设置独立的解析规则,详见 Configuration/Resolve/#resolveloader。
2.3 缓存
通常,文件系统的访问都会被缓存。在 watch 模式下,只有修改过的文件才会从缓存中移除。如果关闭 watch 模式,则会在每次编译之前清除缓存。
更多配置信息,可查阅 Resolve API (Configuration/Resolve)。
3. 模块联盟
多个独立的 builds 应该形成一个应用程序。这些单独的 build 之间不应该有依赖关系,因此它们可以单独开发和部署。
模块分为:
- local modules,本地模块:就是普通模块,它是当前 build 的一部分。 
- remote modules,远程模块:不属于当前 build,它是在运行时从所谓的 container 里加载的 - 加载远程模块是个异步操作,它们会放在远程模块和入口之间的下一个 chunk 的加载操作中。没有 chunk 的加载操作,就不可能使用远程模块。chunk 的加载操作通常是使用 - import()调用的,但也支持像- require.ensure或- require([...])这样的旧语法。
- container 是通过 container 入口创建的,该入口公开了对特定 modules 的异步访问,分两个步骤:加载模块(异步)、执行模块(同步) 
- container 可以嵌套使用。container 可以使用来自其它 container 的 module。container 之间也可以循环依赖 
 
每个 build 都可以充当 container,并将其它 build 作为 container 使用。这样每个 build 都可以访问其它 container 公开的 module。
相关说明:
- import 和 export 任何 webpack 支持的 module 类型 
- chunk 加载应该是并行的 
- 从 consumer 到 container 的控制 - 覆盖 module 是一种单向操作 
- 同级 container 不能覆盖彼此的 module 
 
- 共享中的相对请求和绝对请求 - 会一直提供,即使不使用 
- 会相对于 - config.context进行解析
- 默认不使用 - requiredVersion
 
- 共享中的 module 请求 - 仅在使用时提供 
- 会匹配在 build 中使用的所有相等 module 请求 
- 会提供所有匹配的 modules 
- 会从 package.json 中提取 - requiredVersion,在 graph 中的这个位置
- 可以提供和使用多个不同的版本,当有嵌套的 node_modules 时 
 
- 共享中的以 - /结尾的 module 请求,会匹配所有具有此前缀的 module 请求
更多内容,可查看 Concepts/Module Federation。
Last updated