tutorial servidor proyecto node crear con node.js require

node.js - servidor - npm express



¿Cómo hacer que require en node.js sea siempre relativo a la carpeta raíz del proyecto? (30)

El panorama

Parece "realmente malo", pero dale tiempo. De hecho, es realmente bueno. Los require() explícitos require() ofrecen una total transparencia y facilidad de comprensión que es como una bocanada de aire fresco durante el ciclo de vida de un proyecto.

Piénselo de esta manera: está leyendo un ejemplo, sumergiéndose en Node.js y ha decidido que es "realmente malo IMO". Usted es el segundo en adivinar los líderes de la comunidad Node.js, las personas que han registrado más horas escribiendo y manteniendo aplicaciones Node.js que nadie. ¿Cuál es la posibilidad de que el autor haya cometido un error de novato? (Y estoy de acuerdo, desde mi experiencia con Ruby y Python, al principio parece un desastre).

Hay mucho bombo y contragolpe alrededor de Node.js. Pero cuando el polvo se asiente, reconoceremos que los módulos explícitos y los paquetes "locales primero" fueron un importante impulsor de la adopción.

El caso común

Por supuesto, se node_modules los node_modules del directorio actual, luego el padre, luego abuelo, bisabuelo, etc. Por lo tanto, los paquetes que ha instalado ya funcionan de esta manera. Por lo general, puede require("express") desde cualquier lugar de su proyecto y funciona bien.

Si se encuentra cargando archivos comunes desde la raíz de su proyecto (tal vez porque son funciones de utilidad comunes), entonces esa es una gran pista de que es hora de hacer un paquete. Los paquetes son muy simples: mueva sus archivos a node_modules/ y coloque un package.json allí. Voila! Todo en ese espacio de nombres es accesible desde todo tu proyecto. Los paquetes son la forma correcta de obtener su código en un espacio de nombre global.

Otras soluciones

Personalmente, no uso estas técnicas, pero responden a su pregunta y, por supuesto, usted conoce su propia situación mejor que yo.

Puede establecer $NODE_PATH en su raíz del proyecto. Ese directorio se buscará cuando require() .

A continuación, puede comprometer y exigir un archivo local común de todos sus ejemplos. Ese archivo común simplemente reexporta el archivo verdadero en el directorio de abuelos.

examples / downloads / app.js (y muchos otros como este)

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

examples / downloads / express.js

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

Ahora cuando reubica esos archivos, el peor de los casos es arreglar el módulo de una sola pestaña .

Me gustaría solicitar mis archivos siempre por la raíz de mi proyecto y no en relación con el módulo actual.

Por ejemplo, si mira https://github.com/visionmedia/express/blob/2820f2227de0229c5d7f28009aa432f9f3a7b5f9/examples/downloads/app.js línea 6, verá

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

Eso es realmente malo IMO. Imagina que quisiera poner todos mis ejemplos más cerca de la raíz solo por un nivel. Eso sería imposible, porque tendría que actualizar más de 30 ejemplos y muchas veces dentro de cada ejemplo. A esto:

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

Mi solución sería tener un caso especial para raíz: si una cadena comienza con un $, es relativa a la carpeta raíz del proyecto.

Cualquier ayuda es apreciada, gracias

Actualización 2

Ahora estoy usando require.js, que te permite escribir de una manera y funciona tanto en el cliente como en el servidor. Require.js también te permite crear rutas personalizadas- ««

Actualización 3

Ahora me mudé a webpack + gulp y uso Enhanced-Require para manejar módulos en el lado del servidor. Vea aquí el razonamiento: http://hackhat.com/p/110/module-loader-webpack-vs-requirejs-vs-browserify/


¿No podría el directorio de examples contener un node_modules con un enlace simbólico a la raíz del proyecto del project -> ../../ permitiendo así que los ejemplos utilicen require(''project'') , aunque esto no elimina la asignación, sí permite que la fuente use require(''project'') lugar de require(''../../'') .

He probado esto, y funciona con v0.6.18.

Listado del directorio del 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 -> ../../

