Como fazer o node.js requerer absoluto? (em vez de relativo)

Eu gostaria de exigir meus arquivos sempre pela raiz do meu projeto e não em relação ao módulo atual.

Por exemplo, se você olhar para https://github.com/visionmedia/express/blob/2820f2227de0229c5d7f28009aa432f9f3a7b5f9/examples/downloads/app.js linha 6, você verá

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

Isso é muito ruim IMO. Imagine que eu gostaria de colocar todos os meus exemplos mais próximos da raiz apenas em um nível. Isso seria impossível, porque eu teria que atualizar mais de 30 exemplos e muitas vezes dentro de cada exemplo. Para isso:

 express = require('../') 

Minha solução seria ter um caso especial para raiz: se uma string começa com $, então é relativa à pasta raiz do projeto.

Qualquer ajuda é apreciada, obrigado

Atualização 2

Agora estou usando o require.js que permite escrever de uma maneira e funciona tanto no cliente quanto no servidor. O Require.js também permite que você crie caminhos personalizados.

Atualização 3

Agora eu mudei para o webpack + gulp e uso o enhanced-require para manipular módulos no lado do servidor. Veja aqui o raciocínio: http://hackhat.com/p/110/module-loader-webpack-vs-requirejs-vs-browserify/

E sobre:

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

Ele requer o arquivo como se fosse necessário a partir do arquivo js principal, por isso funciona muito bem, desde que o seu arquivo js principal esteja na raiz do seu projeto … e isso é algo que eu aprecio.

Há uma seção realmente interessante no Manual do Browserify :

evitando ../../../../../../ ..

Nem tudo em um aplicativo pertence adequadamente ao npm público, e a sobrecarga de configurar um repository npm ou git privado ainda é bastante grande em muitos casos. Aqui estão algumas abordagens para evitar o problema de ../../../../../../../ caminhos relativos.

node_modules

As pessoas às vezes se opõem a colocar módulos específicos de aplicativos em node_modules porque não é óbvio como verificar seus módulos internos sem também verificar em módulos de terceiros a partir do npm.

A resposta é bem simples! Se você tiver um arquivo .gitignore que ignora node_modules :

 node_modules 

