我想要求我的文件总是通过我的项目的根,而不是相对于当前模块。

例如,如果查看https://github.com/visionmedia/express/blob/2820f2227de0229c5d7f28009aa432f9f3a7b5f9/examples/downloads/app.js第6行,您将看到

express = require('../../')

在我看来,这真的很糟糕。假设我想让我所有的例子都只靠近根结点一层。这是不可能的,因为我必须更新超过30个例子,并且在每个例子中更新很多次。:

express = require('../')

我的解决方案是有一个基于根的特殊情况:如果字符串以$开头,那么它相对于项目的根文件夹。

任何帮助都是感激的,谢谢

更新2

现在我使用require.js,它允许你以一种方式编写,在客户端和服务器上都可以工作。Require.js还允许你创建自定义路径。

更新3

现在我转移到webpack + gulp,我使用enhanced-require来处理服务器端模块。看这里的基本原理:http://hackhat.com/p/110/module-loader-webpack-vs-requirejs-vs-browserify/


当前回答

我编写了这个小包,它允许您通过项目根的相对路径来要求包,而不引入任何全局变量或覆盖节点默认值

https://github.com/Gaafar/pkg-require

它是这样工作的

// create an instance that will find the nearest parent dir containing package.json from your __dirname
const pkgRequire = require('pkg-require')(__dirname);

// require a file relative to the your package.json directory 
const foo = pkgRequire('foo/foo')

// get the absolute path for a file
const absolutePathToFoo = pkgRequire.resolve('foo/foo')

// get the absolute path to your root directory
const packageRootPath = pkgRequire.root()

其他回答

还有:

var myModule = require.main.require('./path/to/module');

它需要的文件,就像它被要求从主js文件,所以它工作得很好,只要你的主js文件是在你的项目的根…这一点我很感激。

我喜欢为共享代码创建一个新的node_modules文件夹,然后让node和require做它最擅长的事情。

例如:

- node_modules // => these are loaded from your package.json
- app
  - node_modules // => add node-style modules
    - helper.js
  - models
    - user
    - car
- package.json
- .gitignore

例如,如果你在car/index.js中,你可以require('helper'), node会找到它!

node_modules如何工作

Node有一个在竞争对手中独一无二的解决模块的聪明算法 平台。

如果你从/beep/boop/bar.js中require('./foo.js'), node会在/beep/boop/foo.js中寻找。/foo.js。以./或..开头的路径/对于调用require()的文件总是本地的。

然而,如果你需要一个非相对名称,例如require('xyz')来自/beep/boop/foo.js, node会按顺序搜索这些路径,在第一次匹配时停止,如果没有找到就会引发错误:

/beep/boop/node_modules/xyz
/beep/node_modules/xyz
/node_modules/xyz

对于每个存在的xyz目录,node将首先查找一个xyz/包。查看是否存在一个“main”字段。“main”字段定义了如果你需要()目录路径,哪个文件应该负责。

例如,如果/beep/node_modules/xyz是第一个匹配,那么/beep/node_modules/xyz/package。json有:

{
  "name": "xyz",
  "version": "1.2.3",
  "main": "lib/abc.js"
}

然后从/beep/node_modules/xyz/lib/abc.js中导出的文件将被返回 要求(“xyz”)。

如果没有包裹。Json或没有“main”字段,index.js是假设的:

/beep/node_modules/xyz/index.js

手动符号链接(和Windows连接)

examples目录中不能包含一个node_modules,该node_modules带有指向项目根目录的符号链接吗?/因此允许示例使用require('project'),尽管这并没有删除映射,但它允许源代码使用require('project')而不是require('../../')。

我已经对此进行了测试,它确实适用于v0.6.18。

项目目录清单:

$ ls -lR project
project:
drwxr-xr-x 3 user user 4096 2012-06-02 03:51 examples
-rw-r--r-- 1 user user   49 2012-06-02 03:51 index.js

project/examples:
drwxr-xr-x 2 user user 4096 2012-06-02 03:50 node_modules
-rw-r--r-- 1 user user   20 2012-06-02 03:51 test.js

project/examples/node_modules:
lrwxrwxrwx 1 user user 6 2012-06-02 03:50 project -> ../../

index.js的内容将一个值赋给exports对象的一个属性,并调用console.log,并用一条消息声明它是必需的。test.js的内容是require('project')。

自动化的符号链接

手动创建符号链接的问题是,每次你npm ci时,你都会丢失符号链接。如果您使符号链接进程成为依赖项,那么就没有问题。

模块basetag是一个postinstall脚本,它在每次运行npm install或npm ci时创建一个名为$的符号链接(或Windows连接):

npm install --save basetag
node_modules/$ -> ..

这样,您就不需要对代码或require系统进行任何特殊修改。$成为您可以从中进行请求的根。

var foo = require('$/lib/foo.js');

如果你不喜欢使用$,而更喜欢#或其他(除了@,这是npm的一个特殊字符),你可以fork它并进行更改。

注意:虽然Windows符号链接(到文件)需要管理员权限,但Windows连接(到目录)不需要管理员权限。这是一种安全、可靠、跨平台的解决方案。

我喜欢做的是利用node从node_module目录加载的方式。

如果有人试图加载“thing”模块,他会做如下的事情

require('thing');

Node将在'node_module'目录中查找'thing'目录。

由于node_module通常位于项目的根,所以我们可以利用这种一致性。(如果node_module不在根节点上,那么您就会遇到其他令人头痛的问题。)

如果我们进入目录,然后从目录中返回,我们可以获得到节点项目根的一致路径。

require('thing/../../');

如果我们想访问/happy目录,我们会这样做。

require('thing/../../happy');

虽然这有点粗糙,但是我觉得如果node_modules加载的功能发生了变化,将会有更大的问题需要处理。这种行为应该保持一致。

为了使事情更清楚,我这样做,因为模块的名称并不重要。

require('root/../../happy');

我最近在angular2中使用了它。我想从根目录加载服务。

import {MyService} from 'root/../../app/services/http/my.service';

另一个答案是:

想象一下这个文件夹结构:

node_modules lodash src 子目录 foo.js bar.js main.js 测试 . js

然后在test.js中,你需要这样的文件:

const foo = require("../src/subdir/foo");
const bar = require("../src/subdir/bar");
const main = require("../src/main");
const _ = require("lodash");

在main.js中:

const foo = require("./subdir/foo");
const bar = require("./subdir/bar");
const _ = require("lodash");

现在你可以使用。babelrc文件中的babel和babel插件模块解析器来配置两个根文件夹:

{
    "plugins": [
        ["module-resolver", {
            "root": ["./src", "./src/subdir"]
        }]
    ]
}

现在你可以在测试和src中以同样的方式要求文件:

const foo = require("foo");
const bar = require("bar");
const main = require("main");
const _ = require("lodash");

如果你想使用es6模块语法:

{
    "plugins": [
        ["module-resolver", {
            "root": ["./src", "./src/subdir"]
        }],
        "transform-es2015-modules-commonjs"
    ]
}

然后像这样在测试和SRC中导入文件:

import foo from "foo"
import bar from "bar"
import _ from "lodash"