除了process.cwd()之外,是否有其他方法来获取当前项目根目录的路径名。Node是否实现了ruby的属性Rails.root之类的东西。我要找的是稳定可靠的东西。
当前回答
老问题,我知道,但是没有问题提到使用progress.argv。argv数组包含完整的路径名和文件名(带或不带.js扩展名),用作节点执行的参数。因为它也可以包含标志,所以必须对其进行过滤。
这不是一个你可以直接使用的例子(因为使用我自己的框架),但我认为它给了你一些想法如何做到这一点。我还使用缓存方法来避免调用这个函数对系统造成太大的压力,特别是在没有指定扩展名(并且需要文件存在检查)的情况下,例如:
node myfile
or
node myfile.js
这就是我缓存它的原因,参见下面的代码。
function getRootFilePath()
{
if( !isDefined( oData.SU_ROOT_FILE_PATH ) )
{
var sExt = false;
each( process.argv, function( i, v )
{
// Skip invalid and provided command line options
if( !!v && isValidString( v ) && v[0] !== '-' )
{
sExt = getFileExt( v );
if( ( sExt === 'js' ) || ( sExt === '' && fileExists( v+'.js' )) )
{
var a = uniformPath( v ).split("/");
// Chop off last string, filename
a[a.length-1]='';
// Cache it so we don't have to do it again.
oData.SU_ROOT_FILE_PATH=a.join("/");
// Found, skip loop
return true;
}
}
}, true ); // <-- true is: each in reverse order
}
return oData.SU_ROOT_FILE_PATH || '';
}
};
其他回答
在app.js中创建一个函数
/*函数获取应用程序根文件夹*/
var appRootFolder = function(dir,level){
var arr = dir.split('\\');
arr.splice(arr.length - level,level);
var rootFolder = arr.join('\\');
return rootFolder;
}
// view engine setup
app.set('views', path.join(appRootFolder(__dirname,1),'views'));
process.env上有一个INIT_CWD属性。这就是我目前在我的项目中所做的工作。
const {INIT_CWD} = process.env; // process.env.INIT_CWD
const paths = require(`${INIT_CWD}/config/paths`);
祝你好运…
path.dirname(process.mainModule.filename);
序言
这是一个非常古老的问题,但它似乎在2020年和2012年一样触动了人们的神经。 我检查了所有其他的答案,没有找到下面提到的技巧(它有自己的局限性,但其他的也不是适用于所有的情况):
Git +子进程
如果你使用Git作为你的版本控制系统,确定项目根的问题可以简化为(我认为项目的正确根-毕竟,你会希望你的VCS有尽可能充分的可见范围):
检索存储库根路径
由于您必须运行CLI命令来执行此操作,因此我们需要生成一个子进程。此外,由于项目根不太可能在运行时中期更改,我们可以在启动时使用child_process模块的同步版本。
我发现spawnSync()最适合这项工作。至于实际要运行的命令,检索根目录的绝对路径所需要的就是git工作树(带有——porcelain选项,以便于解析)。
在答案后面的示例中,我选择返回一个路径数组,因为可能存在多个工作树(尽管它们可能具有公共路径)。注意,当我们使用CLI命令时,shell选项应该设置为true(安全性不应该成为问题,因为没有不可信的输入)。
方法比较和后备
了解到VCS可能无法访问的情况,在分析了文档和其他答案后,我包含了一些备用方案。建议解决方案可归纳为(不含第三方模块和包):
Solution | Advantage | Main Problem |
---|---|---|
__filename |
points to module file | relative to module |
__dirname |
points to module dir | same as __filename |
node_modules tree walk |
nearly guaranteed root | complex tree walking if nested |
path.resolve(".") |
root if CWD is root | same as process.cwd() |
process.argv\[1\] |
same as __filename |
same as __filename |
process.env.INIT_CWD |
points to npm run dir |
requires npm && CLI launch |
process.env.PWD |
points to current dir | relative to (is the) launch dir |
process.cwd() |
same as env.PWD |
process.chdir(path) at runtime |
require.main.filename |
root if === module |
fails on require d modules |
从上面的对比表来看,以下方法是最普遍的:
require.main.filename作为获取根文件的简单方法。Main ===模块满足 最近提出的Node_modules树遍历使用了另一个假设:
如果模块的目录中有node_modules dir,那么它很可能是根目录
对于主应用程序,它将获得应用程序根,而对于一个模块——它的项目根。
回退1。树走
我的实现使用了一种更宽松的方法,一旦找到目标目录就停止,因为对于给定的模块,它的根是项目根。我们可以链接调用或扩展它,使搜索深度可配置:
/**
* @summary gets root by walking up node_modules
* @param {import("fs")} fs
* @param {import("path")} pt
*/
const getRootFromNodeModules = (fs, pt) =>
/**
* @param {string} [startPath]
* @returns {string[]}
*/
(startPath = __dirname) => {
//avoid loop if reached root path
if (startPath === pt.parse(startPath).root) {
return [startPath];
}
const isRoot = fs.existsSync(pt.join(startPath, "node_modules"));
if (isRoot) {
return [startPath];
}
return getRootFromNodeModules(fs, pt)(pt.dirname(startPath));
};
回退2。主模块
第二个实现很简单:
/**
* @summary gets app entry point if run directly
* @param {import("path")} pt
*/
const getAppEntryPoint = (pt) =>
/**
* @returns {string[]}
*/
() => {
const { main } = require;
const { filename } = main;
return main === module ?
[pt.parse(filename).dir] :
[];
};
实现
我建议使用树行者作为首选的备用工具,因为它更多功能:
const { spawnSync } = require("child_process");
const pt = require('path');
const fs = require("fs");
/**
* @summary returns worktree root path(s)
* @param {function : string[] } [fallback]
* @returns {string[]}
*/
const getProjectRoot = (fallback) => {
const { error, stdout } = spawnSync(
`git worktree list --porcelain`,
{
encoding: "utf8",
shell: true
}
);
if (!stdout) {
console.warn(`Could not use GIT to find root:\n\n${error}`);
return fallback ? fallback() : [];
}
return stdout
.split("\n")
.map(line => {
const [key, value] = line.split(/\s+/) || [];
return key === "worktree" ? value : "";
})
.filter(Boolean);
};
缺点
最明显的是安装和初始化Git,这可能是不可取的/不可信的(旁注:在生产服务器上安装Git并不少见,也不是不安全的)。如上所述,可以通过回退来调节。
简单:
require('path').resolve('./')
推荐文章
- 错误:无法找到模块“webpack”
- 如何在C程序中获取当前目录?
- 在node.js中使用async / await文件系统
- NodeJS -用NPM安装错误
- 如何为本地安装npm包设置自定义位置?
- 回调函数来处理管道的完成
- Express函数中的“res”和“req”参数是什么?
- node.js TypeError:路径必须是绝对路径或指定根路径到res.sendFile[解析JSON失败]
- Passport.js -错误:序列化用户到会话失败
- Node.js vs .Net性能
- 从电子应用程序中删除菜单栏
- 如何用node.js实现一个安全的REST API
- 如何处理Node.js中的循环依赖
- 在猫鼬,我如何排序的日期?(node . js)
- 如何在Node.js内进行远程REST调用?旋度吗?