Resolver 是什么?
对于:
TypeScript
import Button from "@/components/Button";
JavaScript 引擎实际上只看到了 这些:
TEXT
specifier = "@/components/Button"
接下来需要解决的问题是:
TEXT
specifier
↓
真实模块
这个过程称为 Resolution。
Node.js ESM 规范中的入口算法:
TEXT
ESM_RESOLVE(specifier, parentURL)
本质就是完成这个映射过程。
Node 默认支持哪些 specifier
Node 原生 Resolver 只支持四类:
JavaScript
import "./foo.js"
import "../foo.js"
import "/app/foo.js"
路径模块。
JavaScript
import react from "react"
包模块。
CodeBlock Loading...
Package Imports。
CodeBlock Loading...
URL 模块。
除此之外:
CodeBlock Loading...
Node 无法解析。
直接进入:
TEXT
Module Not Found
异常路径。
为什么 Alias 可以工作
假设存在:
CodeBlock Loading...
Webpack 配置:
CodeBlock Loading...
Webpack 在执行真正解析前:
TEXT
@/components/Button
先经过 Alias Resolver:
TEXT
/project/src/components/Button
随后再进入正常模块解析。
因此 Alias 并不是一种新的模块类型。
而是:
TEXT
旧 specifier
↓
新 specifier
的一次转换。
Vite Alias
Vite:
CodeBlock Loading...
执行流程与 Webpack 完全一致。
对于:
CodeBlock Loading...
Vite 首先执行:
TEXT
@ -> /project/src
得到:
TEXT
/project/src/utils/request
然后继续执行后续解析。
因此:
TEXT
Webpack Alias
Vite Alias
Rspack Alias
本质是同一个东西。
区别只是 Resolver 实现不同。
TypeScript Paths 为什么经常失效
配置:
CodeBlock Loading...
很多人会发现:
TEXT
VSCode 正常
TypeScript 正常
Node 运行失败
原因是:
TEXT
paths
不是运行时 Resolver。
TypeScript 只会在:
TEXT
类型检查
IDE 跳转
编译阶段
使用 paths。
Node 运行时根本不会读取:
CodeBlock Loading...
因此:
CodeBlock Loading...
无法让 Node 识别:
CodeBlock Loading...
必须额外配置:
TEXT
Webpack Alias
Vite Alias
Rspack Alias
Node Loader
其中之一。
Node Loader 如何实现 Alias
Node 提供:
CodeBlock Loading...
允许接管解析过程。
例如:
CodeBlock Loading...
此时:
CodeBlock Loading...
会变成:
TEXT
file:///project/src/utils.js
然后进入正常加载流程。
Browser Import Map
浏览器没有:
TEXT
node_modules
因此:
CodeBlock Loading...
无法工作。
Import Map 的作用:
CodeBlock Loading...
执行:
CodeBlock Loading...
时。
浏览器先映射:
TEXT
react
↓
/vendor/react.js
再继续加载。
Resolver 的本质
观察:
TEXT
Webpack Alias
Vite Alias
Rspack Alias
TS Paths
Node Loader
Import Map
会发现它们都在做同一件事:
TEXT
specifier
↓
mapping
↓
new specifier
↓
real URL
区别仅在于:
TEXT
映射规则存放的位置不同
模块图的起点
对于:
CodeBlock Loading...
编译器首先执行:
TEXT
specifier
↓
resolver
↓
real module
得到:
TEXT
App.tsx
然后继续递归:
TEXT
App.tsx
↓
Button.tsx
↓
request.ts
↓
...
最终构建:
TEXT
Module Graph
Tree Shaking、Code Splitting、HMR、Chunk 拆分全部建立在这个图之上。
因此 Resolver 是整个现代前端工具链真正的入口。