2011-12-22 11 views
14

Sto costruendo la mia prima applicazione JavaScript di grandi dimensioni (senza spaghetti). Mentre l'introduzione di RequireJS e di altri framework di gestione delle dipendenze per JavaScript semplifica la divisione dei file, Non sono chiaro su come spingere un codice di grandi dimensioni per la produzione. Quello che vorrei è un modo per aggregare e minimizzare/uglify i miei JavaScript per la produzione, usando qualcosa come Ready.js e UglifyJS. O qualche altro approccio, se ha senso.Come strutturare le applicazioni JavaScript in fase di sviluppo e produzione

In che modo gli sviluppatori con applicazioni JavaScript di grandi dimensioni in produzione gestiscono la loro struttura nello sviluppo e nella produzione?

Potrei, ad esempio, utilizzare RequireJS in fase di sviluppo e quindi utilizzare Ready/Uglify per aggregare/ridimensionare. Ma poi il mio codice sarebbe stato inutile require()'s sparsi ovunque. Sono sicuro che c'è un approccio migliore.

Sono anche confuso sull'inclusione di jQuery in questi file. Devo eseguire il wrapping di ogni singolo file jQuery (ad esempio le viste Backbone che utilizzano jQuery) all'interno del proprio file separato $(document).ready(function(){...})? Sembra molto poco umido.

+2

+1 per l'ammissione di javascript non spaghetti per la prima volta. Per molti sviluppatori vivono negando troppo a lungo :) –

risposta

2

È possibile utilizzare RequireJS optimizer. Le richieste non sono inutili, nemmeno nell'applicazione compressa, perché devi sempre ottenere un riferimento al modulo. La documentazione ottimizzatore anche dire, che non includerà un modulo che è stato caricato con una variabile come

var mods = someCondition ? ['a', 'b'], ['c', 'd']; 
require(mods); 

Penso che RequireJS dovremmo aspettare fino al DOM è pronto e tutti i moduli sono stati caricati, in modo da non è necessario avvolgere tutti i file.

Detto questo, il mio gestore di pacchetti preferito è ancora StealJS. Può lanciare chiamate non necessarie in una build di produzione e un modulo è sempre incapsulato in una chiusura che ottiene l'oggetto jQuery passato e attende fino a quando il DOM è pronto e tutti gli script sono stati caricati. Sfortunatamente non è ancora compatibile con le specifiche del modulo CommonJS.

modo
+0

Questo è fantastico. StealJS sembra carino, ma mi piace di più di ciò che RequireJS può fare. Mi piacerebbe sapere di più sul tuo intero processo di costruzione, se non ti dispiace condividere. In quale fase della distribuzione esegui il tuo ottimizzatore? Stai testando insieme ad esso? Metti alla prova il JS ottimizzato? Potrei chiedere questo in un'altra domanda, ma ho una brutta storia di quei tipi di domande sulle "migliori pratiche" che vengono chiuse. –

+0

