Cómo escribir un módulo que funcione con Node.js, RequireJS y sin ellos
Estoy trabajando en una biblioteca de JavaScript paraProcesamiento JSON / XML. Mi biblioteca funciona tanto en el navegador como en Node.js (conxmldom
yxmlhttprequest
módulos).
Uno de los usuarios solicitó recientemente el soporte de RequireJS. He echado un vistazo a la cosa RequireJS / AMD y creo que es un buen enfoque, así que me gustaría proporcionar esto.
Sin embargo, me gustaría conservar la portabilidad: mi biblioteca debe funcionar en navegadores (con y sin RequireJS) así como en Node.js. Y en el entorno del navegador no dependo dexmldom
oxmlhttprequest
ya que estas cosas son proporcionadas por el navegador mismo.
Mi pregunta es: ¿cómo puedo implementar mi biblioteca para que funcione tanto en los navegadores como en Node.js con y sin RequireJS?
Un poco de historia y mi solución actual
Inicialmente escribí mi biblioteca para navegadores. Por lo tanto, acaba de crear un objeto de alcance global y poner todo dentro de él:
var Jsonix = { ... };
Más tarde, los usuarios solicitaron el soporte de Node.js. Entonces agregué:
if(typeof require === 'function'){
module.exports.Jsonix = Jsonix;
}
También tuve que importar algunos módulos mencionados anteriormente. Lo hice condicionalmente, dependiendo de si elrequire
la función está disponible o no:
if (typeof require === 'function')
{
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
return new XMLHttpRequest();
}
Ahora hay esta historia con RequireJS. Si RequireJS está presente, entonces elrequire
La función también está presente. Pero la carga del módulo funciona de manera diferente, tengo que usar eldefine
función, etc. Tampoco puedo simplementerequire
cosas desderequire
tiene una API asíncrona en RequireJS. Además, si mi biblioteca se carga a través de RequireJS, parece procesar el código fuente y detectarequire('something')
incluso si lo hago condicionalmente como
if (typeof require === 'function' && typeof require.specified !== 'function) ...
RequireJS todavía detectarequire('xmlhttprequest')
An intenta cargar el archivo JS correspondiente.
Actualmente estoy llegando a la siguiente solución.
// Module factory function, AMD style
var _jsonix = function(_jsonix_xmldom, _jsonix_xmlhttprequest, _jsonix_fs)
{
// Complete Jsonix script is included below
var Jsonix = { ... };
// Complete Jsonix script is included above
return { Jsonix: Jsonix };
};
// If require function exists ...
if (typeof require === 'function') {
// ... but define function does not exists, assume we're in the Node.js environment
// In this case, load the define function via amdefine
if (typeof define !== 'function') {
var define = require('amdefine')(module);
define(["xmldom", "xmlhttprequest", "fs"], _jsonix);
}
else {
// Otherwise assume we're in the RequireJS environment
define([], _jsonix);
}
}
// Since require function does not exists,
// assume we're neither in Node.js nor in RequireJS environment
// This is probably a browser environment
else
{
// Call the module factory directly
var Jsonix = _jsonix();
}
Y así es como verifico las dependencias ahora:
if (typeof _jsonix_xmlhttprequest !== 'undefined')
{
var XMLHttpRequest = _jsonix_xmlhttprequest.XMLHttpRequest;
return new XMLHttpRequest();
}
Si tengorequire
pero nodefine
entonces supongo que este es un entorno Node.js. yo sueloamdefine
para definir el módulo y pasar las dependencias requeridas.
Si tengorequire
ydefine
supongo que este es un entorno RequireJS, así que solo uso eldefine
función. Actualmente también supongo que este es un entorno de navegador, por lo que dependencias comoxmldom
yxmlhttprequest
no están disponibles y no los requieren. (Esto probablemente no sea correcto).
Si no tengo elrequire
funciono, entonces supongo que este es un entorno de navegador sin el soporte de RequireJS / AMD, así que invoco la fábrica de módulos_jsonix
directamente y exportar el resultado como un objeto global.
Entonces, este es mi enfoque hasta ahora. Me parece un poco incómodo y, como novato en RequireJS / AMD, estoy buscando asesoramiento. ¿Es el enfoque correcto? ¿Hay mejores formas de abordar el problema? Agradecería tu ayuda.