如何让 node.js 需要绝对?(而不是亲戚)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10860244/
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
How to make node.js require absolute? (instead of relative)
提问by Totty.js
I would like to require my files always by the root of my project and not relative to the current module.
我想要求我的文件总是在我的项目的根目录下,而不是相对于当前模块。
For example if you look at https://github.com/visionmedia/express/blob/2820f2227de0229c5d7f28009aa432f9f3a7b5f9/examples/downloads/app.jsline 6 you will see
例如,如果您查看https://github.com/visionmedia/express/blob/2820f2227de0229c5d7f28009aa432f9f3a7b5f9/examples/downloads/app.js第 6 行,您将看到
express = require('../../')
That's really bad IMO. Imagine I would like to put all my examples closer to the root only by one level. That would be impossible, because I would have to update more than 30 examples and many times within each example. To this:
这真的很糟糕 IMO。想象一下,我想将我所有的例子都放在更接近根的一级。那是不可能的,因为我必须在每个示例中多次更新 30 多个示例。对此:
express = require('../')
My solution would be to have a special case for root based: if a string starts with an $ then it's relative to the root folder of the project.
我的解决方案是对基于根的特殊情况:如果字符串以 $ 开头,则它相对于项目的根文件夹。
Any help is appreciated, thanks
任何帮助表示赞赏,谢谢
Update 2
更新 2
Now I'm using require.js which allows you to write in one way and works both on client and on server. Require.js also allows you to create custom paths.
现在我正在使用 require.js,它允许您以一种方式编写并在客户端和服务器上工作。Require.js 还允许您创建自定义路径。
Update 3
更新 3
Now I moved to webpack + gulp and I use enhanced-require to handle modules on the server side. See here the rationale: http://hackhat.com/p/110/module-loader-webpack-vs-requirejs-vs-browserify/
现在我转向了 webpack + gulp,并且使用了增强的-require 来处理服务器端的模块。看这里的理由:http: //hackhat.com/p/110/module-loader-webpack-vs-requirejs-vs-browserify/
采纳答案by Totty.js
Here is the actual way I'm doing for more than 6 months. I use a folder named node_modules as my root folder in the project, in this way it will always look for that folder from everywhere I call an absolute require:
这是我超过 6 个月的实际工作方式。我在项目中使用一个名为 node_modules 的文件夹作为我的根文件夹,这样它总是会从我称之为绝对需求的任何地方查找该文件夹:
- node_modules
- myProject
- index.js I can require("myProject/someFolder/hey.js") instead of require("./someFolder/hey.js")
- someFolder which contains hey.js
- myProject
- 节点模块
- 我的项目
- index.js 我可以 require("myProject/someFolder/hey.js") 而不是 require("./someFolder/hey.js")
- someFolder 包含 hey.js
- 我的项目
This is more useful when you are nested into folders and it's a lot less work to change a file location if is set in absolute way. I only use 2 the relative require in my whole app.
当您嵌套到文件夹中时,这更有用,并且如果以绝对方式设置,则更改文件位置的工作要少得多。我在我的整个应用程序中只使用 2 个相对需要。
回答by cronvel
And what about:
还有:
var myModule = require.main.require('./path/to/module');
It requires the file as if it were required from the main js file, so it works pretty well as long as your main js file is at the root of your project... and that's something I appreciate.
它需要该文件,就好像它是从主 js 文件中需要的一样,因此只要您的主 js 文件位于项目的根目录下,它就可以很好地工作……这是我欣赏的。
回答by Paolo Moretti
There's a really interesting section in the Browserify Handbook:
Browserify 手册中有一个非常有趣的部分:
avoiding ../../../../../../..
Not everything in an application properly belongs on the public npm and the overhead of setting up a private npm or git repo is still rather large in many cases. Here are some approaches for avoiding the
../../../../../../../relative paths problem.node_modules
People sometimes object to putting application-specific modules into node_modules because it is not obvious how to check in your internal modules without also checking in third-party modules from npm.
The answer is quite simple! If you have a
.gitignorefile that ignoresnode_modules:node_modulesYou can just add an exception with
!for each of your internal application modules:node_modules/* !node_modules/foo !node_modules/barPlease note that you can't unignorea subdirectory, if the parent is already ignored. So instead of ignoring
node_modules, you have to ignore every directory insidenode_moduleswith thenode_modules/*trick, and then you can add your exceptions.Now anywhere in your application you will be able to
require('foo')orrequire('bar')without having a very large and fragile relative path.If you have a lot of modules and want to keep them more separate from the third-party modules installed by npm, you can just put them all under a directory in
node_modulessuch asnode_modules/app:node_modules/app/foo node_modules/app/barNow you will be able to
require('app/foo')orrequire('app/bar')from anywhere in your application.In your
.gitignore, just add an exception fornode_modules/app:node_modules/* !node_modules/appIf your application had transforms configured in package.json, you'll need to create a separate package.json with its own transform field in your
node_modules/fooornode_modules/app/foocomponent directory because transforms don't apply across module boundaries. This will make your modules more robust against configuration changes in your application and it will be easier to independently reuse the packages outside of your application.symlink
Another handy trick if you are working on an application where you can make symlinks and don't need to support windows is to symlink a
lib/orapp/folder intonode_modules. From the project root, do:ln -s ../lib node_modules/appand now from anywhere in your project you'll be able to require files in
lib/by doingrequire('app/foo.js')to getlib/foo.js.custom paths
You might see some places talk about using the
$NODE_PATHenvironment variable oropts.pathsto add directories for node and browserify to look in to find modules.Unlike most other platforms, using a shell-style array of path directories with
$NODE_PATHis not as favorable in node compared to making effective use of thenode_modulesdirectory.This is because your application is more tightly coupled to a runtime environment configuration so there are more moving parts and your application will only work when your environment is setup correctly.
node and browserify both support but discourage the use of
$NODE_PATH.
避免 ../../../../../../..
并非应用程序中的所有内容都正确地属于公共 npm,并且在许多情况下设置私有 npm 或 git repo 的开销仍然相当大。这里有一些避免
../../../../../../../相对路径问题的方法。节点模块
人们有时反对将特定于应用程序的模块放入 node_modules 中,因为如何在不从 npm 中检入第三方模块的情况下检入内部模块并不明显。
答案很简单!如果您有一个
.gitignore忽略的文件node_modules:node_modules您可以
!为每个内部应用程序模块添加一个例外:node_modules/* !node_modules/foo !node_modules/bar请注意,如果父目录已被忽略,则不能取消忽略子目录。因此
node_modules,与其忽略,您必须使用 技巧忽略内部的每个目录,然后您可以添加例外。node_modulesnode_modules/*现在,在您的应用程序中的任何地方,您都可以拥有
require('foo')或require('bar')不拥有非常大且脆弱的相对路径。如果你有很多模块并且想让它们与 npm 安装的第三方模块更加分离,你可以将它们全部放在一个目录下,
node_modules例如node_modules/app:node_modules/app/foo node_modules/app/bar现在,您将能够
require('app/foo')或require('app/bar')在应用程序的任何地方。在您的 中
.gitignore,只需添加一个例外node_modules/app:node_modules/* !node_modules/app如果您的应用程序在 package.json 中配置了转换,则您需要在您的
node_modules/foo或node_modules/app/foo组件目录中创建一个单独的 package.json,并在其自己的转换字段中创建一个单独的 package.json,因为转换不适用于跨模块边界。这将使您的模块更健壮地应对应用程序中的配置更改,并且可以更轻松地独立重用应用程序之外的包。符号链接
如果您正在开发一个可以制作符号链接并且不需要支持 Windows 的应用程序,另一个方便的技巧是将 a
lib/或app/文件夹符号链接到node_modules. 从项目根目录,执行:ln -s ../lib node_modules/app现在从项目的任何地方,您都可以
lib/通过执行require('app/foo.js')get来要求文件lib/foo.js。自定义路径
您可能会看到一些地方谈论使用
$NODE_PATH环境变量或opts.paths为 node 和 browserify 添加目录以查找模块。与大多数其他平台不同,
$NODE_PATH与有效使用node_modules目录相比,使用 shell 样式的路径目录数组在 node 中并不有利。这是因为您的应用程序与运行时环境配置更紧密地耦合,因此有更多的活动部件,并且您的应用程序只有在您的环境设置正确时才能运行。
node 和 browserify 都支持但不鼓励使用
$NODE_PATH.
回答by Blair Anderson
I like to make a new node_modulesfolder for shared code, then let node and require do what it does best.
我喜欢node_modules为共享代码创建一个新文件夹,然后让 node 和 require 做它最擅长的事情。
for example:
例如:
- node_modules // => these are loaded from your package.json
- app
- node_modules // => add node-style modules
- helper.js
- models
- user
- car
- package.json
- .gitignore
For example, if you're in car/index.jsyou can require('helper')and node will find it!
例如,如果你在car/index.js你可以require('helper')和节点会找到它!
How node_modules Work
node_modules 如何工作
node has a clever algorithm for resolving modules that is unique among rival platforms.
node 有一个聪明的算法来解析模块,这在竞争平台中是独一无二的。
If you require('./foo.js')from /beep/boop/bar.js, node will look for ./foo.jsin /beep/boop/foo.js. Paths that start with a ./or ../are always local to the file that calls require().
如果您require('./foo.js')来自/beep/boop/bar.js,节点将./foo.js在/beep/boop/foo.js. 以./或开头的路径../对于调用require().
If however you require a non-relative name such as require('xyz')from /beep/boop/foo.js, node searches these paths in order, stopping at the first match and raising an error if nothing is found:
但是,如果您需要非相对名称,例如require('xyz')from /beep/boop/foo.js,则节点按顺序搜索这些路径,在第一个匹配项处停止并在未找到任何内容时引发错误:
/beep/boop/node_modules/xyz
/beep/node_modules/xyz
/node_modules/xyz
For each xyzdirectory that exists, node will first look for a xyz/package.jsonto see if a "main"field exists. The "main"field defines which file should take charge if you require()the directory path.
对于每个xyz存在的目录,节点会首先查找xyz/package.json一个"main"字段是否存在。"main"如果您require()是目录路径,该字段定义了哪个文件应该负责。
For example, if /beep/node_modules/xyzis the first match and /beep/node_modules/xyz/package.jsonhas:
例如,如果/beep/node_modules/xyz是第一个匹配项并且/beep/node_modules/xyz/package.json具有:
{
"name": "xyz",
"version": "1.2.3",
"main": "lib/abc.js"
}
then the exports from /beep/node_modules/xyz/lib/abc.jswill be returned by
require('xyz').
那么出口 from/beep/node_modules/xyz/lib/abc.js将被返回
require('xyz')。
If there is no package.jsonor no "main"field, index.jsis assumed:
如果没有package.json或没有"main"字段,index.js则假设:
/beep/node_modules/xyz/index.js
回答by JasonSmith
The big picture
大图
It seems "really bad" but give it time. It is, in fact, really good. The explicit require()s give a total transparency and ease of understanding that is like a breath of fresh air during a project life cycle.
看起来“真的很糟糕”,但给它时间。事实上,它真的很好。明确的require()s 提供了完全透明和易于理解的方式,就像项目生命周期中的一股新鲜空气。
Think of it this way: You are reading an example, dipping your toes into Node.js and you've decided it is "really bad IMO." You are second-guessing leaders of the Node.js community, people who have logged more hours writing and maintaining Node.js applications than anyone. What is the chance the author made such a rookie mistake? (And I agree, from my Ruby and Python background, it seems at first like a disaster.)
可以这样想:您正在阅读一个示例,将您的脚趾浸入 Node.js 并确定它是“非常糟糕的 IMO”。您是 Node.js 社区的第二位领导者,他们编写和维护 Node.js 应用程序的时间比任何人都多。作者犯这种菜鸟错误的几率有多大?(我同意,从我的 Ruby 和 Python 背景来看,乍一看似乎是一场灾难。)
There is a lot of hype and counter-hype surrounding Node.js. But when the dust settles, we will acknowledge that explicit modules and "local first" packages were a major driver of adoption.
围绕 Node.js 有很多炒作和反炒作。但是当尘埃落定时,我们将承认显式模块和“本地优先”包是采用的主要驱动力。
The common case
常见情况
Of course, node_modulesfrom the current directory, then the parent, then grandparent, great-grandparent, etc. is searched. So packages you have installedalready work this way. Usually you can require("express")from anywhere in your project and it works fine.
当然,node_modules从当前目录,然后是父,然后是祖父母,曾祖父母等等。所以你安装的包已经可以这样工作了。通常,您可以require("express")在项目的任何地方进行,而且效果很好。
If you find yourself loading common files from the root of your project (perhaps because they are common utility functions), then that is a big clue that it's time to make a package. Packages are very simple: move your files into node_modules/and put a package.jsonthere. Voila!Everything in that namespace is accessible from your entire project. Packages are the correct way to get your code into a global namespace.
如果您发现自己从项目的根目录加载公共文件(可能是因为它们是公共实用程序函数),那么这是一个重要的线索,表明是时候制作一个包了。包非常简单:将您的文件移入node_modules/并放在package.json那里。瞧!该命名空间中的所有内容都可以从整个项目中访问。包是将代码放入全局命名空间的正确方法。
Other workarounds
其他解决方法
I personally don't use these techniques, but they do answer your question, and of course you know your own situation better than I.
我个人不使用这些技术,但它们确实回答了您的问题,当然您比我更了解自己的情况。
You can set $NODE_PATHto your project root. That directory will be searched when you require().
您可以设置$NODE_PATH为您的项目根目录。当您require().
Next, you could compromise and require a common, local file from all your examples. That common file simply re-exports the true file in the grandparent directory.
接下来,您可以妥协并要求所有示例中的公共本地文件。该通用文件只是重新导出祖父目录中的真实文件。
examples/downloads/app.js(and many others like it)
示例/下载/app.js(以及许多其他人喜欢它)
var express = require('./express')
examples/downloads/express.js
示例/下载/express.js
module.exports = require('../../')
Now when you relocate those files, the worst-case is fixing the one shimmodule.
现在,当您重新定位这些文件时,最坏的情况是修复一个shim模块。
回答by warmsea
回答by Aleksei Zabrodskii
IMHO, the easiest way is to define your own function as part of GLOBALobject.
Create projRequire.jsin the root of you project with the following contents:
恕我直言,最简单的方法是将自己的函数定义为GLOBAL对象的一部分。projRequire.js使用以下内容在项目的根目录中创建:
var projectDir = __dirname;
module.exports = GLOBAL.projRequire = function(module) {
return require(projectDir + module);
}
In your main file before requireing any of project-specific modules:
在requireing 任何特定于项目的模块之前,在您的主文件中:
// init projRequire
require('./projRequire');
After that following works for me:
之后以下对我有用:
// main file
projRequire('/lib/lol');
// index.js at projectDir/lib/lol/index.js
console.log('Ok');
@Totty,我想出了另一种解决方案,它适用于您在评论中描述的情况。描述会是
tl;drtl;dr,所以我最好展示一张图片structure of my test project我的测试项目的结构。回答by Walter Roman
I use process.cwd()in my projects. For example:
我process.cwd()在我的项目中使用。例如:
var Foo = require(process.cwd() + '/common/foo.js');
It might be worth noting that this will result in requireing an absolute path, though I have yet to run into issues with this.
可能值得注意的是,这将导致require绝对路径,尽管我还没有遇到过这个问题。
回答by cyberwombat
If you are using yarninstead of npmyou can use workspaces.
如果你使用yarn而不是npm你可以使用workspaces。
Let's say I have a folder servicesI wish to require more easily:
假设我有一个services我希望更轻松地需要的文件夹:
.
├── app.js
├── node_modules
├── test
├── services
│?? ├── foo
│?? └── bar
└── package.json
To create a Yarn workspace, create a package.jsonfile inside the services folder:
要创建 Yarn 工作区,请在以下package.json目录中创建一个文件services folder:
{
"name": "myservices",
"version": "1.0.0"
}
In your main package.json add:
在你的主 package.json 添加:
"private": true,
"workspaces": ["myservices"]
Run yarn installfrom the root of the project.
yarn install从项目的根目录运行。
Then, anywhere in your code, you can do:
然后,您可以在代码的任何位置执行以下操作:
const { myFunc } = require('myservices/foo')
instead of something like:
而不是像:
const { myFunc } = require('../../../../../../services/foo')
回答by indirectlylit
There's a good discussion of this issue here.
有这个问题的一个很好的讨论在这里。
I ran into the same architectural problem: wanting a way of giving my application more organization and internal namespaces, without:
我遇到了同样的架构问题:想要一种方法来为我的应用程序提供更多的组织和内部命名空间,而无需:
- mixing application modules with external dependencies or bothering with private npm repos for application-specific code
- using relative requires, which make refactoring and comprehension harder
- using symlinks or changing the node path, which can obscure source locations and don't play nicely with source control
- 将应用程序模块与外部依赖项混合在一起,或者为特定于应用程序的代码使用私有 npm 存储库
- 使用相对要求,这使得重构和理解变得更加困难
- 使用符号链接或更改节点路径,这可能会掩盖源位置并且不能很好地与源代码控制配合使用
In the end, I decided to organize my code using file naming conventions rather than directories. A structure would look something like:
最后,我决定使用文件命名约定而不是目录来组织我的代码。一个结构看起来像:
- npm-shrinkwrap.json
- package.json
- node_modules
- ...
- src
- app.js
- app.config.js
- app.models.bar.js
- app.models.foo.js
- app.web.js
- app.web.routes.js
- ...
- npm-shrinkwrap.json
- 包.json
- 节点模块
- ...
- 源文件
- 应用程序.js
- 应用配置文件
- app.models.bar.js
- app.models.foo.js
- 应用程序.web.js
- app.web.routes.js
- ...
Then in code:
然后在代码中:
var app_config = require('./app.config');
var app_models_foo = require('./app.models.foo');
or just
要不就
var config = require('./app.config');
var foo = require('./app.models.foo');
and external dependencies are available from node_modules as usual:
和外部依赖项可以像往常一样从 node_modules 获得:
var express = require('express');
In this way, all application code is hierarchically organized into modules and available to all other code relative to the application root.
通过这种方式,所有应用程序代码都被分层组织成模块,并可供与应用程序根相关的所有其他代码使用。
The main disadvantage is of course that in a file browser, you can't expand/collapse the tree as though it was actually organized into directories. But I like that it's very explicit about where all code is coming from, and it doesn't use any 'magic'.
主要的缺点当然是在文件浏览器中,您无法展开/折叠树,就好像它实际上被组织到目录中一样。但我喜欢它非常明确地说明所有代码的来源,并且不使用任何“魔法”。
回答by protometa
Assuming your project root is the current working directory, this should work:
假设您的项目根目录是当前工作目录,这应该可以工作:
// require built-in path module
path = require('path');
// require file relative to current working directory
config = require( path.resolve('.','config.js') );

