一、前文回顾
受限于篇幅,上文并没有完全完成整个流水线的注册工作,之所以不在一篇写完也是不想给各位读者带来过大的压力!
我们大致回顾一下从今天的流水线内容:
- resolve 开始解析:注册 UnsafeCachePlugin、ParsePlugin 插件;
- paresed-resolve:request 解析阶段;
- described-resolve 描述文件已解析;
- raw-resolve: 原始解析阶段,处理 alias/aliasFields/extension/extensionAlias;
二、流水线注册(2)
这里接着上文未尽的流水线注册内容:
2.1 // normal-resolve: 普通解析阶段
-
判断 preferRealative 配置项,默认
false,如果为 true,则注册 JoinRequestPlugin 插件,该插件的 source 钩子是after-normal-resolve,target 钩子是relative。preferRealative 是偏好相对路径,其作用是把不写路径的的 request ,比如import logo from 'logo1';logo1 就会被当成 './logo1.js' 而不是当成 node_modules/logo1 这个模块文件夹解析。上 webpack.config.js.resolve.preferRelative 传送门 -
注册 ConditionalPlugin 插件,条件 { module: true },source 钩子为
after-normal-resolve,target 钩子为raw-resolve钩子。作为模块解析? -
注册 ConditionalPlugin 插件,条件 { internal: true },source 钩子为
after-normal-resolve,target 钩子为internal钩子。作为内部 import 解析? -
判断如果 preferAbsolute 配置项,默认
false,如果为true注册 JoinRequestPlugin 拼接请求,source 钩子为after-normal-resolve,target 钩子为relative。preferAbsolute 是指在解析的过程中优先 webpack.config.js.resolve.roots 配置的包管理路径; -
判断 roots.length > 0,即 webpack.config.js.resolve.roots 配置不为空,就注册 RootsPlugin 插件,
source 钩子为after-normal-resolve,target 钩子为relative。webpack.config.js.resolve.roots 是 webpack 解析包的根路径,默认是 webpack 配置的 context 目录,上 resolve.roots 传送门 -
判断
!preferRelative && !preferAbsolute,如果条件成立表示无绝对路径偏好或者相对路径偏好,此时再次注册 JoinRequestPlugin,source 钩子after-normal-resolve,target 钩子relative;这里有个问题?为啥 preferAbsolute 和 preferRelative 成立时注册 JoinRequestPlugin,都不满足的时候也要注册 JoinRequestPlguin?
2.2 // internal: 内部解析阶段
遍历 importsFields 字段,为每个字段注册 ImportsFieldPlugin 插件,source 钩子 internal,target 钩子 internal-resolve。importsFields 是用于提供包内部request 的 package.json 中的字段名,上 webpack.config.js.resolve.importsFields 传送门。值得注意的是官方文档上写的 importsFields 配置似乎有点问题,应该是:importFields: ["imports"],imports 对应的就是 package.json.imports 字段,而不是配置 browser/node/module 这样的值。。。
就是说有些包内部的某些模块是可以直接给当前包内部解析用的比如有个 npm 包叫做 "qiang-sheng-group",里面有两个模块 "tangxiaolong.js"、 "tangxiaohu.js" 两个模块除了强哥家里人谁也不敢用,这个时候这个包的 package.json 里面就要写上:
{
"name": "qiang-sheng-group",
"main": "./lib/gaoqiqiang.js",
"imports": {
"#xiaohu": "./lib/tangxiaohu.js",
"#xiaolong": "./lib/tangxiaolong.js"
}
}
这个时候 "gaoqiqiang.js" 里面就可以通过以下方式调用:
import TangXiaolong from '#xiaolong';
console.log(Tangxiaolong)
其中 "#xiaolong" 就会发起内部 request;
imports 字段更多参考文献(反正我是看了TM好久才看明白的,原文赶紧上车李有田主任的车):
2.3 // raw-module 阶段
-
遍历
exportsFields字段,为每个字段注册SelfReferencePlugin插件。source 钩子raw-module,target 钩子resolve-as-module。exportsFileds 是借助 package.json.exports(或其他字段)改写原有的 package.json 通过 main 字段指定入口等行为的,除了可以改写 main 主入口,还可以改写 pgk/sub/path 这种子路径,上 [webpack.config.js.resolve.exportsFields 传送门]。(webpack.js.org/configurati…) -
遍历 modules 配置项,配置不同插件插件的 source 钩子为
raw-module,target 钩子为module。webpack.config.js.resolve.modules 可以理解成一组包管理管理的目录,就是 node_modules 同功能的目录,告诉 webpack 从哪个路径解析包。webpack.config.js.resolve.modules 传送门 根据配置不同有以下不同行为:- 2.1 如果 item 是数组并且是 pnp 环境则注册
ModulesInHierarchicalDirectoriesPlugin插件 和PnpPlugin插件。 - 2.2 否则注册
ModulesInHierarchicalDirectoriesPlugin插件;我们使用 node_modules 就是这个插件处理的。
- 2.1 如果 item 是数组并且是 pnp 环境则注册
三、总结
- normal-resolve: 普通解析阶段,处理 preferRealative、preferAbsolute
- internal: 内部解析阶段,处理 importsFields 选项声明的能力;
- raw-module 阶段,处理 resolve.modules、exportsFields 选项声明的能力;