简体   繁体   English

从正在运行的 node.js 应用程序确定项目根目录

[英]Determine project root from a running node.js application

Is there a different way, other than process.cwd() , to get the pathname of the current project's root-directory.除了process.cwd()之外,还有其他方法可以获取当前项目的根目录的路径名。 Does Node implement something like ruby's property, Rails.root ,. Node 是否实现了 ruby 的属性Rails.root之类的东西。 I'm looking for something that is constant, and reliable.我正在寻找一些不变的、可靠的东西。

There are many ways to approach this, each with their own pros and cons:有很多方法可以解决这个问题,每种方法都有自己的优缺点:

require.main.filename

From http://nodejs.org/api/modules.html :http://nodejs.org/api/modules.html

When a file is run directly from Node, require.main is set to its module .当一个文件直接从 Node 运行时, require.main被设置为它的module That means that you can determine whether a file has been run directly by testing require.main === module这意味着你可以通过测试require.main === module来确定文件是否已经直接运行

Because module provides a filename property (normally equivalent to __filename ), the entry point of the current application can be obtained by checking require.main.filename .因为module提供了一个filename属性(通常相当于__filename ),所以可以通过检查require.main.filename来获得当前应用程序的入口点。

So if you want the base directory for your app, you can do:因此,如果您想要应用程序的基本目录,您可以执行以下操作:

const { dirname } = require('path');
const appDir = dirname(require.main.filename);

Pros & Cons优点缺点

This will work great most of the time, but if you're running your app with a launcher like pm2 or running mocha tests, this method will fail.这在大多数情况下都非常有效,但如果您使用pm2之类的启动器运行您的应用程序或运行mocha测试,则此方法将失败。

module.paths

Node publishes all the module search paths to module.paths . Node 将所有模块搜索路径发布到module.paths We can traverse these and pick the first one that resolves.我们可以遍历这些并选择第一个解决的问题。

async function getAppPath() {
  const { dirname } = require('path');
  const { constants, promises: { access } } = require('fs');
  
  for (let path of module.paths) {
    try {
      await access(path, constants.F_OK);
      return dirname(path);
    } catch (e) {
      // Just move on to next path
    }
  }
}

Pros & Cons优点缺点

This will sometimes work, but is not reliable when used in a package because it may return the directory that the package is installed in rather than the directory that the application is installed in.这有时会起作用,但在包中使用时并不可靠,因为它可能会返回安装包的目录,而不是安装应用程序的目录。

Using a global variable使用全局变量

Node has a global namespace object called global — anything that you attach to this object will be available everywhere in your app. Node 有一个名为global的全局命名空间对象——你附加到这个对象的任何东西都可以在你的应用程序的任何地方使用。 So, in your index.js (or app.js or whatever your main app file is named), you can just define a global variable:因此,在您的index.js (或app.js或任何您的主应用程序文件的名称)中,您可以定义一个全局变量:

// index.js
var path = require('path');
global.appRoot = path.resolve(__dirname);

// lib/moduleA/component1.js
require(appRoot + '/lib/moduleB/component2.js');

Pros & Cons优点缺点

Works consistently, but you have to rely on a global variable, which means that you can't easily reuse components/etc.始终如一地工作,但是您必须依赖全局变量,这意味着您不能轻松地重用组件/等。

process.cwd()

This returns the current working directory.这将返回当前工作目录。 Not reliable at all, as it's entirely dependent on what directory the process was launched from :根本不可靠,因为它完全取决于进程哪个目录启动:

$ cd /home/demo/
$ mkdir subdir
$ echo "console.log(process.cwd());" > subdir/demo.js
$ node subdir/demo.js
/home/demo
$ cd subdir
$ node demo.js
/home/demo/subdir

app-root-path应用程序根路径

To address this issue, I've created a node module called app-root-path .为了解决这个问题,我创建了一个名为app-root-path的节点模块。 Usage is simple:用法很简单:

