Ecco un esempio più concreto.
Sto lavorando a un progetto con 60 file. Abbiamo 2 diverse modalità di esecuzione.
Carica una versione concatenata, 1 file di grandi dimensioni. (Produzione)
Carica tutti i 60 file (sviluppo)
Stiamo usando un caricatore, quindi abbiamo solo uno script nella pagina web
<script src="loader.js"></script>
L'impostazione predefinita è la modalità n. 1 (caricamento di un file concatenato di grandi dimensioni). Per eseguire la modalità in # 2 (file separati) impostiamo alcuni flag. Potrebbe essere qualsiasi cosa. Una chiave nella stringa di query. In questo esempio lo facciamo e basta
<script>useDebugVersion = true;</script>
<script src="loader.js"></script>
loader.js è simile a questo
if (useDebugVersion) {
injectScript("app.js");
injectScript("somelib.js");
injectScript("someotherlib.js");
injectScript("anotherlib.js");
... repeat for 60 files ...
} else {
injectScript("large-concatinated.js");
}
Lo script di compilazione è solo un file .sh che assomiglia a questo
cat > large-concantinated.js app.js somelib.js someotherlib.js anotherlib.js
eccetera...
Se viene aggiunto un nuovo file, probabilmente useremo la modalità # 2 poiché stiamo facendo lo sviluppo, dobbiamo aggiungere una injectScript("somenewfile.js")
riga a loader.js
Successivamente, per la produzione, dobbiamo anche aggiungere somenewfile.js al nostro script di build. Un passaggio che spesso dimentichiamo e quindi riceviamo messaggi di errore.
Passando ad AMD non è necessario modificare 2 file. Il problema di mantenere sincronizzati loader.js e lo script di compilazione scompare. Utilizzando r.js
o webpack
si può semplicemente leggere il codice per crearelarge-concantinated.js
Può anche gestire le dipendenze, ad esempio abbiamo caricato 2 file lib1.js e lib2.js in questo modo
injectScript("lib1.js");
injectScript("lib2.js");
lib2 ha bisogno di lib1. Ha un codice all'interno che fa qualcosa di simile
lib1Api.installPlugin(...);
Ma poiché gli script iniettati vengono caricati in modo asincrono, non vi è alcuna garanzia che vengano caricati nell'ordine corretto. Questi 2 script non sono script AMD, ma utilizzando Requis.js possiamo dirgli le loro dipendenze
require.config({
paths: {
lib1: './path/to/lib1',
lib2: './path/to/lib2',
},
shim: {
lib1: {
"exports": 'lib1Api',
},
lib2: {
"deps": ["lib1"],
},
}
});
Nel nostro modulo che usa lib1 lo facciamo
define(['lib1'], function(lib1Api) {
lib1Api.doSomething(...);
});
Ora request.js inietterà gli script per noi e non inietterà lib2 fino a quando non sarà caricato lib1 poiché gli abbiamo detto che lib2 dipende da lib1. Inoltre non avvierà il nostro modulo che utilizza lib1 fino a quando non sono stati caricati sia lib2 che lib1.
Questo rende piacevole lo sviluppo (nessuna fase di compilazione, nessuna preoccupazione per l'ordine di caricamento) e rende piacevole la produzione (non è necessario aggiornare uno script di compilazione per ogni script aggiunto).
Come bonus aggiuntivo possiamo usare il plug-in babel di webpack per eseguire babel sul codice per i browser più vecchi e anche in questo caso non è necessario mantenere lo script di build.
Se Chrome (il nostro browser preferito) inizia a supportare import
davvero, probabilmente passeremmo a quello per lo sviluppo, ma ciò non cambierebbe nulla. Potremmo ancora usare il webpack per creare un file concatenato e potremmo usarlo eseguendo babel sul codice per tutti i browser.
Tutto ciò si ottiene non usando i tag di script e usando AMD