2012-06-11 10 views
37

Ci piace RequireJS e AMD durante lo sviluppo, dove possiamo modificare un modulo, premere ricarica nel nostro browser e vedere immediatamente il risultato. Ma quando arriva il momento di concatenare i nostri moduli in un unico file per la distribuzione di produzione, ci deve evidentemente essere un caricatore AMD ancora presente, sia che caricatore è RequireJS stesso o il suo più piccolo partner “mandorla”, come spiegato qui:Perché i moduli concatenati di RequireJS AMD richiedono un caricatore?

http://requirejs.org/docs/faq-optimization.html#wrap

La mia confusione è: perché è necessario un caricatore? A meno che non si abbiano circostanze insolite che rendono necessario effettuare chiamate require() all'interno dei moduli, sembrerebbe che una serie di moduli AMD possa essere concatenata senza alcun caricatore presente. L'esempio più semplice possibile sarebbe una coppia di moduli come il seguente.

ModA.js:

define([], function() { 
    return {a: 1}; 
}); 

ModB.js:

define(['ModA'], function(A) { 
    return {b : 2}; 
}); 

Attribuite questi due moduli, sembra che una concatenazione potrebbe semplicemente produrre il testo riportato di seguito, e non appesantire il server di produzione o di browser con larghezza di banda o calcolo extra richiesta da RequireJS o Almond.

immagino una concatenazione che produce (e sto usando chevron virgolette «» per mostrare dove i frammenti dei due moduli di cui sopra sono stati inseriti):

Questo, per quanto posso vedere, riprodurrebbe correttamente la semantica di AMD, con un minimo di colla estranea JavaScript. C'è un tale concatenatore disponibile? In caso contrario, sarei un pazzo a pensare che dovrei scriverne uno? Ci sono davvero poche basi di codice che consistono in moduli semplici e puliti scritti con define() e che non necessitino mai di ulteriori chiamate require() all'interno di questo kick-off in seguito a fasci di codice asincroni?

+1

Come hai risolto questo problema? Ho scoperto che usando almond, il file min è più grande di 3k quindi il file concatenato (9K vs 6K). – Naor

risposta

14

Un ottimizzatore AMD ha lo scopo di ottimizzare più del numero di file da scaricare, ma può anche ottimizzare il numero di moduli caricati in memoria.

Ad esempio, se si dispone di 10 moduli e possono essere ottimizzati su 1 file, è stato salvato 9 download.

Se Page 1 utilizza tutti e 10 i moduli, allora è fantastico. Ma cosa succede se Page 2 utilizza solo 1? Un caricatore AMD può ritardare l'esecuzione della "funzione fabbrica" ​​finché un modulo non è require "d. Pertanto, Pagina2 attiva solo una singola "funzione di fabbrica" ​​da eseguire.

Se ogni modulo consuma 100kb di memoria su require 'd, quindi un framework AMD con ottimizzazione runtime ci salverà anche 900kb di memoria su Page2.

Un esempio di questo potrebbe essere una finestra di dialogo di stile "Informazioni sul box". Dove l'esecuzione stessa è ritardata fino all'ultimo secondo in quanto non sarà accessibile nel 99% dei casi. Per esempio. (Nella sintassi sciolti jQuery):

aboutBoxBtn.click(function() { 
    require(['aboutBox'], function (aboutBox) { 
     aboutBox.show(); 
    } 
}); 

Si salva la spesa di creazione degli oggetti JS e DOM associato con il 'About Box' fino a quando si è sicuri che sia necessario.

Per ulteriori informazioni, vedere Delay executing defines until first require per assumere requirejs su questo.

+1

Interessante! Quindi, se capisco quello che stai dicendo, stai postando codice che crea oggetti e modifica il DOM * semplicemente come un effetto collaterale dell'essere richiesto *, è corretto? Non ci avrei pensato, e se questa pratica è comune, allora potreste aver colto le ragioni per cui i programmatori di JS amavano avere il caricatore AMD lì in produzione. Probabilmente a causa del mio background in Python, nessuno del mio codice viene mai eseguito quando importato - restituisce semplicemente un oggetto pieno di funzioni da chiamare quando i loro effetti collaterali sono finalmente necessari. –

+0

Il tuo esempio sull'uso della memoria è spesso confuso dall'overhead di I/O: per qualcosa di simile alla scatola sembra che sarebbe una vittoria da caricare prima, ma rinviare l'inizializzazione in modo da poter salvare memoria e configurazione senza un grande colpo di latenza interattivo. –

+0

@Chris, sono d'accordo con i vostri punti ma volevo solo presentare un caso per avere un caricatore AMD presente in fase di esecuzione. Potrei essere preoccupato per il troppo codice in esecuzione all'avvio, mentre potresti essere preoccupato per la latenza. A parte i casi insignificanti, non penso che esista una taglia unica per quanto riguarda le prestazioni. E non ci sarebbe un colpo di latenza nel mio esempio, dato che tutto il JS è stato caricato, ma non "eseguito". –

1

L'unico vero vantaggio è se si utilizzano i moduli tra le sezioni, quindi c'è un vantaggio per i moduli di cache in modo indipendente.

0

Nel caso in cui si compili il codice con require.js in un unico file di grandi dimensioni per la produzione, è possibile utilizzare almond.js per sostituire completamente richiedere.

Almond gestisce solo la gestione dei riferimenti del modulo e non il caricamento stesso che non è più necessario.

Fare attenzione della mandorla restrictions introduce al fine di lavorare

0

Non v'è alcun motivo per cui non ci non è il programma di compilazione, come quello che si propone.

L'ultima volta * Ho esaminato l'output dell'ottimizzatore, ha convertito i moduli in moduli con nome esplicito e quindi li ha concatenati. Si basava sulla necessità di assicurarsi che le funzioni di fabbrica venissero chiamate nell'ordine giusto e che gli oggetti modulo appropriati fossero passati in giro. Per costruire uno strumento come vuoi, devi linearizzare esplicitamente i moduli - non è impossibile, ma molto più lavoro. Questo è probabilmente il motivo per cui non è stato fatto.

Credo che ** l'ottimizzatore disponga di una funzionalità che includa automaticamente la richiesta stessa (o mandorla) nel file costruito, in modo che sia necessario disporre di un solo download. Sarebbe più grande dell'output dello strumento di creazione che si desidera, ma in caso contrario lo stesso.

Se ci fosse un tool di creazione che ha prodotto il tipo di output che stai chiedendo, avrebbe dovuto essere più attento, in caso di sincroni require, l'uso di exports invece di ritorno, e qualsiasi altro CommonJS compatibilità Caratteristiche.

* Qualche anno fa. 2010, penso.

** Ma non riesco a trovarlo adesso.

1

Avevo lo stesso bisogno, quindi ho creato un semplice "compilatore" AMD per quello scopo che fa proprio questo. Si può arrivare a https://github.com/amitayh/amd-compiler

prega di notare che ha molte caratteristiche mancanti, ma non il lavoro (almeno per me). Sentiti libero di contribuire al codice base.