const appRoot = require('app-root-path');
const myModule = require(`${ appRoot }/lib/my-module.js`);

The app-root-path module uses several techniques to determine the root path of the app, taking into account globally installed modules (for example, if your app is running in /var/www/ but the module is installed in ~/.nvm/v0.xx/lib/node/ ). app-root-path模块使用多种技术来确定应用程序的根路径,同时考虑到全局安装的模块(例如,如果您的应用程序在/var/www/中运行但模块安装在~/.nvm/v0.xx/lib/node/ )。 It won't work 100% of the time, but it's going to work in most common scenarios.它不会在 100% 的时间里工作,但它会在最常见的情况下工作。

Pros & Cons优点缺点

Works without configuration in most circumstances.在大多数情况下无需配置即可工作。 Also provides some nice additional convenience methods (see project page).还提供了一些不错的附加便利方法(参见项目页面)。 The biggest con is that it won't work if:最大的缺点是,如果:

  • You're using a launcher, like pm2您正在使用启动器,例如 pm2
  • AND , the module isn't installed inside your app's node_modules directory (for example, if you installed it globally)并且,该模块未安装在您的应用程序的node_modules目录中(例如,如果您将其安装在全局范围内)

You can get around this by either setting a APP_ROOT_PATH environmental variable, or by calling .setPath() on the module, but in that case, you're probably better off using the global method.您可以通过设置APP_ROOT_PATH环境变量或在模块上调用.setPath()来解决此问题,但在这种情况下,您最好使用global方法。

NODE_PATH environmental variable NODE_PATH 环境变量

If you're looking for a way to determine the root path of the current app, one of the above solutions is likely to work best for you.如果您正在寻找一种方法来确定当前应用程序的根路径,那么上述解决方案之一可能最适合您。 If, on the other hand, you're trying to solve the problem of loading app modules reliably, I highly recommend looking into the NODE_PATH environmental variable.另一方面,如果您试图解决可靠地加载应用程序模块的问题,我强烈建议您查看NODE_PATH环境变量。

Node's Modules system looks for modules in a variety of locations. Node 的模块系统在不同的位置寻找模块。 One of these locations is wherever process.env.NODE_PATH points . 这些位置之一是process.env.NODE_PATH指向的任何位置 If you set this environmental variable, then you can require modules with the standard module loader without any other changes.如果您设置了这个环境变量,那么您可以使用标准模块加载器来require模块,而无需进行任何其他更改。

For example, if you set NODE_PATH to /var/www/lib , the the following would work just fine:例如,如果您将NODE_PATH设置为/var/www/lib ,则以下内容可以正常工作:

require('module2/component.js');
// ^ looks for /var/www/lib/module2/component.js

A great way to do this is using npm :一个很好的方法是使用npm

{
  "scripts": {
    "start": "NODE_PATH=. node app.js"
  }
}

Now you can start your app with npm start and you're golden.现在您可以使用npm start启动您的应用程序,您就可以了。 I combine this with my enforce-node-path module, which prevents accidentally loading the app without NODE_PATH set.我将它与我的enforce-node-path模块结合起来,它可以防止在未设置NODE_PATH的情况下意外加载应用程序。 For even more control over enforcing environmental variables, see checkenv .有关强制执行环境变量的更多控制,请参阅checkenv

One gotcha: NODE_PATH must be set outside of the node app.一个问题:必须在节点应用程序之外设置NODE_PATH You cannot do something like process.env.NODE_PATH = path.resolve(__dirname) because the module loader caches the list of directories it will search before your app runs.您不能执行类似process.env.NODE_PATH = path.resolve(__dirname)的操作,因为模块加载器会在您的应用程序运行之前缓存它将搜索的目录列表。

[added 4/6/16] Another really promising module that attempts to solve this problem is wavy . [2016 年 4 月 6 日添加]尝试解决此问题的另一个非常有前途的模块是wavy

