为什么Node.js中__dirname未返回完整绝对路径?如何正确获取路径读取文件
问题原因
__dirname缺失上层路径前缀,通常是两个核心原因导致:
- TypeScript编译配置问题:如果你的
tsconfig.json中配置了rootDir指向server目录,编译后的JS文件会直接以server作为目录根节点,运行时的__dirname是基于编译后JS文件的实际存储路径,不会保留原始TS文件的上层路径前缀。 - 打包工具篡改:如果你使用了Webpack、Rollup、Esbuild等工具打包Node服务代码,这类工具默认会将Node原生的
__dirname替换为相对于打包根目录的相对路径,不会输出完整的磁盘绝对路径。
额外说明:你直接使用/server/templates/docx/word2016_tpl.docx读取失败的原因是,路径开头的/代表操作系统的磁盘根目录,不是你的项目根目录,系统会直接在磁盘根路径下查找server目录,自然找不到对应文件。
解决方案
方案1:修复__dirname的原生行为
根据你的开发环境调整配置,让__dirname返回完整的绝对路径:
- 如果使用Webpack打包:在webpack配置中添加如下配置,关闭对Node变量的篡改:
module.exports = { node: { __dirname: false, __filename: false } }
- 如果使用ts-node直接运行TS文件:检查
tsconfig.json中是否开启了路径篡改相关配置,关闭rootDirs等会修改模块路径映射的配置项即可。 - 如果使用其他打包工具:搜索对应工具的配置项,关闭对
__dirname的自动替换即可。
方案2:正确拼接目标文件路径
__dirname修复完成后,使用Node内置的path模块拼接路径,不要手动拼接斜杠,避免跨平台兼容问题:
import path from 'path' import fs from 'fs' // __dirname为 /Users/me/Documents/myapp/services/myapp/server/methods/documents // 向上跳两级到server目录,再进入templates目录 const templatePath = path.join(__dirname, '../../templates/docx/word2016_tpl.docx') const buff = fs.readFileSync(templatePath)
方案3:基于项目根目录定位(更稳定)
如果你不想依赖目录的相对层级,可以通过定位项目根目录(即存放package.json的目录)的方式生成绝对路径,不会受文件移动影响:
import path from 'path' import fs from 'fs' // 向上查找最近的package.json所在目录作为项目根 function getProjectRoot(): string { let currentDir = __dirname while (!fs.existsSync(path.join(currentDir, 'package.json'))) { const parentDir = path.dirname(currentDir) if (parentDir === currentDir) throw new Error('未找到项目根目录,请确认项目存在package.json文件') currentDir = parentDir } return currentDir } const projectRoot = getProjectRoot() const templatePath = path.join(projectRoot, 'server/templates/docx/word2016_tpl.docx') const buff = fs.readFileSync(templatePath)
内容的提问来源于stack exchange,提问作者Jake Wright
相关产品推荐
相关产品推荐