Você pode simplesmente adicionar uma exceção com ! para cada um dos seus módulos de aplicativo internos:

 node_modules/* !node_modules/foo !node_modules/bar 

Por favor, note que você não pode ignorar um subdiretório, se o pai já foi ignorado. Então, ao invés de ignorar node_modules , você tem que ignorar todo diretório dentro de node_modules com o truque node_modules/* , e então você pode adicionar suas exceções.

Agora, em qualquer lugar do seu aplicativo, você poderá require('foo') ou require('bar') sem ter um caminho relativo muito grande e frágil.

Se você tem muitos módulos e quer mantê-los mais separados dos módulos de terceiros instalados pelo npm, você pode colocá-los todos em um diretório em node_modules , como node_modules/app :

 node_modules/app/foo node_modules/app/bar 

Agora você poderá require('app/foo') ou require('app/bar') de qualquer lugar em seu aplicativo.

Em seu .gitignore , apenas adicione uma exceção para node_modules/app :

 node_modules/* !node_modules/app 

Se seu aplicativo teve transformações configuradas em package.json, você precisará criar um package.json separado com seu próprio campo de transformação em seu diretório do componente node_modules/foo ou node_modules/app/foo , pois as transformações não se aplicam aos limites do módulo. Isso tornará seus módulos mais robustos contra alterações de configuração em seu aplicativo e será mais fácil reutilizar independentemente os pacotes fora de seu aplicativo.

link simbólico

Outro truque útil se você estiver trabalhando em um aplicativo onde você pode criar links simbólicos e não precisar de suporte ao windows é fazer uma node_modules simbólica de uma lib/ ou app/ em node_modules . A partir da raiz do projeto, faça:

 ln -s ../lib node_modules/app 

e agora de qualquer lugar em seu projeto você poderá requerer arquivos em lib/ fazendo require('app/foo.js') para obter lib/foo.js

caminhos personalizados

Você pode ver alguns locais falando sobre o uso da variável de ambiente $NODE_PATH ou opts.paths para adicionar diretórios para o nó e navegar para procurar módulos.

Ao contrário da maioria das outras plataformas, o uso de uma matriz de diretórios de caminho no estilo de shell com $NODE_PATH não é tão favorável no nó em comparação com o uso efetivo do diretório node_modules .

Isso ocorre porque seu aplicativo é mais acoplado a uma configuração de ambiente de tempo de execução, portanto, há mais partes móveis e seu aplicativo só funcionará quando o ambiente for configurado corretamente.

nó e navegador ambos suporte, mas desencorajar o uso de $NODE_PATH .

Eu gosto de fazer uma nova pasta node_modules para código compartilhado, então deixe o node e require fazer o que ele faz melhor.

por exemplo:

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

Por exemplo, se você estiver em car/index.js você pode require('helper') e o nó irá encontrá-lo!

Como funcionam os node_modules

O node tem um algoritmo inteligente para resolver módulos que é único entre as plataformas rivais.

Se você require('./foo.js') de /beep/boop/bar.js , o nó procurará ./foo.js em /beep/boop/foo.js . Os caminhos que começam com ./ ou ../ são sempre locais para o arquivo que chama require() .

No entanto, se você precisar de um nome não relativo, como require('xyz') de /beep/boop/foo.js , o nó pesquisará esses caminhos em ordem, parando na primeira correspondência e gerando um erro se nada for encontrado:

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

Para cada diretório xyz que existe, o nó procurará primeiro por um xyz/package.json para ver se existe um campo "main" . O campo "main" define qual arquivo deve assumir o controle se você require() do caminho do diretório.

Por exemplo, se /beep/node_modules/xyz for a primeira correspondência e /beep/node_modules/xyz/package.json tiver:

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

então as exportações de /beep/node_modules/xyz/lib/abc.js serão retornadas por require('xyz') .

Se não houver nenhum package.json ou nenhum campo "main" , o index.js será assumido:

 /beep/node_modules/xyz/index.js 

A grande imagem

Parece “muito ruim”, mas dá tempo. É, de fato, muito bom. Os require() explícitos require() fornecem uma total transparência e facilidade de compreensão, que é como uma lufada de ar fresco durante o ciclo de vida de um projeto.

Pense desta maneira: Você está lendo um exemplo, colocando os dedos do pé no Node.js e decidiu que é “IMO realmente ruim”. Você está questionando os líderes da comunidade Node.js, pessoas que registraram mais horas escrevendo e mantendo aplicativos Node.js do que qualquer outra pessoa. Qual é a chance do autor ter cometido um erro tão novato? (E eu concordo, a partir do meu background em Ruby e Python, parece a princípio um desastre.)

Há muito hype e contra-hype em torno do Node.js. Mas quando a poeira baixar, reconheceremos que os módulos explícitos e os pacotes “locais primeiros” foram um dos principais impulsionadores da adoção.

O caso comum

Naturalmente, node_modules do diretório atual, então o pai, o avô, o bisavô, etc. são pesquisados. Então os pacotes que você instalou já funcionam dessa maneira. Normalmente você pode require("express") de qualquer lugar em seu projeto e funciona bem.

Se você se encontrar carregando arquivos comuns a partir da raiz do seu projeto (talvez porque eles sejam funções utilitárias comuns), então isso é uma grande dica de que é hora de fazer um pacote. Os pacotes são muito simples: mova seus arquivos para node_modules/ e coloque um package.json lá. Voila! Tudo nesse espaço de nomes é acessível a partir do seu projeto inteiro. Pacotes são a maneira correta de colocar seu código em um namespace global.

Outras soluções alternativas

Eu pessoalmente não uso essas técnicas, mas elas respondem a sua pergunta e, claro, você conhece sua própria situação melhor do que eu.

Você pode definir $NODE_PATH para a raiz do seu projeto. Esse diretório será pesquisado quando você require() .

Em seguida, você pode comprometer e exigir um arquivo local comum de todos os seus exemplos. Esse arquivo comum simplesmente exporta novamente o arquivo true no diretório grandparent.

examples / downloads / app.js (e muitos outros como ele)

 var express = require('./express') 

examples / downloads / express.js

 module.exports = require('../../') 

Agora, quando você realoca esses arquivos, o pior caso é consertar o módulo de um shim .

Dê uma olhada no node-rfr .

É tão simples assim:

 var rfr = require('rfr'); var myModule = rfr('projectSubDir/myModule'); 

IMHO, a maneira mais fácil é definir sua própria function como parte do object GLOBAL . Crie projRequire.js na raiz do seu projeto com o seguinte conteúdo:

 var projectDir = __dirname; module.exports = GLOBAL.projRequire = function(module) { return require(projectDir + module); } 

No seu arquivo principal antes de require qualquer um dos módulos específicos do projeto:

 // init projRequire require('./projRequire'); 

Depois disso, o seguinte funciona para mim:

 // main file projRequire('/lib/lol'); // index.js at projectDir/lib/lol/index.js console.log('Ok'); 


@Totty, eu me juntei a outra solução, que poderia funcionar para o caso que você descreveu nos comentários. A descrição será tl;dr , então é melhor eu mostrar uma imagem com a estrutura do meu projeto de teste .

Eu uso process.cwd() em meus projetos. Por exemplo:

 var Foo = require(process.cwd() + '/common/foo.js'); 

Pode valer a pena notar que isso resultará na require um caminho absoluto, embora eu ainda tenha que me deparar com problemas com isso.

Há uma boa discussão desta questão aqui .

Eu me deparei com o mesmo problema de arquitetura: querendo uma maneira de dar ao meu aplicativo mais organização e namespaces internos, sem:

  • misturando módulos de aplicativos com dependencies externas ou incomodando-se com repos npm privados para código específico de aplicativo
  • usando parente requer, o que torna a refatoração e a compreensão mais difíceis
  • usando links simbólicos ou alterando o caminho do nó, o que pode obscurecer os locais de origem e não funcionar bem com o controle de origem

No final, decidi organizar meu código usando convenções de nomenclatura de arquivos em vez de diretórios. Uma estrutura seria algo como:

  • 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

Então no código:

 var app_config = require('./app.config'); var app_models_foo = require('./app.models.foo'); 

ou apenas

 var config = require('./app.config'); var foo = require('./app.models.foo'); 

e dependencies externas estão disponíveis em node_modules como de costume:

 var express = require('express'); 

Desta forma, todo o código da aplicação é hierarquicamente organizado em módulos e disponível para todos os outros códigos relativos à raiz da aplicação.

A principal desvantagem é que em um navegador de arquivos, você não pode expandir / recolher a tree como se ela estivesse organizada em diretórios. Mas eu gosto que seja muito explícito de onde todo o código está vindo, e ele não usa nenhuma ‘magia’.

Supondo que o seu projeto raiz é o diretório de trabalho atual, isso deve funcionar:

 // require built-in path module path = require('path'); // require file relative to current working directory config = require( path.resolve('.','config.js') ); 

Aqui está o jeito que estou fazendo há mais de 6 meses. Eu uso uma pasta chamada node_modules como minha pasta raiz no projeto, desta forma ele sempre irá procurar por aquela pasta de qualquer lugar que eu chame de absolute require:

  • node_modules
    • meu projeto
      • index.js Eu posso exigir (“myProject / someFolder / hey.js”) em vez de exigir (“. / someFolder / hey.js”)
      • someFolder que contém hey.js

Isso é mais útil quando você está nested em pastas e muito menos trabalho para alterar um local de arquivo se for definido de maneira absoluta. Eu só uso 2 a necessidade relativa em todo o meu aplicativo .

Você poderia definir algo assim em seu app.js:

 requireFromRoot = (function(root) { return function(resource) { return require(root+"/"+resource); } })(__dirname); 

e sempre que você quiser exigir algo da raiz, não importa onde você esteja, basta usar requireFromRoot em vez da baunilha. Funciona muito bem para mim até agora.

Eu tentei muitas dessas soluções. Eu acabei adicionando isso ao topo do meu arquivo principal (por exemplo, index.js):

 process.env.NODE_PATH = __dirname; require('module').Module._initPaths(); 

Isso adiciona a raiz do projeto ao NODE_PATH quando o script é carregado. O permite-me requerer qualquer arquivo no meu projeto referenciando seu caminho relativo a partir da raiz do projeto, como var User = require('models/user') . Essa solução deve funcionar desde que você esteja executando um script principal na raiz do projeto antes de executar qualquer outra coisa em seu projeto.

A maneira mais fácil de conseguir isso é criando um link simbólico na boot do aplicativo em node_modules/app (ou seja lá como você o chamar) que aponta para ../app . Então você pode apenas chamar require("app/my/module") . Links simbólicos estão disponíveis em todas as principais plataformas.

No entanto, você ainda deve dividir seu material em módulos menores, que podem ser mantidos e instalados via npm. Você também pode instalar seus módulos privados via git-url, então não há razão para ter um diretório de aplicativos monolítico.

Em seu próprio projeto, você pode modificar qualquer arquivo .js usado no diretório raiz e adicionar seu caminho a uma propriedade da variável process.env . Por exemplo:

 // in index.js process.env.root = __dirname; 

Depois você pode acessar a propriedade em todos os lugares:

 // in app.js express = require(process.env.root); 

Você poderia usar um módulo que eu fiz, Undot . Não é nada avançado, apenas um ajudante para que você possa evitar esses infernos com simplicidade.

Exemplo:

 var undot = require('undot'); var User = undot('models/user'); var config = undot('config'); var test = undot('test/api/user/auth'); 

O que eu gosto de fazer é aproveitar como o nó carrega do diretório node_module para isso.

Se alguém tenta carregar o módulo “coisa”, alguém faria algo como

 require('thing'); 

O nó procurará o diretório ‘thing’ no diretório ‘node_module’.

Como o node_module normalmente está na raiz do projeto, podemos aproveitar essa consistência. (Se node_module não está na raiz, então você tem outras dores de cabeça autoinduzidas para lidar.)

Se entrarmos no diretório e depois voltarmos, podemos obter um caminho consistente para a raiz do projeto do nó.

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

Então, se quisermos acessar o diretório / happy, faríamos isso.

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

Embora seja um pouco hacky, no entanto eu sinto que se a funcionalidade de como node_modules carregar muda, haverá problemas maiores para lidar. Esse comportamento deve permanecer consistente.

Para deixar as coisas claras, eu faço isso, porque o nome do módulo não importa.

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

Eu usei recentemente para angular2. Eu quero carregar um serviço da raiz.

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

Algumas das respostas estão dizendo que a melhor maneira é adicionar o código ao node_module como um pacote, eu concordo e provavelmente é a melhor maneira de perder o ../../../ no require, mas nenhum deles realmente dá uma maneira de fazer isso.

da versão 2.0.0 você pode instalar um pacote de arquivos locais, o que significa que você pode criar pastas em sua raiz com todos os pacotes que você quer,

 -modules --foo --bar -app.js -package.json 

Portanto, em package.json você pode adicionar os modules (ou foo e bar ) como um pacote sem publicar ou usar um servidor externo como este:

 { "name": "baz", "dependencies": { "bar": "file: ./modules/bar", "foo": "file: ./modules/foo" } } 

Depois disso, você npm install e pode acessar o código com var foo = require("foo") , assim como faz com todos os outros pacotes.

mais informações podem ser encontradas aqui:

https://docs.npmjs.com/files/package.json#local-paths

e aqui como criar um pacote:

https://docs.npmjs.com/getting-started/creating-node-modules

O diretório de examples não poderia conter um node_modules com um link simbólico para a raiz do project -> ../../ permitindo assim que os exemplos usem require('project') , embora isso não remova o mapeamento, ele permite que a fonte use require('project') vez de require('../../') .

Eu testei isso e funciona com v0.6.18.

Listagem do diretório do 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 -> ../../ 

O conteúdo de index.js atribui um valor a uma propriedade do object de exports e chama console.log com uma mensagem que declara que foi necessário. O conteúdo de test.js é require('project') .

Se alguém está procurando outra maneira de contornar este problema, aqui está minha própria contribuição para o esforço:

https://www.npmjs.com/package/use-import

A idéia básica: você cria um arquivo JSON na raiz do projeto que mapeia seus caminhos de arquivos para nomes abreviados (ou use o autopurpper para fazer isso por você). Você pode então solicitar seus arquivos / módulos usando esses nomes. Igual a:

 var use = require('use-import'); var MyClass = use('MyClass'); 

Então tem isso.

Eu escrevi este pequeno pacote que permite que você requeira pacotes pelo caminho relativo do projeto raiz, sem introduzir variables ​​globais ou sobrescrevendo padrões de nós

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

Funciona assim

 // 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() 

Outra resposta:

Imagine esta estrutura de pastas:

  • node_modules
    • lodash
  • src
    • subdirecionar
      • foo.js
      • bar.js
    • main.js
  • Testes

    • test.js

Em seguida, em test.js , você precisa exigir arquivos como este:

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

e em main.js :

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

Agora você pode usar o babel e o babel-plugin-module-resolver com isso. Arquivo babelrc para configurar duas pastas raiz:

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

Agora você pode exigir arquivos da mesma maneira em testes e em src :

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

e se você quiser usar a syntax do módulo es6 :

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

então você importa arquivos em testes e src assim:

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

Eu criei um módulo de nó chamado “rekiure”

permite que você exija sem o uso de caminhos relativos

https://npmjs.org/package/rekuire

é super fácil de usar

Estamos prestes a tentar uma nova maneira de resolver esse problema.

Tomando exemplos de outros projetos conhecidos como spring e guice, definiremos um object “context” que conterá toda a instrução “require”.

Este object será então passado para todos os outros módulos para uso.

Por exemplo

 var context = {} context.module1 = require("./module1")( { "context" : context } ) context.module2 = require("./module2")( { "context" : context } ) 

Isso nos obriga a escrever cada módulo como uma function que recebe opts, o que nos parece uma boa prática de qualquer maneira ..

 module.exports = function(context){ ... } 

e então você se referirá ao contexto em vez de requerer material.

var module1Ref = context.moduel1;

Se você quiser, você pode facilmente escrever um loop para fazer as declarações requeridas

 var context = {}; var beans = {"module1" : "./module1","module2" : "./module2" }; for ( var i in beans ){ if ( beans.hasOwnProperty(i)){ context[i] = require(beans[i])(context); } }; 

Isso deve facilitar a vida quando você quiser simular (testes) e também resolver seu problema ao mesmo tempo em que torna seu código reutilizável como um pacote.

Você também pode reutilizar o código de boot do contexto, separando a declaração de beans dele. por exemplo, seu arquivo main.js poderia parecer assim

 var beans = { ... }; // like before var context = require("context")(beans); // this example assumes context is a node_module since it is reused.. 

Esse método também se aplica a bibliotecas externas, sem necessidade de codificar seus nomes toda vez que precisarmos delas – no entanto, será necessário um tratamento especial, já que suas exportações não são funções que esperam contexto.

Posteriormente, também podemos definir beans como funções – o que nos permitirá require diferentes módulos de acordo com o ambiente -, mas fora do escopo desta thread.

Eu estava tendo problemas com esse mesmo problema, então escrevi um pacote chamado include .

Inclua alças para descobrir a pasta raiz do seu projeto, localizando o arquivo package.json e, em seguida, passe o argumento path que você forneceu para o native require () sem toda a confusão relativa do caminho. Eu imagino isso não como um substituto para require (), mas uma ferramenta para exigir o manuseio de arquivos ou bibliotecas não-empacotados / não-de terceiros. Algo como

 var async = require('async'), foo = include('lib/path/to/foo') 

Espero que isso possa ser útil.

If your app’s entry point js file (ie the one you actually run “node” on) is in your project root directory, you can do this really easily with the rootpath npm module . Simply install it via

 npm install --save rootpath 

…then at the very top of the entry point js file, add:

 require('rootpath')(); 

From that point forward all require calls are now relative to project root – eg require('../../../config/debugging/log'); becomes require('config/debugging/log'); (where the config folder is in the project root).

In simple lines, u can call your own folder as module :

For that we need: global and app-module-path module

here “App-module-path” is the module ,it enables you to add additional directories to the Node.js module search path And “global” is, anything that you attach to this object will b available everywhere in your app.

Now take a look at this snippet:

 global.appBasePath = __dirname; require('app-module-path').addPath(appBasePath); 

__dirname is current running directory of node.You can give your own path here to search the path for module.

Just want to follow up on the great answer from Paolo Moretti and Browserify. If you are using a transpiler (eg, babel, typescript) and you have separate folders for source and transpiled code like src/ and dist/ , you could use a variation of the solutions as

node_modules

With the following directory structure:

 app node_modules ... // normal npm dependencies for app src node_modules app ... // source code dist node_modules app ... // transpiled code 

you can then let babel etc to transpile src directory to dist directory.

symlink

Using symlink we can get rid some levels of nesting:

 app node_modules ... // normal npm dependencies for app src node_modules app // symlinks to '..' ... // source code dist node_modules app // symlinks to '..' ... // transpiled code 

A caveat with babel –copy-files The --copy-files flag of babel does not deal with symlinks well. It may keep navigating into the .. symlink and recusively seeing endless files. A workaround is to use the following directory structure:

 app node_modules app // symlink to '../src' ... // normal npm dependencies for app src ... // source code dist node_modules app // symlinks to '..' ... // transpiled code 

In this way, code under src will still have app resolved to src , whereas babel would not see symlinks anymore.

Just came across this article which mentions app-module-path . It allows you to configure a base like this:

 require('app-module-path').addPath(baseDir); 

Some time ago I created module for loading modules relative to pre-defined paths.

https://github.com/raaymax/irequire

You can use it instead of require.

 irequire.prefix('controllers',join.path(__dirname,'app/master')); var adminUsersCtrl = irequire("controllers:admin/users"); var net = irequire('net'); 

Maybe it will be usefull for someone..

Whilst these answers work they do not address the problem with npm test

If, for example, I create a global variable in server.js, it will not be set for my test suite execution.

To set a global appRoot variable that will avoid the ../../../ problem and will be available in both npm start AND npm test see:

Mocha tests with extra options or parameters

Note that this is the new official mocha solution .