__dirname isn't a global; __dirname不是全局的; it's local to the current module so each file has its own local, different value.它是当前模块的本地文件,因此每个文件都有自己的本地不同值。

If you want the root directory of the running process, you probably do want to use process.cwd() .如果你想要运行进程的根目录,你可能确实想要使用process.cwd()

If you want predictability and reliability, then you probably need to make it a requirement of your application that a certain environment variable is set.如果您想要可预测性和可靠性,那么您可能需要将设置某个环境变量作为您的应用程序的要求。 Your app looks for MY_APP_HOME (Or whatever) and if it's there, and the application exists in that directory then all is well.您的应用程序查找MY_APP_HOME (或其他),如果它在那里,并且应用程序存在于该目录中,那么一切都很好。 If it is undefined or the directory doesn't contain your application then it should exit with an error prompting the user to create the variable.如果它未定义或目录不包含您的应用程序,那么它应该退出并提示用户创建变量的错误。 It could be set as a part of an install process.它可以设置为安装过程的一部分。

You can read environment variables in node with something like process.env.MY_ENV_VARIABLE .您可以使用类似process.env.MY_ENV_VARIABLE的方式读取节点中的环境变量。

1- create a file in the project root call it settings.js 1-在项目根目录中创建一个文件,命名为settings.js

2- inside this file add this code 2-在这个文件里面添加这个代码

module.exports = {
    POST_MAX_SIZE : 40 , //MB
    UPLOAD_MAX_FILE_SIZE: 40, //MB
    PROJECT_DIR : __dirname
};

3- inside node_modules create a new module name it "settings" and inside the module index.js write this code: 3- 在 node_modules 里面创建一个新的模块,命名为“settings”,在模块 index.js 里面写下这段代码:

module.exports = require("../../settings");

4- and any time you want your project directory just use 4-任何时候你想要你的项目目录就可以使用

var settings = require("settings");
settings.PROJECT_DIR; 

in this way you will have all project directories relative to this file ;)这样,您将拥有与该文件相关的所有项目目录;)

