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