Hay algunas bibliotecas de Javascript de terceros que tienen alguna funcionalidad que me gustaría usar en un servidor Node.js. (Específicamente, quiero usar una biblioteca de JavaScript QuadTree que encontré). Pero estas bibliotecas son simplemente .js
archivos sencillos y no "bibliotecas de Node.js".
Como tal, estas bibliotecas no siguen la exports.var_name
sintaxis que Node.js espera para sus módulos. Por lo que tengo entendido, eso significa que cuando lo haga module = require('module_name');
o module = require('./path/to/file.js');
terminará con un módulo sin funciones de acceso público, etc.
Entonces, mi pregunta es "¿Cómo cargo un archivo javascript arbitrario en Node.js de modo que pueda utilizar su funcionalidad sin tener que reescribirlo para que funcione exports
?"
Soy muy nuevo en Node.js, así que avíseme si hay algún vacío evidente en mi comprensión de cómo funciona.
EDITAR : Investigando más cosas y ahora veo que el patrón de carga del módulo que usa Node.js es en realidad parte de un estándar desarrollado recientemente para cargar bibliotecas de Javascript llamado CommonJS . Dice esto directamente en la página del documento del módulo para Node.js , pero me lo perdí hasta ahora.
Puede terminar siendo que la respuesta a mi pregunta sea "espere hasta que los autores de su biblioteca comiencen a escribir una interfaz CommonJS o hágalo usted mismo".
fuente
Respuestas:
Hay un método mucho mejor que usar
eval
: elvm
módulo.Por ejemplo, aquí está mi
execfile
módulo, que evalúa la secuencia de comandos enpath
en cualquieracontext
o en el contexto global:Y se puede usar así:
Donde
example.js
contiene:La gran ventaja de este método es que tiene un control completo sobre las variables globales en el script ejecutado: puede pasar globales personalizados (vía
context
), y se agregarán todos los globales creados por el scriptcontext
. La depuración también es más fácil porque los errores de sintaxis y similares se informarán con el nombre de archivo correcto.fuente
runInNewContext
Utiliza el contexto global sicontext
(de lo contrariosandbox
, en los documentos) no está definido? (este punto no quedó claro en ningún documento que encontré)vm
ofrecer el módulo en este caso?Esta es la que creo que es la respuesta 'más correcta' para esta situación.
Supongamos que tiene un archivo de script llamado
quadtree.js
.Debería crear una personalizada
node_module
que tenga este tipo de estructura de directorios ...Todo en su
./node_modules/quadtree/quadtree-lib/
directorio son archivos de su biblioteca de terceros.Luego, su
./node_modules/quadtree/index.js
archivo simplemente cargará esa biblioteca desde el sistema de archivos y hará el trabajo de exportar las cosas correctamente.Ahora puede usar su
quadtree
módulo como cualquier otro módulo de nodo ...Me gusta este método porque no es necesario cambiar el código fuente de su biblioteca de terceros, por lo que es más fácil de mantener. Todo lo que necesita hacer en la actualización es mirar su código fuente y asegurarse de que todavía está exportando los objetos adecuados.
fuente
npm link
en su aplicación. Luego se maneja como si fuera un paquete nativo de Node.js.La forma más sencilla es:
eval(require('fs').readFileSync('./path/to/file.js', 'utf8'));
Esto funciona muy bien para realizar pruebas en el shell interactivo.fuente
AFAIK, así es como se deben cargar los módulos. Sin embargo, en lugar de agregar todas las funciones exportadas al
exports
objeto, también puede agregarlasthis
(lo que de otro modo sería el objeto global).Entonces, si desea mantener las otras bibliotecas compatibles, puede hacer esto:
o, cuando la biblioteca externa ya tiene su propio espacio de nombres, por ejemplo
jQuery
(no es que pueda usar eso en un entorno del lado del servidor):En un entorno sin nodo,
this
se resolvería en el objeto global, convirtiéndolo en una variable global ... que ya lo era. Entonces no debería romper nada.Editar : James Herdman tiene un buen artículo sobre node.js para principiantes, que también menciona esto.
fuente
No estoy seguro de si realmente terminaré usando esto porque es una solución bastante hacky, pero una forma de evitar esto es construir un pequeño importador de mini-módulos como este ...
En el archivo
./node_modules/vanilla.js
:Luego, cuando desee utilizar la funcionalidad de su biblioteca, deberá elegir manualmente qué nombres exportar.
Entonces, para una biblioteca como el archivo
./lib/mylibrary.js
...Cuando desee utilizar su funcionalidad en su código Node.js ...
Sin embargo, no sé qué tan bien funcionaría todo esto en la práctica.
fuente
Pude hacer que funcionara actualizando su script, muy fácilmente, simplemente agregando
module.exports =
cuando fuera apropiado ...Por ejemplo, tomé su archivo y lo copié en './libs/apprise.js'. Entonces, donde comienza con
Asigné la función
module.exports =
así:Por lo tanto, puedo importar la biblioteca a mi código de esta manera:
Y estaba listo para irme. YMMV, esto fue con webpack .
fuente
Una
include(filename)
función simple con mejores mensajes de error (pila, nombre de archivo, etc.) paraeval
, en caso de errores:Pero incluso se vuelve más sucio con nodejs: debe especificar esto:
De lo contrario, no podrá utilizar variables globales en archivos incluidos con
include(...)
.fuente