the easiest way to get the global root ( assuming you use NPM to run your node.js app 'npm start', etc )获取全局根的最简单方法(假设您使用 NPM 运行您的 node.js 应用程序“npm start”等

var appRoot = process.env.PWD;

If you want to cross-verify the above如果您想交叉验证上述内容

Say you want to cross-check process.env.PWD with the settings of you node.js application.假设你想用你的 node.js 应用程序的设置来交叉检查process.env.PWD if you want some runtime tests to check the validity of process.env.PWD , you can cross-check it with this code (that I wrote which seems to work well).如果你想要一些运行时测试来检查process.env.PWD的有效性,你可以用这段代码交叉检查它(我写的似乎很好用)。 You can cross-check the name of the last folder in appRoot with the npm_package_name in your package.json file, for example:您可以使用 package.json 文件中的 npm_package_name 交叉检查 appRoot 中最后一个文件夹的名称,例如:

    var path = require('path');

    var globalRoot = __dirname; //(you may have to do some substring processing if the first script you run is not in the project root, since __dirname refers to the directory that the file is in for which __dirname is called in.)

    //compare the last directory in the globalRoot path to the name of the project in your package.json file
    var folders = globalRoot.split(path.sep);
    var packageName = folders[folders.length-1];
    var pwd = process.env.PWD;
    var npmPackageName = process.env.npm_package_name;
    if(packageName !== npmPackageName){
        throw new Error('Failed check for runtime string equality between globalRoot-bottommost directory and npm_package_name.');
    }
    if(globalRoot !== pwd){
        throw new Error('Failed check for runtime string equality between globalRoot and process.env.PWD.');
    }

you can also use this NPM module: require('app-root-path') which works very well for this purpose你也可以使用这个 NPM 模块: require('app-root-path')非常适合这个目的

简单的:

require('path').resolve('./')

As simple as adding this line to your module in the root, usually it is app.js or app.ts .就像将这一行添加到根目录中的模块一样简单,通常是app.jsapp.ts

global.__basedir = __dirname;

Then _basedir will be accessible to all your modules.然后你的所有模块都可以访问 _basedir。

Note: For typescript implementation, follow the above step and then you will be able to use the root directory path using global.__basedir注意:对于 typescript 实现,请按照上述步骤操作,然后您将能够使用global.__basedir使用根目录路径

I've found this works consistently for me, even when the application is invoked from a sub-folder, as it can be with some test frameworks, like Mocha:我发现这对我来说始终如一,即使从子文件夹调用应用程序也是如此,因为它可以与某些测试框架一起使用,例如 Mocha:

process.mainModule.paths[0].split('node_modules')[0].slice(0, -1);

Why it works:为什么有效:

At runtime node creates a registry of the full paths of all loaded files.在运行时节点创建所有加载文件的完整路径的注册表。 The modules are loaded first, and thus at the top of this registry.模块首先加载,因此位于此注册表的顶部。 By selecting the first element of the registry and returning the path before the 'node_modules' directory we are able to determine the root of the application.通过选择注册表的第一个元素并返回“node_modules”目录之前的路径,我们能够确定应用程序的根目录。

It's just one line of code, but for simplicity's sake (my sake), I black boxed it into an NPM module:这只是一行代码,但为了简单起见(我的缘故),我将它黑盒化到一个 NPM 模块中:

https://www.npmjs.com/package/node-root.pddivine https://www.npmjs.com/package/node-root.pddivine

Enjoy!享受!

EDIT:编辑:

process.mainModule is deprecated as of v14.0.0 process.mainModule自 v14.0.0 起 已弃用

Use require.main instead:使用require.main代替:

require.main.paths[0].split('node_modules')[0].slice(0, -1);

All these "root dirs" mostly need to resolve some virtual path to a real pile path, so may be you should look at path.resolve ?所有这些“根目录”大多需要将一些虚拟路径解析为真正的堆路径,所以你应该看看path.resolve吗?

var path= require('path');
var filePath = path.resolve('our/virtual/path.ext');

也许您可以尝试从__filename向上遍历,直到找到package.json ,并确定这是您当前文件所属的主目录。

Actually, i find the perhaps trivial solution also to most robust: you simply place the following file at the root directory of your project: root-path.js which has the following code:实际上,我发现最强大的解决方案可能也是微不足道的:您只需将以下文件放在项目的根目录中:root-path.js,其中包含以下代码:

import * as path from 'path'
const projectRootPath = path.resolve(__dirname)
export const rootPath = projectRootPath

Preamble前言

This is a very old question, but it seems to hit the nerve in 2020 as much as back in 2012. I've checked all the other answers and could not find the following technique mentioned (it has its own limitations, but the others are not applicable to every situation either):这是一个非常古老的问题,但它似乎在 2020 年和 2012 年一样触动了神经。我检查了所有其他答案,但找不到提到的以下技术(它有其自身的局限性,但其他的是也不适用于所有情况):

Git + child process Git + 子进程

If you are using Git as your version control system , the problem of determining the project root can be reduced to (which I would consider the proper root of the project - after all, you would want your VCS to have the fullest visibility scope possible):如果您使用 Git 作为您的版本控制系统,那么确定项目根目录的问题可以简化为(我会考虑项目的正确根目录 - 毕竟,您希望您的 VCS 具有尽可能完整的可见性范围) :

retrieve repository root path检索存储库根路径

Since you have to run a CLI command to do that, we need to spawn a child process.由于您必须运行 CLI 命令来执行此操作,因此我们需要生成一个子进程。 Additionally, as project root is highly unlikely to change mid-runtime, we can use the synchronous version of the child_process module at startup.此外,由于项目根极不可能在运行时更改,我们可以在启动时使用child_process模块的同步版本。

I found spawnSync() to be the most suitable for the job.我发现spawnSync()最适合这项工作。 As for the actual command to run, git worktree (with a --porcelain option for ease of parsing) is all that is needed to retrieve the absolute path of the root.至于要运行的实际命令,只需要git worktree (带有--porcelain选项以便于解析)即可检索根目录的绝对路径。

In the sample at the end of the answer, I opted to return an array of paths because there might be multiple worktrees (although they are likely to have common paths) just to be sure.在答案末尾的示例中,我选择返回一个路径数组,因为可能有多个工作树(尽管它们可能有公共路径)只是为了确定。 Note that as we utilize a CLI command, shell option should be set to true (security shouldn't be an issue as there is no untrusted input).请注意,当我们使用 CLI 命令时, shell选项应设置为true (安全不应该成为问题,因为没有不受信任的输入)。

Approach comparison and fallbacks方法比较和后备

Understanding that a situation where VCS can be inaccessible is possible, I've included a couple of fallbacks after analyzing docs and other answers.了解 VCS 可能无法访问的情况是可能的,在分析文档和其他答案后,我包含了一些后备方案。 The proposed solutions boil down to (excluding third-party modules & packages):提议的解决方案归结为(不包括第三方模块和包):

Solution解决方案 Advantage优势 Main Problem主要问题
__filename points to module file指向模块文件 relative to module相对于模块
__dirname points to module dir指向模块目录 same as __filename__filename相同
node_modules tree walk node_modules树遍历 nearly guaranteed root几乎保证根 complex tree walking if nested嵌套复杂的树行走
path.resolve(".") root if CWD is root如果 CWD 是 root,则为 root same as process.cwd()process.cwd()相同
process.argv\[1\] same as __filename__filename相同 same as __filename__filename相同
process.env.INIT_CWD points to npm run dir指向npm run目录 requires npm && CLI launch需要npm && CLI 启动
process.env.PWD points to current dir指向当前目录 relative to (is the) launch dir相对于(是)启动目录
process.cwd() same as env.PWDenv.PWD相同 process.chdir(path) at runtime运行时的process.chdir(path)
require.main.filename root if === module根 if === module fails on require d modulesrequire d 模块上失败

From the comparison table above, the following approaches are the most universal:从上面的比较表中,以下方法是最普遍的:

  • require.main.filename as an easy way to get the root if require.main === module is met如果满足require.main === module ,则require.main.filename作为获取根目录的简单方法
  • node_modules tree walk proposed recently uses another assumption:最近提出node_modules tree walk 使用了另一个假设:

if the directory of the module has node_modules dir inside, it is likely to be the root如果模块的目录里面有node_modules dir,很有可能是root

For the main app, it will get the app root and for a module — its project root.对于主应用程序,它将获取应用程序根目录,而对于一个模块——它的项目根目录。

Fallback 1. Tree walk后备 1. 树漫步

My implementation uses a more lax approach by stopping once a target directory is found as for a given module its root is the project root.我的实现使用了一种更宽松的方法,一旦找到目标目录就停止,因为对于给定的模块,它的根目录是项目根目录。 One can chain the calls or extend it to make the search depth configurable:可以链接调用或扩展它以使搜索深度可配置:

/**
 * @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));
    };

Fallback 2. Main module Fallback 2. 主模块

The second implementation is trivial:第二个实现是微不足道的:

/**
 * @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] :
            [];
    };

Implementation执行

I would suggest using the tree walker as the preferred fallback because it is more versatile:我建议使用 tree walker 作为首选的后备,因为它更通用:

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);
};

Disadvantages缺点

The most obvious one is having Git installed and initialized which might be undesirable/implausible (side note: having Git installed on production servers is not uncommon, nor is it unsafe ).最明显的是安装和初始化 Git,这可能是不受欢迎/难以置信的(旁注: 在生产服务器上安装Git 并不少见,也不是不安全的)。 Can be mediated by fallbacks as described above.可以通过上述回退进行调解。

A technique that I've found useful when using express is to add the following to app.js before any of your other routes are set我发现使用 express 时有用的一种技术是在设置任何其他路由之前将以下内容添加到 app.js

// set rootPath
app.use(function(req, res, next) {
  req.rootPath = __dirname;
  next();
});

app.use('/myroute', myRoute);

No need to use globals and you have the path of the root directory as a property of the request object.无需使用全局变量,您将根目录的路径作为请求对象的属性。

This works if your app.js is in the root of your project which, by default, it is.如果您的 app.js 位于项目的根目录中,则此方法有效,默认情况下,它位于项目的根目录中。

There is an INIT_CWD property on process.env . process.env上有一个INIT_CWD属性。 This is what I'm currently working with in my project.这是我目前在我的项目中使用的。

const {INIT_CWD} = process.env; // process.env.INIT_CWD 
const paths = require(`${INIT_CWD}/config/paths`);

Good Luck...祝你好运...

Add this somewhere towards the start of your main app file (eg app.js):将其添加到您的主应用程序文件(例如 app.js)的开头:

global.__basedir = __dirname;

This sets a global variable that will always be equivalent to your app's base dir.这将设置一个全局变量,该变量将始终等同于您的应用程序的基本目录。 Use it just like any other variable:像任何其他变量一样使用它:

const yourModule = require(__basedir + '/path/to/module.js');

Simple...简单的...

I know this one is already too late.我知道这个已经太晚了。 But we can fetch root URL by two methods但是我们可以通过两种方法获取根 URL

1st method第一种方法

var path = require('path');
path.dirname(require.main.filename);

2nd method第二种方法

var path = require('path');
path.dirname(process.mainModule.filename);

Reference Link:- https://gist.github.com/geekiam/e2e3e0325abd9023d3a3参考链接:- https://gist.github.com/geekiam/e2e3e0325abd9023d3a3

process.mainModule is deprecated since v 14.0.0. process.mainModule自 v 14.0.0 起已弃用 When referring to the answer, please use require.main , the rest still holds.参考答案时,请使用require.main ,其余的仍然成立。

process.mainModule.paths
  .filter(p => !p.includes('node_modules'))
  .shift()

Get all paths in main modules and filter out those with "node_modules", then get the first of remaining path list.获取主模块中的所有路径并过滤掉带有“node_modules”的路径,然后获取剩余路径列表中的第一个。 Unexpected behavior will not throw error, just an undefined .意外的行为不会抛出错误,只是一个undefined

Works well for me, even when calling ie $ mocha .对我来说效果很好,即使在调用 ie $ mocha时也是如此。

如果您想从正在运行的 node.js 应用程序中确定项目根目录,您也可以这样做。

process.mainModule.path

它对我有用

process.env.PWD

At top of main file add:在主文件顶部添加:

mainDir = __dirname;

Then use it in any file you need:然后在您需要的任何文件中使用它:

console.log('mainDir ' + mainDir);
  • mainDir is defined globally, if you need it only in current file - use __dirname instead. mainDir是全局定义的,如果您只在当前文件中需要它 - 请改用__dirname
  • main file is usually in root folder of the project and is named like main.js , index.js , gulpfile.js . main 文件通常位于项目的根文件夹中,命名为main.jsindex.jsgulpfile.js

This will step down the directory tree until it contains a node_modules directory, which usually indicates your project root:这将逐步降低目录树,直到它包含一个node_modules目录,该目录通常指示您的项目根目录:

const fs = require('fs')
const path = require('path')

function getProjectRoot(currentDir = __dirname.split(path.sep)) {
  if (!currentDir.length) {
    throw Error('Could not find project root.')
  }
  const nodeModulesPath = currentDir.concat(['node_modules']).join(path.sep)
  if (fs.existsSync(nodeModulesPath) && !currentDir.includes('node_modules')) {
    return currentDir.join(path.sep)
  }
  return this.getProjectRoot(currentDir.slice(0, -1))
}

It also makes sure that there is no node_modules in the returned path, as that means that it is contained in a nested package install.它还确保返回的路径中没有node_modules ,因为这意味着它包含在嵌套包安装中。

Create a function in app.js在 app.js 中创建一个函数

/*Function to get the app root folder*/

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

I use this.我用这个。

For my module named mymodule对于我名为mymodule的模块

var BASE_DIR = __dirname.replace(/^(.*\/mymodule)(.*)$/, '$1')

Make it sexy 💃🏻.让它变得性感💃🏻。

const users = require('../../../database/users'); // 👎 what you have
// OR
const users = require('$db/users'); // 👍 no matter how deep you are
const products = require('/database/products'); // 👍 alias or pathing from root directory


Three simple steps to solve the issue of ugly path.解决丑陋路径问题的三个简单步骤。

  1. Install the package: npm install sexy-require --save安装包: npm install sexy-require --save
  2. Include require('sexy-require') once on the top of your main application file.在主应用程序文件的顶部包含一次require('sexy-require')

     require('sexy-require'); const routers = require('/routers'); const api = require('$api'); ...
  3. Optional step.可选步骤。 Path configuration can be defined in .paths file on root directory of your project.路径配置可以在项目根目录的.paths文件中定义。

     $db = /server/database $api-v1 = /server/api/legacy $api-v2 = /server/api/v2

You can simply add the root directory path in the express app variable and get this path from the app.您可以简单地在 express app 变量中添加根目录路径,然后从应用程序中获取此路径。 For this add app.set('rootDirectory', __dirname);为此添加app.set('rootDirectory', __dirname); in your index.js or app.js file.在您的 index.js 或 app.js 文件中。 And use req.app.get('rootDirectory') for getting the root directory path in your code.并使用req.app.get('rootDirectory')获取代码中的根目录路径。

Old question, I know, however no question mention to use progress.argv .老问题,我知道,但是没有提到使用progress.argv的问题。 The argv array includes a full pathname and filename (with or without .js extension) that was used as parameter to be executed by node. argv 数组包括一个完整的路径名和文件名(带或不带 .js 扩展名),用作节点执行的参数。 Because this also can contain flags, you must filter this.因为它也可以包含标志,所以您必须过滤它。

This is not an example you can directly use (because of using my own framework) but I think it gives you some idea how to do it.这不是您可以直接使用的示例(因为使用了我自己的框架),但我认为它可以让您了解如何去做。 I also use a cache method to avoid that calling this function stress the system too much, especially when no extension is specified (and a file exist check is required), for example:我还使用缓存方法来避免调用此函数对系统造成太大压力,尤其是在未指定扩展名时(并且需要文件存在检查),例如:

node myfile

or或者

node myfile.js

That's the reason I cache it, see also code below.这就是我缓存它的原因,另请参见下面的代码。


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 || '';
    }
}; 

