我在AWS EC2上的Linux上运行了一个Node.JS应用程序,该应用程序使用fs模块读取HTML模板文件。以下是该应用程序的当前结构:
/server.js
/templates/my-template.html
/services/template-reading-service.js
HTML模板将始终位于该位置,但是,模板读取服务可能会移动到不同的位置(更深的子目录等)。在模板读取服务中,我使用fs.readFileSync()来加载文件,如下所示:
var templateContent = fs.readFileSync('./templates/my-template.html', 'utf8');
这会引发以下错误:
Error: ENOENT, no such file or directory './templates/my-template.html'
我假设这是因为路径'./'正在解析到'/ services /'目录而不是应用程序根目录。我也尝试将路径更改为'../templates/my-template.html'并且有效,但它看起来很脆弱,因为我认为这只是相对于“向上一个目录”进行解析。如果我将模板读取服务移动到更深的子目录,那么该路径将会中断。
那么,相对于应用程序根目录引用文件的正确方法是什么?
答案 0 :(得分:28)
要获取运行节点进程的目录的绝对文件系统路径,可以使用process.cwd()
。所以假设你正在运行 /server.js 作为一个实现 /services/template-reading-service.js 作为模块的过程,那么您可以从 /service/template-reading-service.js 执行以下操作:
var appRoot = process.cwd(),
templateContent = fs.readFileSync(appRoot + '/templates/my-template.html', 'utf8');
如果这不起作用,那么您可能正在运行 /service/template-reading-service.js 作为一个单独的进程,在这种情况下,您将需要进行任何启动该进程通过它您希望将其视为主应用程序根目录的路径。例如,如果/server.js将 /service/template-reading-service.js 作为单独的进程启动,那么 /server.js 应该将其自己的process.cwd传递给它()。
答案 1 :(得分:24)
尝试
var templateContent = fs.readFileSync(path.join(__dirname, '../templates') + '/my-template.html', 'utf8');
答案 2 :(得分:16)
接受的答案是错误的。硬编码path.join(__dirname, '../templates')
将完全执行不需要的操作,如果service-XXX.js
文件移动到子位置(如给定示例services/template
),则process.cwd()
文件会破坏主应用程序。
使用/Myuser/myproject/server.js
将返回启动正在运行的进程的文件的根路径(因此,例如/Myuser/myproject/
返回__dirname
)。
这是问题Determine project root from a running node.js application的副本。
关于这个问题,{{1}}答案得到了应有的正确鞭打。 提防绿色标记,路人。
答案 3 :(得分:1)
对于ES模块,__dirname
不可用,因此请阅读this answer并使用:
import { resolve, dirname, join } from 'path'
import { fileURLToPath } from 'url'
import fs from 'fs'
const relativePath = a => join(dirname(fileURLToPath(import.meta.url)), a)
const pathToFileInSameDirectory = relativePath('./file.xyz')
const pathToFileInParentDirectory = relativePath('../file.xyz')
const content1 = fs.readFileSync(pathToFileInSameDirectory, 'utf8')
const content2 = fs.readFileSync(pathToFileInParentDirectory, 'utf8')