Benché funzioni da solo, StealJS è parte del framework JavaScriptMVC (http://javascriptmvc.com/), che è quello che uso per strutturare, costruire e testare le mie applicazioni e si prende cura di tutte queste cose molto da solo (ed è l'unica soluzione completamente contenuta per JavaScript che conosco). – Daff

1

Ho trovato YUI Builder funziona bene per me. Non sono sicuro di quanto sia utile se non stai usando YUI 3, ma ci sono buone possibilità che tu possa adattarlo alle tue esigenze.

D'altra parte, hai dato un'occhiata a RequireJS Optimizer?

Riguardo alla gestione document.ready; Penso che sia una buona pratica non lasciare che il codice nei moduli faccia qualcosa finché non viene inizializzato o chiamato. Quindi avrei un singolo $(document).ready() in un tag <script> nella parte inferiore della pagina stessa, che "incolla" i moduli necessari in quella pagina.

0

Anti-spaghetti di

Sviluppare in modo efficace e facilmente mantenere un'applicazione JavaScript, al contrario di una serie di script ad hoc o di automazione entri non trasparente, è possibile utilizzare native Qooxdoo application. E 'impossibile coprire Qooxdoo senza scrivere troppo, ma in caso di applicazione nativa (da non confondere il termine con C o Java, Qooxdoo è puro JavaScript) è descritto come:

Per le applicazioni utilizzando HTML custom/GUI basate su CSS al posto del livello widget di qooxdoo.

Pertanto, tale applicazione non utilizza alcun livello di interfaccia utente Qooxdoo, ma solo strutture di struttura del codice e strumenti di creazione. Codice in Qooxdoo organizzato in classi, uno per file come in Java. Potrei assomigliare a questo:

/** 
* @use(website.library.MosaicFlow) 
*/ 
qx.Class.define('website.controller.Gallery', { 

    extend : website.controller.Abstract, 

    members : { 

    _baseUrl : 'https://picasaweb.google.com/data/feed/api', 


    _render : function(photos) 
    { 
     q('.preloader').remove(); 

     q.template.get('gallery-template', {'photos': photos}).appendTo('#gallery-container'); 
     var gallery = window.jQuery('#gallery-container .gallery').mosaicflow({ 
     'minItemWidth' : 256, 
     'itemSelector' : '.photo', 
     'autoCalculation' : false 
     }); 
     gallery.trigger('resize'); 
    }, 

    _convert : function(item, index) 
    { 
     try 
     { 
     return { 
      'url'  : item.content.src, 
      'summary' : item.summary.$t, 
      'thumb' : item.media$group.media$thumbnail[0] 
     }; 
     } 
     catch(ex) 
     { 
     this.debug('failed to convert', index, item); 
     return null; 
     } 
    }, 

    _onLoadSuccess : function(event) 
    { 
     var request = event.getTarget(); 
     var response = request.getResponse(); 
     if(!qx.lang.Type.isObject(response) || !('feed' in response)) 
     { 
     request.debug('Malformed response received'); 
     } 
     else 
     { 
     this._render(response.feed.entry.map(this._convert, this).filter(function(item) 
     { 
      return !!item; 
     })); 
     } 
    }, 

    _onLoadFail : function() 
    { 
     this.debug('Picasa search failed'); 
    }, 

    main : function() 
    { 
     var query = /^\/gallery\/(\w+)$/.exec(window.location.pathname); 
     var request = new qx.io.request.Jsonp(qx.lang.String.format('%1/all', [this._baseUrl])); 
     request.setRequestData({ 
     'q'   : query[1], 
     'thumbsize' : 300, 
     'max-results' : 20, 
     'alt'   : 'json' 
     }); 
     request.setTimeout(16000); 
     request.setCache(false); 
     request.addListener('fail', this._onLoadFail, this); 
     request.addListener('success', this._onLoadSuccess, this); 
     request.send(); 
    } 

    } 

}); 

Il modello di oggetto Qooxdoo sfrutta entrambi i mondi. In ha qualità di piattaforme mature come Java, allo stesso tempo è moderno e dinamico, fornendo classi, ereditarietà, interfacce, mixin, eventi, proprietà, data-binding e altro. Poiché ogni classe ha un nome definito e si trova in un albero dei nomi, il generatore di Qooxdoo può trarne vantaggio. Analizza le tue classi e costruisce i loro alberi di sintassi. Quindi risolve le dipendenze. Cioè quando fai riferimento a un'altra classe, ad esempio website.controller.Abstract. Ciò porta al grafico delle dipendenze, che viene utilizzato per caricare gli script nell'ordine corretto. Nota che tutto è automatico e trasparente per uno sviluppatore e che i file vengono caricati così come sono. In caso di CommonJS non è previsto alcun tipo di implementazione, non c'è nessun brutto piano di lavoro per avvolgere il codice come con AMD.

Come si può vedere nell'esempio sopra, è possibile gestire librerie esterne non qooxdoo. È sufficiente scrivere un wrapper fittizio per una libreria per includerlo nel processo di creazione.

di sviluppo e di produzione ambienti

Si sviluppa costruire la vostra applicazione (build è necessaria solo quando nuova dipendenza viene introdotto nel codice), con la cosiddetta sorgente destinazione. I file dell'applicazione vengono caricati in ordine di dipendenza, uno per uno. I file di framework possono essere caricati uno per uno, o quale è l'opzione migliore, sono costruiti in diversi grandi blocchi. Nell'ambiente di produzione il codice dell'applicazione è costruito con obiettivo di compilazione. Hai un'opzione per produrre un singolo file di output, o hai una costruzione parziale, dove il codice è suddiviso in grandi file (puoi controllarne le dimensioni). accumulo parziale può assomigliare a questo (ottimizzata/compresso con gzip):

├── [127/64kB] website.f6ffa57fc541.js 
├── [100/33kB] website.f86294b58d1a.js 
└── [361/110kB] website.js 

Nota che le parti sono caricati on-demand sulle pagine che li richiedono.

http://example.com/ 
└── website.js 
http://example.com/article 
└── website.js 
http://example.com/form 
└── website.js 
    └── website.f86294b58d1a.js 
http://example.com/gallery 
└── website.js 
    └── website.f6ffa57fc541.js 
http://example.com/geo 
└── website.js 

Perché Qooxdoo non bersaglia sito conclamata costruisce ancora, ma fornisce solo una piattaforma di tipo applicazione nativa, è necessario codificare l'ingresso alla domanda e alcune nozioni di base, come il bootstrap, il routing dell'URL, ecc. Ho provato a risolvere questo problema con qooxdoo-website-skeleton, a cui appartengono gli esempi precedenti. Sei libero di usarlo o di scriverne uno tuo.

Infine, notare che potrebbe non essere facile da avviare come con la libreria JavaScript media, ma la complessità è proporzionale all'eventuale vantaggio.

Problemi correlati