Finding the root path of an electron app could get tricky.找到电子应用程序的根路径可能会很棘手。 Because the root path is different for the main process and renderer under different conditions such as production, development and packaged conditions.因为在生产、开发、打包等不同条件下,主进程和渲染器的根路径是不同的。

I have written a npm package electron-root-path to capture the root path of an electron app.我编写了一个 npm 包electron-root-path来捕获电子应用程序的根路径。

$ npm install electron-root-path

or 

$ yarn add electron-root-path


// Import ES6 way
import { rootPath } from 'electron-root-path';

// Import ES2015 way
const rootPath = require('electron-root-path').rootPath;

// e.g:
// read a file in the root
const location = path.join(rootPath, 'package.json');
const pkgInfo = fs.readFileSync(location, { encoding: 'utf8' });

这将做:

path.join(...process.argv[1].split(/\/|\\/).slice(0, -1))

I've gone through all the solutions suggested here but none of them really helped, so here is a solution. 我已经仔细阅读了这里建议的所有解决方案,但没有一个真正有用,因此这里是一个解决方案。

Assume you need a config.js file present at your project's root in a file which is present at /routes/api/users/profile.js , you do not want to import it as ../../../config.js 假设您需要在项目的根目录下存在一个config.js文件,该文件位于/routes/api/users/profile.js ,而您不想将其导入为../../../config.js

  1. Create a directory structure in your project's root directory as described below: 如下所述,在项目的根目录中创建目录结构:
    • /Modules /模块
      • index.js index.js
      • package.json package.json
  2. Modules/index.js 模块/ index.js
     module.exports.config = require('../config.js') 
  3. Modules/package.js 模块/package.js
     { "name": "modules", "main": "index.js", "version": "1.0.0", "dependencies": {} } 
  4. Now run 现在运行
     npm install ./Modules 
  5. /routes/api/users/profile.js /routes/api/users/profile.js
     const { config } = require('modules') 