El contenido de index.js asigna un valor a una propiedad del objeto de exports e invoca console.log con un mensaje que indica que fue requerido. El contenido de test.js es require(''project'') .


Algunas de las respuestas dicen que la mejor manera es agregar el código al node_module como un paquete, estoy de acuerdo y es probablemente la mejor manera de perder el ../../../ requerido pero ninguno de ellos en realidad da una forma de hacerlo

desde la versión 2.0.0 puede instalar un paquete desde archivos locales, lo que significa que puede crear una carpeta en su raíz con todos los paquetes que desee,

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

entonces en package.json puede agregar los modules (o foo y bar ) como un paquete sin publicar o usar un servidor externo como este:

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

Después de eso, npm install , y puede acceder al código con var foo = require("foo") , tal como lo hace con todos los demás paquetes.

Aquí se puede encontrar más información :

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

y aquí cómo crear un paquete:

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



Eche un vistazo a node-rfr .

Es tan simple como esto:

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


En líneas simples, puedes llamar a tu propia carpeta como módulo:

Para eso necesitamos: módulo global y módulo app-module-path

aquí "App-module-path" es el módulo, le permite agregar directorios adicionales a la ruta de búsqueda del módulo Node.js Y "global" es que todo lo que adjunte a este objeto estará disponible en cualquier lugar de su aplicación.

Ahora eche un vistazo a este fragmento:

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

__dirname es el directorio de ejecución actual del nodo. Puede dar su propia ruta aquí para buscar la ruta del módulo.


En mi humilde opinión, la forma más fácil es definir su propia función como parte del objeto GLOBAL . Cree projRequire.js en la raíz de su proyecto con los siguientes contenidos:

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

En su archivo principal antes de require cualquiera de los módulos específicos del proyecto:

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

Después de eso el siguiente trabajo para mí:

// main file projRequire(''/lib/lol''); // index.js at projectDir/lib/lol/index.js console.log(''Ok''); @Totty, he comentado con otra solución, que podría funcionar para el caso que describiste en los comentarios. La descripción va a ser tl;dr , así que será mejor que muestre una imagen con la estructura de mi proyecto de prueba .


En su propio proyecto, puede modificar cualquier archivo .js que se use en el directorio raíz y agregar su ruta a una propiedad de la variable process.env . Por ejemplo:

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

Luego puede acceder a la propiedad en todas partes:

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


Escribí este pequeño paquete que le permite requerir paquetes por su ruta relativa desde la raíz del proyecto, sin introducir variables globales ni anular los valores predeterminados de los nodos

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

Funciona así

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


Esta es la manera real en que estoy haciendo por más de 6 meses. Utilizo una carpeta llamada node_modules como mi carpeta raíz en el proyecto, de esta manera siempre buscará esa carpeta desde cualquier lugar que llame una necesidad absoluta:

  • node_modules
    • mi proyecto
      • index.js Puedo requerir ("myProject / someFolder / hey.js") en lugar de require ("./ someFolder / hey.js")
      • someFolder que contiene hey.js

Esto es más útil cuando está anidado en carpetas y es mucho menos trabajo cambiar la ubicación de un archivo si está configurado de manera absoluta. Solo uso 2 los requisitos relativos en toda mi aplicación .


Estaba teniendo problemas con este mismo problema, así que escribí un paquete llamado include .

include identificadores que resuelven la carpeta raíz de su proyecto al ubicar su archivo package.json y luego pasa el argumento de ruta que usted le da al require () nativo sin todo el desorden relativo de la ruta. Imagino que esto no es un reemplazo de require (), sino una herramienta para requerir el manejo de archivos o bibliotecas no empaquetados / que no sean de terceros. Algo como

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

Espero que esto pueda ser útil.


Estamos a punto de probar una nueva forma de abordar este problema.

Tomando ejemplos de otros proyectos conocidos como Spring y Guice, definiremos un objeto de "contexto" que contendrá toda la declaración "require".

Este objeto se pasará a todos los otros módulos para su uso.

