关键问题: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 模块环境下,安全可靠地获取文件系统路径,特别是在配置路径别名这种需要精确路径的场景下。