This way autocomplete feature of your code editor will also work. 这样,代码编辑器的自动完成功能也将起作用。 No more global variables pollution, long relative imports, no dependency on environment variables and the best part is, it will work with pm2 and nodemon. 不再有全局变量污染,相对较长的进口量,对环境变量的依赖性,最好的部分是,它将与pm2和nodemon一起使用。

path.dirname(process.mainModule.filename);

In modern versions of npm, you can add an entry to exports , to use as a shorthand.在现代版本的 npm 中,您可以在exports中添加一个条目,用作速记。 Note that if you want to be able to reference both the root itself and files within that root, you'll need both ./ and ./* respectively:请注意,如果您希望能够同时引用根本身和该根中的文件,则分别需要././*

package.json : package.json

{
  "imports": {
    "#root": "./",
    "#root/*": "./*",
    ...
  },
  ...
}

./index.js : ./index.js

import {namedExport} from '#root/file.js'

./file.js : ./file.js

export const namedExport = {
  hi: "world",
};

Then:然后:

$ node --experimental-specifier-resolution=node index.js

You could extend this further with a constants.js file, where you may use one of the methods in the above answers, or input an absolute path, should you require the path itself您可以使用constants.js文件进一步扩展它,您可以在其中使用上述答案中的一种方法,或者输入绝对路径,如果您需要路径本身

