🗒️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 可以是来自应用程序的代码,也可以来自第三方库。
resolver 会帮 webpack 为每个这样的 require/import
语句找到要包含在 bundle 中的 module 代码。在打包模块(bundle modules)时,webpack 使用 enhanced-resolve
来解析文件路径。
2.1 解析规则
使用 enhanced-resolve
,webpack 可以解析三种文件路径:
重点介绍下模块路径。
解析路径
在
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