Por ejemplo

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

This requires us to write each module as a function that receives opts, which looks to us as a best practice anyway..

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

and then you will refer to the context instead of requiring stuff.

var module1Ref = context.moduel1;

If you want to, you can easily write a loop to do the require statements

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

This should make life easier when you want to mock (tests) and also solves your problem along the way while making your code reusable as a package.

You can also reuse the context initialization code by separating the beans declaration from it. for example, your main.js file could look like so

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

This method also applies to external libraries, no need to hard code their names every time we require them - however it will require a special treatment as their exports are not functions that expect context..

Later on we can also define beans as functions - which will allow us to require different modules according to the environment - but that it out of this thread''s scope.


Hay una buena discusión de este tema gist.github.com/branneman/8048520 .

Me encontré con el mismo problema arquitectónico: querer una forma de darle a mi aplicación más organización y espacios de nombres internos, sin:

  • mezclar módulos de aplicaciones con dependencias externas o molestar con repositorios npm privados para código específico de la aplicación
  • usando las necesidades relativas, lo que hace que la refactorización y la comprensión sean más difíciles
  • utilizar enlaces simbólicos o cambiar la ruta del nodo, lo que puede oscurecer las ubicaciones de origen y no jugar bien con el control de código fuente

Al final, decidí organizar mi código usando convenciones de nomenclatura de archivos en lugar de directorios. Una estructura se vería algo así como:

  • npm-shrinkwrap.json
  • paquete.json
  • node_modules
    • ...
  • src
    • app.js
    • app.config.js
    • app.models.bar.js
    • app.models.foo.js
    • app.web.js
    • app.web.routes.js
    • ...

Luego en el código:

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

o solo

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

y las dependencias externas están disponibles desde node_modules como de costumbre:

var express = require(''express'');

De esta forma, todos los códigos de la aplicación se organizan jerárquicamente en módulos y están disponibles para todos los demás códigos relativos a la raíz de la aplicación.

La principal desventaja es, por supuesto, que en un explorador de archivos, no puede expandir / contraer el árbol como si realmente estuviera organizado en directorios. Pero me gusta que sea muy explícito acerca de dónde viene todo el código, y no usa ninguna ''magia''.


Hay una sección realmente interesante en el Manual de Browserify :

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

No todo lo que se incluye en una aplicación pertenece al npm público y la sobrecarga de la configuración de un repositorio privado de npm o git sigue siendo bastante grande en muchos casos. Aquí hay algunos enfoques para evitar el ../../../../../../../ problema de caminos relativos.

node_modules

Las personas a veces se oponen a colocar módulos específicos de la aplicación en node_modules porque no es obvio cómo verificar sus módulos internos sin verificar también los módulos de terceros desde npm.

¡La respuesta es bastante simple! Si tiene un archivo .gitignore que ignora node_modules :

node_modules

¡Solo puede agregar una excepción con ! para cada uno de sus módulos internos de aplicación:

