Linux 在 Node.JS 中引用与应用程序根相关的文件的正确方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13051961/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 17:36:08  来源:igfitidea点击:

Proper way to reference files relative to application root in Node.JS

linuxnode.js

提问by user1438940

I have a Node.JS application running on Linux at AWS EC2 that uses the fs module to read in HTML template files. Here is the current structure of the application:

我有一个 Node.JS 应用程序在 AWS EC2 的 Linux 上运行,它使用 fs 模块读取 HTML 模板文件。这是应用程序的当前结构:

/server.js
/templates/my-template.html
/services/template-reading-service.js

The HTML templates will always be in that location, however, the template-reading-service may move around to different locations (deeper subdirectories, etc.) From within the template-reading-service I use fs.readFileSync() to load the file, like so:

HTML 模板将始终位于该位置,但是,模板读取服务可能会移动到不同的位置(更深的子目录等)。在模板读取服务中,我使用 fs.readFileSync() 加载文件,像这样:

var templateContent = fs.readFileSync('./templates/my-template.html', 'utf8');

This throws the following error:

这会引发以下错误:

Error: ENOENT, no such file or directory './templates/my-template.html'

I'm assuming that is because the path './' is resolving to the '/services/' directory and not the application root. I've also tried changing the path to '../templates/my-template.html' and that worked, but it seems brittle because I imagine that is just resolving relative to 'up one directory'. If I move the template-reading-service to a deeper subdirectory, that path will break.

我假设这是因为路径“./”正在解析到“/services/”目录而不是应用程序根目录。我也尝试将路径更改为 '../templates/my-template.html' 并且有效,但它似乎很脆弱,因为我认为这只是相对于“向上一个目录”的解析。如果我将模板读取服务移动到更深的子目录,该路径将中断。

So, what is the proper way to reference files relative to the root of the application?

那么,相对于应用程序的根目录引用文件的正确方法是什么?

采纳答案by jwchang

Try

尝试

var templateContent = fs.readFileSync(path.join(__dirname, '../templates') + '/my-template.html', 'utf8');

回答by gregtczap

To get an absolute filesystem path to the directory where the node process is running, you can use process.cwd(). So assumingyou are running /server.jsas a process which implements /services/template-reading-service.jsas a module, then you can do the following from /service/template-reading-service.js:

要获取运行节点进程的目录的绝对文件系统路径,您可以使用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');

If that doesn't work then you may be running /service/template-reading-service.jsas a separate process, in which case you will need to have whatever launches that process pass it the path you want to treat as the primaryapplication root. For example, if /server.js launches /service/template-reading-service.jsas a separate process then /server.jsshould pass it its own process.cwd().

如果这不起作用,那么您可能将/service/template-reading-service.js作为一个单独的进程运行,在这种情况下,您需要让该进程将任何启动传递给您想要作为主要应用程序的路径根。例如,如果 /server.js 将/service/template-reading-service.js作为一个单独的进程启动,那么/server.js应该将它自己的 process.cwd() 传递给它。

回答by deimosaffair

Accepted answer is wrong. Hardcoding path.join(__dirname, '../templates')will do exactly what is not wanted, making the service-XXX.jsfile break the main app if it moves to a sub location (as the given example services/template).

接受的答案是错误的。硬编码path.join(__dirname, '../templates')会做不想要的事情,service-XXX.js如果文件移动到子位置(如给定的例子services/template),就会破坏主应用程序。

Using process.cwd()will return the root path for the file that initiated the running process (so, as example a /Myuser/myproject/server.jsreturns /Myuser/myproject/).

Usingprocess.cwd()将返回启动运行进程的文件的根路径(例如 a/Myuser/myproject/server.js返回/Myuser/myproject/)。

This is a duplicate of question Determine project root from a running node.js application.

这是问题的副本从正在运行的 node.js 应用程序中确定项目根

On that question, the __dirnameanswer got the proper whipping it deserves. Beware of the green mark, passers-by.

在这个问题上,__dirname答案得到了应有的惩罚。小心绿标,路人。

回答by David

For ES modules, __dirnameis not available, so read this answerand use:

对于 ES 模块,__dirname不可用,因此请阅读此答案并使用:

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')