您还可以使用git rev-parse --show-toplevel假设您正在使用 git 存储库

A very simple and reliable solution would be to cd.. recursively searching for package.json , considering that this file is always on the project root directory.考虑到此文件始终位于项目根目录中,一个非常简单且可靠的解决方案是cd..递归搜索package.json

const fs = require('fs')
const path = require('path')

function getAppRootDir () {
  let currentDir = __dirname
  while(!fs.existsSync(path.join(currentDir, 'package.json'))) {
    currentDir = path.join(currentDir, '..')
  }
  return currentDir
}
const __root = `${__dirname.substring(0, __dirname.lastIndexOf('projectName'))}projectName`

` `

Try path._makeLong('some_filename_on_root.js');尝试path._makeLong('some_filename_on_root.js');

example:例子:

cons path = require('path');
console.log(path._makeLong('some_filename_on_root.js');

That will return full path from root of your node application (same position of package.json)这将从您的节点应用程序的根目录返回完整路径(与 package.json 的位置相同)

只需使用:

 path.resolve("./") ... output is your project root directory

__dirname will give you the root directory, as long as you're in a file that's in the root directory. __dirname 将为您提供根目录,只要您位于根目录中的文件中。

// ProjectDirectory.js (this file is in the project's root directory because you are putting it there).
module.exports = {

    root() {
        return __dirname;
    }
}

In some other file:在其他一些文件中:

const ProjectDirectory = require('path/to/ProjectDirectory');
console.log(`Project root directory is ${ProjectDirectory.root}`);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM