我想要我的文件总是由我的项目的根目录而不是相对于当前模块.
例如,如果你看看https://github.com/visionmedia/express/blob/2820f2227de0229c5d7f28009aa432f9f3a7b5f9/examples/downloads/app.js第6行,你会看到
express = require('../../')
Run Code Online (Sandbox Code Playgroud)
这真是糟糕的IMO.想象一下,我想把我的所有例子都放在根目录上,只有一个级别.这是不可能的,因为我必须在每个示例中更新超过30个示例和多次.对此:
express = require('../')
Run Code Online (Sandbox Code Playgroud)
我的解决方案是基于root的特殊情况:如果一个字符串以$开头,那么它相对于项目的根文件夹.
任何帮助表示赞赏,谢谢
现在我正在使用require.js,它允许您以一种方式编写,并在客户端和服务器上运行.Require.js还允许您创建自定义路径.-«
现在我转到webpack + gulp,我使用enhanced-require来处理服务器端的模块.请参阅此处的基本原理:http://hackhat.com/p/110/module-loader-webpack-vs-requirejs-vs-browserify/
cro*_*vel 155
那怎么样:
var myModule = require.main.require('./path/to/module');
Run Code Online (Sandbox Code Playgroud)
它需要文件,好像它是从主js文件中需要的,所以只要您的主js文件位于项目的根目录,它就能很好地工作......这是我所欣赏的.
Pao*_*tti 125
Browserify手册中有一个非常有趣的部分:
避免../../../../../../ ..
并非应用程序中的所有内容都属于公共npm,并且在许多情况下设置私有npm或git repo的开销仍然很大.以下是一些避免
../../../../../../../
相对路径问题的方法.node_modules
人们有时会反对将特定于应用程序的模块放入node_modules中,因为如果不检查npm中的第三方模块,如何检查内部模块并不明显.
答案很简单!如果您有一个
.gitignore
忽略的文件node_modules
:Run Code Online (Sandbox Code Playgroud)node_modules
您只需
!
为每个内部应用程序模块添加一个例外:Run Code Online (Sandbox Code Playgroud)node_modules/* !node_modules/foo !node_modules/bar
请注意,如果父项已被忽略,则无法取消对子目录的取消标记.所以,不是忽略的
node_modules
,你必须忽略每一个目录内node_modules
与node_modules/*
技巧,然后您可以添加您的例外.现在,在您的应用程序的任何地方,您都可以拥有
require('foo')
或require('bar')
不拥有非常大且脆弱的相对路径.如果你有很多模块,并希望将它们与npm安装的第三方模块分开,你可以将它们全部放在一个目录下,
node_modules
例如node_modules/app
:Run Code Online (Sandbox Code Playgroud)node_modules/app/foo node_modules/app/bar
现在,您将能够
require('app/foo')
或require('app/bar')
在应用程序的任何地方.在你的
.gitignore
,只需添加一个例外node_modules/app
:Run Code Online (Sandbox Code Playgroud)node_modules/* !node_modules/app
如果您的应用程序在package.json中配置了转换,则需要在您的
node_modules/foo
或node_modules/app/foo
组件目录中创建一个单独的package.json及其自己的转换字段,因为转换不适用于模块边界.这将使您的模块对应用程序中的配置更改更加健壮,并且可以更轻松地在应用程序之外独立重用软件包.符号链接
如果您正在开发一个可以创建符号链接而不需要支持窗口的应用程序,那么另一个方便的技巧就是将一个
lib/
或一个app/
文件夹符号链接到node_modules
.从项目根目录,执行:Run Code Online (Sandbox Code Playgroud)ln -s ../lib node_modules/app
现在,从项目的任何地方,您都可以
lib/
通过执行require('app/foo.js')
来获取文件lib/foo.js
.自定义路径
您可能会看到一些地方谈论使用
$NODE_PATH
环境变量或opts.paths
添加节点和browserify的目录以查找模块.与大多数其他平台不同,
$NODE_PATH
与有效使用node_modules
目录相比,使用shell样式的路径目录数组在节点中不是那么有利.这是因为您的应用程序与运行时环境配置紧密耦合,因此有更多移动部件,您的应用程序仅在您的环境设置正确时才能工作.
node和browserify都支持但不鼓励使用
$NODE_PATH
.
Bla*_*son 67
我喜欢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
Run Code Online (Sandbox Code Playgroud)
例如,如果你在,car/index.js
你可以require('helper')
和节点找到它!
node有一个聪明的算法来解析竞争平台中独有的模块.
如果require('./foo.js')
从/beep/boop/bar.js
节点将寻找./foo.js
在/beep/boop/foo.js
.以a开头./
或../
始终是调用文件的本地路径require()
.
但是,如果您需要非相对名称(如require('xyz')
from)/beep/boop/foo.js
,则节点按顺序搜索这些路径,在第一次匹配时停止并在未找到任何内容时引发错误:
/beep/boop/node_modules/xyz
/beep/node_modules/xyz
/node_modules/xyz
Run Code Online (Sandbox Code Playgroud)
对于xyz
存在的每个目录,节点将首先查找a xyz/package.json
以查看"main"
字段是否存在."main"
如果您require()
是目录路径,该字段定义应该负责哪个文件.
例如,if /beep/node_modules/xyz
是第一个匹配并且/beep/node_modules/xyz/package.json
具有:
{
"name": "xyz",
"version": "1.2.3",
"main": "lib/abc.js"
}
Run Code Online (Sandbox Code Playgroud)
那么出口/beep/node_modules/xyz/lib/abc.js
将由
require('xyz')
.
如果没有package.json
或没有"main"
字段,index.js
则假定:
/beep/node_modules/xyz/index.js
Run Code Online (Sandbox Code Playgroud)
Jas*_*ith 36
看起来"非常糟糕",但要给它时间.事实上,它确实很好.明确的require()
s给出了完全透明和易于理解,就像在项目生命周期中呼吸新鲜空气.
可以这样想:你正在阅读一个例子,将你的脚趾浸入Node.js,你已经确定它是"非常糟糕的IMO".你是Node.js社区的第二猜测领导者,他们编写和维护Node.js应用程序的时间比任何人都多.作者犯这样一个菜鸟错误的可能性有多大?(我同意,从我的Ruby和Python背景来看,它最初看起来像是一场灾难.)
围绕Node.js有很多炒作和反炒作.但是当尘埃落定时,我们将承认明确的模块和"本地第一"软件包是采用的主要动力.
当然,node_modules
从当前目录开始,然后搜索父母,祖父母,曾祖父母等.所以你安装的软件包已经以这种方式工作了.通常你可以require("express")
在你的项目的任何地方,它工作正常.
如果您发现自己从项目的根目录加载公共文件(可能是因为它们是常用的实用程序功能),那么这是一个很大的线索,是时候制作一个包.包非常简单:将文件移入node_modules/
并放入package.json
其中.瞧!可以从整个项目中访问该命名空间中的所有内容.包是将代码放入全局命名空间的正确方法.
我个人不使用这些技巧,但他们确实回答了你的问题,当然你比我更了解你自己的情况.
您可以设置$NODE_PATH
为项目根目录.您将搜索该目录require()
.
接下来,您可以妥协并要求所有示例中的公共本地文件.该公共文件只是重新导出祖父目录中的真实文件.
examples/downloads/app.js(和许多其他人一样)
var express = require('./express')
Run Code Online (Sandbox Code Playgroud)
实例/下载/ express.js
module.exports = require('../../')
Run Code Online (Sandbox Code Playgroud)
现在,当您重新定位这些文件时,最糟糕的情况是修复一个填充模块.
war*_*sea 20
看看node-rfr.
这很简单:
var rfr = require('rfr');
var myModule = rfr('projectSubDir/myModule');
Run Code Online (Sandbox Code Playgroud)
Ale*_*kii 12
恕我直言,最简单的方法是将自己的函数定义为GLOBAL
对象的一部分.projRequire.js
使用以下内容在项目的根目录中创建:
var projectDir = __dirname;
module.exports = GLOBAL.projRequire = function(module) {
return require(projectDir + module);
}
Run Code Online (Sandbox Code Playgroud)
在require
任何项目特定模块之前的主文件中:
// init projRequire
require('./projRequire');
Run Code Online (Sandbox Code Playgroud)
以下之后对我有用:
// main file
projRequire('/lib/lol');
// index.js at projectDir/lib/lol/index.js
console.log('Ok');
Run Code Online (Sandbox Code Playgroud)
tl;dr
,所以我更好地展示了我的测试项目结构的图片.
Wal*_*man 12
我process.cwd()
在我的项目中使用.例如:
var Foo = require(process.cwd() + '/common/foo.js');
Run Code Online (Sandbox Code Playgroud)
值得注意的是,这将导致require
绝对路径,尽管我还没有遇到这个问题.
假设您的项目root是当前工作目录,这应该工作:
// require built-in path module
path = require('path');
// require file relative to current working directory
config = require( path.resolve('.','config.js') );
Run Code Online (Sandbox Code Playgroud)
有这个问题的一个很好的讨论在这里.
我遇到了同样的架构问题:想要一种给我的应用程序提供更多组织和内部命名空间的方法,而不需要:
最后,我决定使用文件命名约定而不是目录来组织我的代码.结构看起来像:
然后在代码中:
var app_config = require('./app.config');
var app_models_foo = require('./app.models.foo');
Run Code Online (Sandbox Code Playgroud)
要不就
var config = require('./app.config');
var foo = require('./app.models.foo');
Run Code Online (Sandbox Code Playgroud)
和往常一样,node_modules可以使用外部依赖项:
var express = require('express');
Run Code Online (Sandbox Code Playgroud)
通过这种方式,所有应用程序代码都按层次结构组织成模块,并且可用于相对于应用程序根目录的所有其他代码.
当然,主要的缺点是在文件浏览器中,您无法展开/折叠树,就好像它实际上已组织到目录中一样.但我喜欢它非常清楚所有代码的来源,并且它不使用任何"魔法".
如果您使用yarn而不是npm,则可以使用工作区。
假设我有一个services
我希望更轻松地需要的文件夹:
.
??? app.js
??? node_modules
??? test
??? services
? ??? foo
? ??? bar
??? package.json
Run Code Online (Sandbox Code Playgroud)
要创建Yarn工作区,请package.json
在内创建一个文件services folder
:
{
"name": "myservices",
"version": "1.0.0"
}
Run Code Online (Sandbox Code Playgroud)
在您的主要package.json中添加:
"private": true,
"workspaces": ["myservices"]
Run Code Online (Sandbox Code Playgroud)
yarn install
从项目的根目录运行。
然后,您可以在代码中的任何地方执行以下操作:
const { myFunc } = require('myservices/foo')
Run Code Online (Sandbox Code Playgroud)
而不是这样的:
const { myFunc } = require('../../../../../../services/foo')
Run Code Online (Sandbox Code Playgroud)
我尝试过很多这样的解决方案.我最后将它添加到我的主文件的顶部(例如index.js):
process.env.NODE_PATH = __dirname;
require('module').Module._initPaths();
Run Code Online (Sandbox Code Playgroud)
这会在加载脚本时将项目根添加到NODE_PATH.允许我通过引用项目根目录中的相对路径来请求项目中的任何文件var User = require('models/user')
.只要您在项目根目录中运行主脚本,然后在项目中运行其他任何内容,此解决方案就应该可以运行.
小智 7
你可以使用我制作的模块,Undot.这不是什么先进的,只是一个帮手,所以你可以简单地避免那些点地狱.
例:
var undot = require('undot');
var User = undot('models/user');
var config = undot('config');
var test = undot('test/api/user/auth');
Run Code Online (Sandbox Code Playgroud)
一些答案是说最好的方法是将代码作为一个包添加到node_module中,我同意并且它可能是丢失../../../
in in 的最佳方法,但它们实际上都没有给出一种方法.
从版本开始,2.0.0
您可以从本地文件安装包,这意味着您可以在根目录中创建包含所需包的所有包,
-modules
--foo
--bar
-app.js
-package.json
Run Code Online (Sandbox Code Playgroud)
所以在package.json中你可以添加modules
(或foo
和bar
)作为包而无需发布或使用这样的外部服务器:
{
"name": "baz",
"dependencies": {
"bar": "file: ./modules/bar",
"foo": "file: ./modules/foo"
}
}
Run Code Online (Sandbox Code Playgroud)
之后,您npm install
可以使用var foo = require("foo")
,就像使用所有其他软件包一样,您可以访问代码.
更多信息可以在这里找到:
https://docs.npmjs.com/files/package.json#local-paths
在这里如何创建一个包:
https://docs.npmjs.com/getting-started/creating-node-modules
另一个答案:
想象一下这个文件夹结构:
测试
然后在test.js 中,你需要这样的文件:
const foo = require("../src/subdir/foo");
const bar = require("../src/subdir/bar");
const main = require("../src/main");
const _ = require("lodash");
Run Code Online (Sandbox Code Playgroud)
在main.js 中:
const foo = require("./subdir/foo");
const bar = require("./subdir/bar");
const _ = require("lodash");
Run Code Online (Sandbox Code Playgroud)
现在你可以使用babel和babel-plugin-module-resolver了。babelrc文件来配置 2 个根文件夹:
{
"plugins": [
["module-resolver", {
"root": ["./src", "./src/subdir"]
}]
]
}
Run Code Online (Sandbox Code Playgroud)
现在您可以在测试和src中以相同的方式要求文件:
const foo = require("foo");
const bar = require("bar");
const main = require("main");
const _ = require("lodash");
Run Code Online (Sandbox Code Playgroud)
如果你想使用es6 模块语法:
{
"plugins": [
["module-resolver", {
"root": ["./src", "./src/subdir"]
}],
"transform-es2015-modules-commonjs"
]
}
Run Code Online (Sandbox Code Playgroud)
然后像这样在测试和src 中导入文件:
import foo from "foo"
import bar from "bar"
import _ from "lodash"
Run Code Online (Sandbox Code Playgroud)
您可以在app.js中定义类似的内容:
requireFromRoot = (function(root) {
return function(resource) {
return require(root+"/"+resource);
}
})(__dirname);
Run Code Online (Sandbox Code Playgroud)
然后,无论何时你想要从root用户那里获得某些东西,你只需使用requireFromRoot而不是vanilla require.到目前为止对我来说效果很好.
examples
目录不能包含node_modules
带有指向项目根目录的符号链接的 ,project -> ../../
从而允许示例使用require('project')
,尽管这不会删除映射,但它确实允许源使用require('project')
而不是require('../../')
.
我已经对此进行了测试,它确实适用于 v0.6.18。
目录列表project
:
$ 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 -> ../../
Run Code Online (Sandbox Code Playgroud)
的内容为对象index.js
的属性分配一个值,exports
并console.log
使用说明它是必需的消息进行调用。的内容test.js
是require('project')
。
手动创建符号链接的问题是每次你npm ci
都会丢失符号链接。如果您使符号链接过程成为依赖项,中提琴,没问题。
该模块basetag
是一个安装后脚本,它在$
每次运行npm install
或npm ci
运行时创建一个符号链接(或 Windows 连接):
$ 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 -> ../../
Run Code Online (Sandbox Code Playgroud)
npm install --save basetag
Run Code Online (Sandbox Code Playgroud)
有了这个,您不需要对代码或要求系统进行任何特殊修改。$
成为您可以要求的根。
node_modules/$ -> ..
Run Code Online (Sandbox Code Playgroud)
如果您不喜欢使用$
and 更喜欢#
或其他东西(除了@
,这是 npm 的一个特殊字符),您可以分叉它并进行更改。
注意:虽然 Windows 符号链接(到文件)需要管理员权限,但 Windows 连接(到目录)不需要 Windows 管理员权限。这是一个安全、可靠、跨平台的解决方案。
这是我做了6个多月的实际方式.我在项目中使用名为node_modules的文件夹作为我的根文件夹,这样它总是会从我称之为绝对需求的任何地方查找该文件夹:
当您嵌套到文件夹中时,这更有用,如果以绝对方式设置,更改文件位置的工作要少得多.我只在整个应用程序中使用2相对要求.
恕我直言,实现此目标的最简单方法是在应用启动时创建一个指向的符号链接node_modules/app
(或您所说的任何名称),该链接指向../app
。然后,您可以致电require("app/my/module")
。符号链接在所有主要平台上均可用。
但是,您仍然应该将内容拆分成较小的,可维护的模块,这些模块通过npm安装。您也可以通过git-url安装私有模块,因此没有理由拥有一个单一的应用程序目录。
小智 5
在您自己的项目中,您可以修改在根目录中使用的任何 .js 文件,并将其路径添加到process.env
变量的属性中。例如:
// in index.js
process.env.root = __dirname;
Run Code Online (Sandbox Code Playgroud)
之后,您可以在任何地方访问该属性:
// in app.js
express = require(process.env.root);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
157340 次 |
最近记录: |