关键问题:ES 模块与传统模块的路径差异
1. 传统 CommonJS 模块的做法
在传统的 Node.js 模块(使用 require
)中,我们会这样获取当前文件所在目录的路径:
javascript
复制
const path = require('path'); const dirPath = path.join(__dirname, 'src'); // __dirname 是当前文件所在目录
__dirname
直接给出了当前文件的目录路径,比如 /Users/me/project/src
。
2. ES 模块的新挑战
但在 ES 模块(使用 import/export
)中:
-
没有
__dirname
这个变量 -
取而代之的是
import.meta.url
,但它返回的是 URL 格式的字符串,比如file:///Users/me/project/src/config.js
为什么需要转换?
问题场景
在 Vite 配置中,我们需要设置路径别名:
javascript
复制
alias: { '@': '/path/to/src' // 这里需要真实的文件系统路径 }
但是:
-
我们只有
import.meta.url
(URL 格式) -
我们需要把它转换成普通路径格式
解决方案步骤
-
new URL('./src', import.meta.url)
-
基于当前文件的 URL (
import.meta.url
) -
解析相对路径
./src
-
得到完整的文件 URL,如
file:///Users/me/project/src
-
-
fileURLToPath()
-
把
file:///Users/me/project/src
-
转换成普通路径
/Users/me/project/src
-
为什么不能直接用字符串处理?
-
跨平台问题
Windows 和 Unix 的路径格式不同(C:\
vs/
) -
编码问题
URL 中的特殊字符需要正确处理 -
可靠性
使用标准 API 比手动字符串操作更可靠
实际代码解析
javascript
复制
import { fileURLToPath, URL } from 'node:url' // 转换过程: // 1. import.meta.url → 当前文件的URL (file:///...) // 2. new URL('./src', import.meta.url) → src目录的URL // 3. fileURLToPath() → 转换成普通路径 resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } }
总结
步骤 | 工具 | 输入 | 输出 |
---|---|---|---|
1. 获取当前文件URL | import.meta.url | - | file:///.../config.js |
2. 解析相对路径 | new URL() | ./src + 基础URL | file:///.../src |
3. 转换URL为路径 | fileURLToPath() | file:///.../src | /.../src |
这样做的目的是在 ES 模块环境下,安全可靠地获取文件系统路径,特别是在配置路径别名这种需要精确路径的场景下。