not library javascript jquery module requirejs

javascript - library - Require.js está lastimando mi cerebro. Algunas preguntas fundamentales sobre la forma en que carga los scripts/módulos



requirejs 2.2 0 (2)

  1. Las rutas indican a require.js dónde buscar cuando necesita esa dependencia.

    Por ejemplo, tengo cosas configuradas así:

    "paths": { "jquery": "require_jquery" }, "shim": { "jquery-cookie" : ["jquery"], "bootstrap-tab" : ["jquery"], "bootstrap-modal": ["jquery"], "bootstrap-alert": ["jquery"] },

    esto significa que cada vez en un módulo que hago

    define( [''jquery'']

    requirejs carga el archivo require_jquery de la ruta principal en lugar de intentar cargar jquery.js. En su caso, cargaría el archivo fuente jQuery, que luego estaría disponible globalmente. Personalmente, no me gusta ese enfoque y por esa razón en el archivo require_jquery.js que hago:

    define( ["jquery_1.7.2"], function() { // Raw jQuery does not return anything, so return it explicitly here. return jQuery.noConflict( true ); } );

    lo que significa que jQuery se definirá solo dentro de mis módulos. (Esto es porque escribo plugins de Wordpress y entonces puedo incluir mi propia versión de jQuery sin tocar la versión externa)

  2. Exportaciones (la lectura de los documentos simplemente debe ser el nombre del módulo que está utilizando para que se pueda detectar si la carga fue correcta. Here se explica. Por lo tanto, si desea establecer una exportación para guión bajo, debe ser _

  3. jQuery debería ser global, como expliqué, si simplemente lo importas, el archivo se ejecuta y jQuery es global

EDITAR - para responder los comentarios.

  1. sí, quiero decir que debe exportar $ o jQuery para jQuery y _ para backbone. Según lo que obtuve de los documentos, esto solo se necesita en algunos casos extremos y no sería necesario para las bibliotecas que se declaran en el espacio de nombre global como jQuery.

    Creo que requirejs los necesita cuando tiene que retroceder al cargar jQuery desde un CDN. Creo que requirejs primero intenta cargar jQuery desde el CDN, luego verifica que se cargó correctamente comprobando que la variable "exportada" existe, y si no la carga forma el sistema de archivos local (si había configurado retrocesos, por supuesto). Esto es algo que se necesita cuando requirejs no puede ver un 404 regresar.

  2. jQuery está disponible a nivel mundial porque se declara global. Si simplemente carga y ejecuta el script jQuery, terminará con dos globales, $ y jQuery (o puede hacer lo que hice y evitar eso). Dentro de la función define() puedes alias jQuery para que sea lo que quieras.

    define( [ ''jquery'' ], function( jq ) { // jq is jquery inside this function. if you declared it // globally it will be also available as $ and jQuery } );

Supongamos que este es mi config.js o main.js:

require.config({ // paths are analogous to old-school <script> tags, in order to reference js scripts paths: { jquery: "libs/jquery-1.7.2.min", underscore: "libs/underscore-min", backbone: "libs/backbone-min", jquerymobile: "libs/jquery.mobile-1.1.0.min", jquerymobilerouter: "libs/jquery.mobile.router.min" }, // configure dependencies and export value aliases for old-school js scripts shim: { jquery: ["require"], underscore: { deps: ["jquery"], exports: "_" }, backbone: { deps: ["underscore", "jquery"], exports: "Backbone" }, jquerymobilerouter: ["jquery", "backbone", "underscore"], jquerymobile: ["jquery", "jquerymobilerouter", "backbone", "underscore"] } }); require(["jquery", "backbone", "underscore", "app/app.min", "jquerymobilerouter", "jquerymobile"], function ($, Backbone, _, App) { console.log($); console.log(Backbone); console.log(_); $("body").fadeIn(function () { App.init(); }); });

  1. Si entiendo correctamente, la opción de configuración de paths permite hacer referencia a las secuencias de comandos, a-la, la etiqueta <script> dentro de HTML. Asumiendo que este es el caso, ¿todavía necesito alias los guiones como jQuery con un $ o un guión bajo con un _ en mi declaración de requerimiento real a continuación? Parece extraño que deba hacerlo, dado que si hace referencia a jQuery con una etiqueta <script> estándar, $ se puede usar en todo el script automáticamente. ¿No debería ser lo mismo usar las paths ?

  2. Soy nuevo en la opción de configuración shim , que según tengo entendido, ¡ha reemplazado el order! desuso order! enchufar. ¿Qué hace realmente la propiedad de exports ? No parece crear un alias para un script; por ejemplo, si configuro las exports para subrayado como "whatever" y luego trato de console.log(whatever) , no está definido. ¿Entonces cuál es el punto?

  3. ¿Cómo se usarían adecuadamente los scripts como jQuery "globalmente"? Es decir, ¿cuál es la forma correcta de poder usar $ alias en mi módulo App.js o en cualquier otro módulo de mi carpeta "app"? ¿Debo exigir jQuery dentro de cada módulo individual y alias $ cada vez? ¿O es la forma en que lo hice aquí de la manera correcta?

También agradecería cualquier otra crítica de este guión en particular; la documentación para Require.js, en mi opinión, deja mucho que desear; las cosas sobre las que me gustaría saber más parecen ser ignoradas y me dejan rascándome la cabeza.


Para aclarar cualquier confusión sobre las exports , se asume que cualquier biblioteca shim asocia una propiedad al contexto global ( window o root ) o modifica una propiedad global ya existente (por ejemplo, un plugin jQuery). Cuando requireJS obtiene el comando para cargar una dependencia calzada, examina el contexto global para una propiedad que coincide con el valor de exports de esa configuración shim y, si la encuentra, la devuelve como el valor de ese módulo. Si no lo encuentra, carga el script asociado, espera a que se ejecute, luego encuentra el símbolo global y lo devuelve.

Un hecho importante para recordar es que a menos que la configuración shim contenga un valor de exports , NO se ejecutará ningún método init en esa configuración. El cargador de dependencias debe ubicar un valor para el módulo (que es lo que especifica exports ) antes de que el módulo pueda inicializarse, por lo que la propiedad es obligatoria si hay un init shim para ese módulo.

actualización: también debo señalar que si el módulo en cuestión llama a define cualquier lugar, se ignorará cualquier configuración shim que tenga para ese módulo. Esto realmente me causó algunos dolores de cabeza porque quería usar la configuración de shim para llamar al jQuery.noConflict(true) de jQuery para desagregar jQuery y mantenerlo en el alcance solo de los módulos que lo requieren, pero no pude lograr que funcionara . (Consulte la actualización en la parte inferior para obtener información sobre cómo hacer esto fácilmente usando la configuración del mapa en lugar de la configuración shim).

actualización 2: una pregunta reciente sobre el grupo requireJS google me hizo darme cuenta de que mi explicación podría ser un poco engañosa, por lo que me gustaría aclarar. RequireJS solo volverá a utilizar una dependencia calzada si se cargó mediante requireJS al menos una vez . Es decir, si simplemente tiene una etiqueta <script> en la página de alojamiento (por ejemplo, subrayado), así:

<script src=''lib/underscore.js''></script> <script src=''lib/require.js'' data-main=''main.js''></script>

... y tienes algo como esto en tu configuración de requireJS:

paths: { ''underscore'': ''lib/underscore'' }, shim: { ''underscore'': { exports: ''_'' } }

Luego, la primera vez que define([''underscore''], function (_) {}); o var _ = require(''underscore''); , RequireJS volverá a cargar la biblioteca de guiones bajos en lugar de reutilizar la window._ definida window._ , porque, por lo que se requiere, JS sabe que nunca cargó guiones bajos antes. Claro, puede verificar si _ ya está definido en el ámbito raíz, pero no tiene forma de verificar que _ que ya existe sea el mismo que el definido en la configuración de sus paths . Por ejemplo, tanto prototype como jquery asignan a window.$ De forma predeterminada, y si requireJS asume que ''window. $'' Es jQuery cuando de hecho es prototipo, vas a estar en una mala situación.

Todo eso significa que si mezclas estilos de carga de scripts de ese tipo, tu página terminará con algo como esto:

<script src=''lib/underscore.js''></script> <script src=''lib/require.js'' data-main=''main.js''></script> <script src=''lib/underscore.js''></script>

Donde la segunda instancia de subrayado es la cargada por requireJS.

Básicamente, una biblioteca tiene que ser cargada a través de requireJS para que requireJS tenga conocimiento de ella. Sin embargo, la próxima vez que necesite un guión bajo, requerirá que JS marque "hey, ya lo he cargado, así que devuelva el valor de las exports y no se preocupe por cargar otro guión".

Esto significa que tienes dos opciones reales. Uno es lo que yo consideraría un antipatrón: simplemente no use requireJS para expresar dependencias para scripts globales. Es decir, siempre que una biblioteca agregue un contexto global al raíz, podrá acceder a él, evento si esa dependencia no se requiere explícitamente. Puedes ver por qué esto es un antipatrón; básicamente has eliminado la mayoría de las ventajas de usar un cargador AMD (lista de dependencia explícita y portabilidad).

La otra, mejor opción es usar requireJS para cargar todo, en la medida en que la única etiqueta de script real que debe crear usted mismo es la que inicialmente carga requireJS. Puedes usar cuñas, pero el 95% de las veces no es tan difícil agregar un envoltorio AMD al guión. Podría tomar un poco más de trabajo convertir todas las bibliotecas que no son de AMD para que sean compatibles con AMD, pero una vez que hayas hecho una o dos se vuelve mucho más fácil: puedo tomar cualquier complemento de jQuery genérico y convertirlo a un módulo de AMD en menos de un minuto. Por lo general, solo se trata de agregar

define([''jquery''], function (jQuery) {

en la parte superior, y

return jQuery; });

en el fondo. La razón por la que tengo el mapeo ''jquery'' de jQuery lugar de $ es que he notado que la mayoría de los complementos en estos días están envueltos en un cierre como este:

(function ($) { // plugin code here })(jQuery);

Y es una buena idea prestar atención al alcance previsto. Sin embargo, puede asignar "jquery" a $ directamente, suponiendo que el complemento no espera encontrar jQuery lugar de $ . Esa es solo la envoltura básica de AMD: las más complejas generalmente intentan detectar qué tipo de cargador se está utilizando (commonJS vs AMD frente a los ol ''globals normales) y usan un método de carga diferente según el resultado. Puedes encontrar ejemplos de esto con bastante facilidad con unos segundos en google.

Actualización: la solución alternativa que utilicé para usar jQuery.noConflict(true) con RequireJS funcionó, pero requirió una pequeña modificación en la fuente jQuery, y desde entonces he descubierto una forma mucho mejor de lograr lo mismo sin modificar jQuery. Afortunadamente, también lo ha hecho James Burke, el autor de RequireJS, quien lo ha agregado a la documentación RequireJS: http://requirejs.org/docs/jquery.html#noconflictmap