Aquí hay un ejemplo más concreto.
Estoy trabajando en un proyecto con 60 archivos. Tenemos 2 modos diferentes de ejecutarlo.
Cargue una versión concatenada, 1 archivo grande. (Producción)
Cargue los 60 archivos (desarrollo)
Estamos usando un cargador, así que solo tenemos un script en la página web
<script src="loader.js"></script>
El valor predeterminado es el modo n. ° 1 (cargar el archivo concatenado grande). Para ejecutar el modo in # 2 (archivos separados) configuramos alguna bandera. Podría ser cualquier cosa. Una clave en la cadena de consulta. En este ejemplo solo hacemos esto
<script>useDebugVersion = true;</script>
<script src="loader.js"></script>
loader.js se parece a esto
if (useDebugVersion) {
injectScript("app.js");
injectScript("somelib.js");
injectScript("someotherlib.js");
injectScript("anotherlib.js");
... repeat for 60 files ...
} else {
injectScript("large-concatinated.js");
}
El script de compilación es solo un archivo .sh que se ve así
cat > large-concantinated.js app.js somelib.js someotherlib.js anotherlib.js
etc ...
Si se agrega un nuevo archivo, probablemente injectScript("somenewfile.js")
usaremos el modo n. ° 2, ya que estamos desarrollando, tenemos que agregar una línea a loader.js
Luego, para la producción, también tenemos que agregar somenewfile.js a nuestro script de compilación. Un paso que a menudo olvidamos y luego recibimos mensajes de error.
Al cambiar a AMD no tenemos que editar 2 archivos. El problema de mantener loader.js y el script de compilación sincronizado desaparece. Usando r.js
o webpack
simplemente puede leer el código para construirlarge-concantinated.js
También puede tratar dependencias, por ejemplo, teníamos 2 archivos lib1.js y lib2.js cargados así
injectScript("lib1.js");
injectScript("lib2.js");
lib2 necesita lib1. Tiene código dentro que hace algo como
lib1Api.installPlugin(...);
Pero como los scripts inyectados se cargan de forma asincrónica, no hay garantía de que se carguen en el orden correcto. Estas 2 secuencias de comandos no son secuencias de comandos AMD, pero utilizando require.js podemos decirle sus dependencias
require.config({
paths: {
lib1: './path/to/lib1',
lib2: './path/to/lib2',
},
shim: {
lib1: {
"exports": 'lib1Api',
},
lib2: {
"deps": ["lib1"],
},
}
});
Yo nuestro módulo que usa lib1 hacemos esto
define(['lib1'], function(lib1Api) {
lib1Api.doSomething(...);
});
Ahora require.js inyectará los scripts por nosotros y no inyectará lib2 hasta que lib1 se haya cargado, ya que dijimos que lib2 depende de lib1. Tampoco iniciará nuestro módulo que usa lib1 hasta que se hayan cargado lib2 y lib1.
Esto hace que el desarrollo sea agradable (sin paso de compilación, sin preocuparse por el orden de carga) y hace que la producción sea agradable (no es necesario actualizar un script de compilación para cada script agregado).
Como beneficio adicional, podemos usar el complemento babel de webpack para ejecutar babel sobre el código de los navegadores más antiguos y, de nuevo, tampoco tenemos que mantener ese script de compilación.
Tenga en cuenta que si Chrome (nuestro navegador de elección) comenzó a admitirlo import
de verdad, probablemente cambiaríamos a eso para el desarrollo, pero eso realmente no cambiaría nada. Todavía podríamos usar webpack para hacer un archivo concatenado y podríamos usarlo para ejecutar babel sobre el código para todos los navegadores.
Todo esto se obtiene al no usar etiquetas de script y usar AMD