node_modules/* !node_modules/foo !node_modules/bar

Tenga en cuenta que no puede ignorar un subdirectorio, si el padre ya se ha ignorado. Entonces, en lugar de ignorar node_modules , debes ignorar todos los directorios dentro de node_modules con node_modules/* trick, y luego puedes agregar tus excepciones.

Ahora, en cualquier lugar de su aplicación, podrá require(''foo'') o require(''bar'') sin tener una ruta relativa muy grande y frágil.

Si tiene muchos módulos y desea mantenerlos más separados de los módulos de terceros instalados por npm, puede ponerlos todos bajo un directorio en node_modules como node_modules/app :

node_modules/app/foo node_modules/app/bar

Ahora podrá solicitar require(''app/foo'') o require(''app/bar'') desde cualquier lugar de su aplicación.

En su .gitignore , solo agregue una excepción para node_modules/app :

node_modules/* !node_modules/app

Si su aplicación tenía transformadas configuradas en package.json, necesitará crear un paquete.json separado con su propio campo de transformación en su directorio de componentes node_modules/foo o node_modules/app/foo porque las transformaciones no se aplican a través de los límites del módulo. Esto hará que sus módulos sean más robustos frente a los cambios de configuración en su aplicación y será más fácil reutilizar los paquetes independientemente de su aplicación.

enlace simbólico

Otro truco útil si está trabajando en una aplicación en la que puede crear enlaces simbólicos y no necesita admitir ventanas es enlazar simbólicamente una lib/ o app/ carpeta a node_modules . Desde la raíz del proyecto, hazlo:

ln -s ../lib node_modules/app

y ahora, desde cualquier lugar de su proyecto, podrá solicitar archivos en lib/ haciendo require(''app/foo.js'') para obtener lib/foo.js

rutas personalizadas

Es posible que vea algunos lugares hablar sobre el uso de la variable de entorno $NODE_PATH o opts.paths para agregar directorios para node y browserify para buscar módulos.

A diferencia de la mayoría de las otras plataformas, el uso de una matriz de directorios de rutas estilo shell con $NODE_PATH no es tan favorable en el nodo en comparación con hacer un uso efectivo del directorio node_modules .

Esto se debe a que su aplicación está más estrechamente acoplada a una configuración de entorno de tiempo de ejecución, por lo que hay más partes móviles y su aplicación solo funcionará cuando su entorno esté configurado correctamente.

node y browserify admiten pero desalientan el uso de $NODE_PATH .


He probado muchas de estas soluciones. Terminé añadiendo esto a la parte superior de mi archivo principal (por ejemplo, index.js):

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

Esto agrega la raíz del proyecto a NODE_PATH cuando se carga la secuencia de comandos. Esto me permite solicitar cualquier archivo en mi proyecto al hacer referencia a su ruta relativa desde la raíz del proyecto, como var User = require(''models/user'') . Esta solución debería funcionar siempre que ejecute un script principal en la raíz del proyecto antes de ejecutar cualquier otra cosa en su proyecto.


La forma más fácil de lograr esto es mediante la creación de un enlace simbólico al inicio de la aplicación en node_modules/app (o como se llame) que apunta a ../app . A continuación, puede llamar require("app/my/module") . Los enlaces simbólicos están disponibles en todas las plataformas principales.

Sin embargo, aún debe dividir sus cosas en módulos más pequeños y fáciles de mantener que se instalan a través de npm. También puede instalar sus módulos privados a través de git-url, por lo que no hay ninguna razón para tener un directorio de aplicaciones monolítico.


Lo que me gusta hacer es aprovechar cómo se carga el nodo desde el directorio node_module para esto.

Si uno intenta cargar el módulo "cosa", uno haría algo como

require(''thing'');

Nodo buscará el directorio ''thing'' en el directorio ''node_module''.

Como node_module normalmente está en la raíz del proyecto, podemos aprovechar esta coherencia. (Si node_module no está en la raíz, entonces tienes otros dolores de cabeza autoinducidos para tratar).

Si entramos en el directorio y luego nos alejamos de él, podemos obtener una ruta consistente hacia la raíz del proyecto del nodo.

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

Entonces, si queremos acceder al directorio / happy, haríamos esto.

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

Aunque es bastante hacky, sin embargo, creo que si la funcionalidad de cómo carga la carga de node_modules, habrá problemas más grandes con los que lidiar. Este comportamiento debe permanecer constante.

Para aclarar las cosas, hago esto, porque el nombre del módulo no importa.

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

Lo utilicé recientemente para angular2. Quiero cargar un servicio desde la raíz.

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


Me gusta crear una nueva carpeta node_modules para el código compartido, luego dejo que node y haga lo que mejor hace.

por ejemplo:

- 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 ejemplo, si estás en car/index.js puedes require(''helper'') y el nodo lo encontrará!

Cómo funcionan los node_modules

nodo tiene un algoritmo inteligente para resolver módulos que es único entre las plataformas rivales.

Si require(''./foo.js'') desde /beep/boop/bar.js , el nodo buscará ./foo.js en /beep/boop/foo.js . Las rutas que comienzan con ./ o ../ son siempre locales al archivo que requiere require() .

Sin embargo, si necesita un nombre que no sea relativo, como require(''xyz'') desde /beep/boop/foo.js , el nodo busca estas rutas en orden, deteniéndose en la primera coincidencia y provocando un error si no se encuentra nada:

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

Para cada directorio xyz que exista, el nodo primero buscará un xyz/package.json para ver si existe un campo "main" . El campo "main" define qué archivo debe hacerse cargo si require() la ruta del directorio.

Por ejemplo, si /beep/node_modules/xyz es la primera coincidencia y /beep/node_modules/xyz/package.json tiene:

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

entonces las exportaciones de / /beep/node_modules/xyz/lib/abc.js serán devueltas por require(''xyz'') .

Si no hay package.json o ningún campo "main" , se supone index.js :

/beep/node_modules/xyz/index.js


Podrías definir algo como esto en tu app.js:

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

y luego, en cualquier momento que desee requerir algo desde la raíz, sin importar dónde se encuentre, solo debe usar requireFromRoot en lugar del requerido. Funciona muy bien para mí hasta ahora.


Podrías usar un módulo que hice, Undot . No es nada avanzado, solo un ayudante para que puedas evitar esos infiernos con simplicidad.

Ejemplo:

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


Si alguien está buscando otra forma de evitar este problema, aquí está mi propia contribución al esfuerzo:

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

La idea básica: usted crea un archivo JSON en la raíz del proyecto que asigna sus rutas de archivo a nombres abreviados (u obtenga use-automapper para que lo haga por usted). Luego puede solicitar sus archivos / módulos usando esos nombres. Al igual que:

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

Entonces hay eso.


Si bien estas respuestas funcionan , no abordan el problema con la prueba de npm

Si, por ejemplo, creo una variable global en server.js, no se configurará para la ejecución de mi suite de pruebas.

Para establecer una variable appRoot global que evitará el problema ../../../ y estará disponible tanto en el inicio npm como en la prueba npm, consulte:

Pruebas de Mocha con opciones adicionales o parámetros

Tenga en cuenta que esta es la nueva solución oficial de mocha .


Si el archivo js del punto de entrada de su aplicación (es decir, el que realmente ejecuta "node") está en el directorio raíz de su proyecto, puede hacerlo fácilmente con el módulo rootpath npm . Simplemente instálalo a través de

npm install --save rootpath

... luego, en la parte superior del archivo js del punto de entrada, agregue:

require(''rootpath'')();

A partir de ese momento, todas las llamadas requeridas ahora están relacionadas con la raíz del proyecto, por ejemplo, require(''../../../config/debugging/log''); se convierte en require(''config/debugging/log''); (donde la carpeta de configuración está en la raíz del proyecto).


Suponiendo que su raíz de proyecto es el directorio de trabajo actual, esto debería funcionar:

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


Y que hay con:

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

Requiere el archivo como si fuera requerido desde el archivo js principal, por lo que funciona bastante bien siempre y cuando el archivo js principal esté en la raíz de su proyecto ... y eso es algo que aprecio.


Yo uso process.cwd() en mis proyectos. Por ejemplo:

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

Vale la pena señalar que esto dará como resultado la require de un camino absoluto, aunque todavía tengo que tener problemas con esto.


Another answer :

Imagine this folders structure :

  • node_modules
    • lodash
  • src
    • subdir
      • foo.js
      • bar.js
    • main.js
  • tests

    • test.js

Then in test.js , you need to require files like this :

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

and in main.js :

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

Now you can use babel and the babel-plugin-module-resolver with this . babelrc file to configure 2 root folders:

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

Now you can require files in the same manner in tests and in src :

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

and if you want use the es6 module syntax:

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

entonces importas archivos en pruebas y src así:

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


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.


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..


Try using asapp:

npm install --save asapp

https://www.npmjs.com/package/asapp

var { controller, helper, middleware, route, schema, model, APP, ROOT } = require(''asapp'')

controller(''home'') instead require(''../../controllers/home)