¿Cómo modularizar y empaquetar una biblioteca Javascript del lado del cliente hoy?

11

Me he puesto al día con el ecosistema JS moderno del lado del cliente y he leído CommonJS y AMD (incluidas las herramientas asociadas: browserify, requirejs, onejs, jam, docenas de otras). Si estoy escribiendo una biblioteca Javascript, ¿cómo la modularizo / empaqueto de modo que pueda ser accesible de manera más amplia (idealmente por usuarios que confían en CommonJS, AMD y especialmente ninguno)?

Las bibliotecas populares como jQuery parecen usar la concatenación de archivos de la vieja escuela para construirse y detectar dinámicamente si debe escribir en un exportscontexto global o en otro. Actualmente estoy haciendo lo mismo, pero la desventaja principal es que si (a diferencia de jQuery) dependo de algunas bibliotecas, es bueno no tener que pedirles a los usuarios que incluyan manualmente el conjunto transitivo. (Aunque actualmente solo tengo dos dependencias). Y, por supuesto, la contaminación del espacio de nombres global.

¿O tal vez es más limpio generar múltiples versiones de mi biblioteca, para cada contexto?

También me pregunto sobre empaque y publicación. Hay varios sistemas, pero creo que el principal es Bower, que es fácil de manejar ya que todo lo que hace es buscar. Sin embargo, me pregunto si también debería apuntar a otros sistemas de paquetes como el componente (que requiere CommonJS).

¿Hay otros aspectos relevantes que debería tener en cuenta? ¿Hay algún buen proyecto de ejemplo a seguir para todo esto?

Yang
fuente
Este es un tutorial increíble: youtube.com/watch?v=USk1ie30z5k El chico menciona requirejs (r.js), nodo, bower, backbone, ...
@MattFenwick He usado todas las herramientas mencionadas; El video no responde ninguna de mis preguntas.
Yang
¿Lo has visto? Me parece recordar al tipo que nos guiaba por una biblioteca y explicaba las líneas específicas de código que lo hacían funcionar con sistemas de módulos múltiples sin requerir ninguno de ellos.

Respuestas:

2

Siempre solía usar archivos de compilación, pero desde que comencé mi primer proyecto nodejs comencé a usar browserify . Con Browerify y otras bibliotecas similares, su código es su archivo de compilación. Estoy aprovechando una biblioteca de cliente y servidor que puede ejecutarse en ambos, pero también puede funcionar con código puramente de cliente. En resumen, browserify le brinda todos los beneficios de escribir código en el nodo (no hay funciones anon para evitar globales, npm, simples requisitos) y le permite empaquetar ese código para que se ejecute en el cliente con un comando y solo cargue un archivo.

Con browserify puedes hacer algo como (llamado app.js):

var MyLib = require('../myLib');

if(typeof window !== 'undefined') {
    window.MyLib = MyLib;
    window._ = require('underscore');
    window.$ = require('$');
    window.MyLib.myCan = require('./3rdParty/can/can');
}

browserify app.js> client.js

Produciría algo como:

[function(require,module,exports){
    window.MyLib = //MyLib code
},
function(require,module,exports){
     window._ = //_ code
},
function(require,module,exports){
    window.$ = //$ code
},
function(require,module,exports){
    window.MyLib.myCan = //can code
}

El archivo que definiría podría incluir todas sus librerías de terceros y no entrar en conflicto con ninguno de sus desarrolladores que lo usan.

--Edite en responder al comentario (y una falla completa en la pregunta)

Supongo que eso dependerá de sus dependencias y de cuánto tiempo desee pasar asegurándose de que funcionen en todas las versiones y bibliotecas. Si sus dependencias son comunes y siguen la misma API de una versión a otra, puede seguir la ruta Backbone y solo requerir que el usuario tenga $ y _. Sugeriría poner las librerías más oscuras como parte del archivo incluido. Las opciones tampoco tienen que ser cortadas y secas. Puede ofrecer un paquete precompilado o construir su propio paquete.

por favor
fuente
+1 para browserify, más personas necesitan saber sobre esa herramienta
Benjamin Gruenbaum
@BenjaminGruenbaum Es una herramienta realmente genial. Soy muy afortunado de haberlo revisado nuevamente. Inicialmente lo ignoré porque solía cargar los archivos de forma asíncrona, lo que podría desencadenar N # de cargas de archivos en el navegador. Ahora solo hay uno y los mapas de origen se pueden habilitar.
favor
1
Mira, aquí está el problema: estoy preguntando cómo publicar una biblioteca. De hecho, sé acerca de los sistemas basados ​​en Commonify de browserify / onejs / otros, pero si empiezo a usar require()mi código, eso significa que ya no será accesible para los usuarios a menos que ellos también cambien sus propios proyectos para usar CommonJS. Si lanzo un script compilado, entonces incluirá potencialmente incluir dependencias redundantes con sus propios proyectos y potencialmente hinchar enormemente el entregable (por ejemplo, jquery múltiple).
Yang
0

Tipos de bibliotecas del lado del cliente:

  1. Toca DOM
  2. No toca DOM

Con el primer tipo (widgets de UI, etc.), normalmente asumirá que jQuery está presente. También puede escribir "agnóstico de biblioteca DOM" y hacer que funcione con los menos populares también, pero no me molesto.

Con el segundo tipo. En primer lugar, no lo convierta en un complemento jQuery, por ejemplo, el "complemento de cookies jQuery" es ridículo, pero en realidad existe una biblioteca de este tipo.

Es posible que estos dos tipos no tengan dependencias, dependencias pequeñas o dependencias enormes, con una biblioteca dom que no cuenta como dependencia en este sentido. Con los primeros 2, simplemente los concatenará dentro del alcance de su biblioteca y no se preocupará por la posible duplicación. Por ejemplo, jQuery concatena una isArrayLikefunción interna , a pesar de que el usuario puede tener la suya ya incluida en alguna biblioteca de cinturón de utilidad aleatoria.

Solo tengo una experiencia personal con una gran dependencia al desarrollar una biblioteca (en realidad un lenguaje) - moment.js. En este caso, proporcionaría 2 compilaciones, una con moment.js concatenada y otra sin, donde el usuario es responsable de incluirla. Sin embargo, no sé si esta es una buena solución.

Y sí, en todos los casos, se toma el enfoque jQuery de construir un archivo grande final que simplemente funcione. Tiene el módulo repetitivo en la parte inferior (requiere detección / AMD / global, etc.).

Esailija
fuente