2010-07-02 14 views
15

Sviluppiamo un'applicazione in un ambiente embedded. Si tratta di un ambiente di calcolo di alto livello con un browser completo in cima a un sistema Linux busybox. L'unica eccezione è che il sistema ha una quantità limitata di memoria di sistema.È possibile utilizzare requirejs quando è necessario rimuovere i moduli per risparmiare memoria

La nostra applicazione è costruita in JavaScript e viene eseguita all'interno di un browser Webkit basato su un sacco di moduli javascript caricati in sequenza (il che non è molto efficiente).

Alcuni moduli forniscono funzionalità comuni utilizzate da diversi moduli. Stiamo procedendo alla conversione del nostro caricatore javascript corrente con requirejs, ma c'è una necessità specifica che dobbiamo affrontare per prima.

È possibile scaricare un modulo quando è stato caricato utilizzando requirejs? Assumiamo di carica dinamicamente un modulo utilizzando:

require(["somemodule.js"], function(m) { m.run(); }); 

che funziona bene per il caricamento e l'esecuzione di 'QualcheModulo' e anche di risolvere tutte le dipendenze per 'QualcheModulo' e il quadro requirejs sarà memorizzare un riferimento a 'QualcheModulo' per le richieste future .

Se a un certo punto è necessario recuperare la memoria, ad esempio per poter caricare ed eseguire un numero infinito di moduli, è necessario iniziare a rimuovere alcuni di essi dopo un po 'di tempo. È possibile con requirejs senza alterare l'implementazione interna?

Qualcuno ha già avuto a che fare con questo tipo di problema? La maggior parte delle applicazioni JS a pagina singola viene eseguita in un browser su un PC desktop in cui l'utilizzo della memoria di solito non è una preoccupazione importante.

risposta

17

RequireJS non ha una funzione di scarico incorporata, ma potrebbe essere aggiunta forse come parte aggiuntiva che è possibile creare in essa. Se desideri avere questa funzione, sentiti libero di proporla in the mailing list o come GitHub issue.

Se si voleva sperimentare per vedere se aiuta la vostra situazione, quello che dovete fare è il seguente:

1) Rimuovere il modulo definito dalla cache del modulo RequireJS. Se non si utilizza il supporto multiversione, si può fare qualcosa di simile:

var context = require.s.contexts['_']; 
delete context.defined[moduleName]; 
delete context.specified[moduleName]; 
delete context.loaded[moduleName]; 

2) Poi si può provare a rimuovere il tag script per vedere se questo aiuta:

var scripts = document.getElementsByTagName('script'); 
for (var i = scripts.length - 1; i >= 0; i--) { 
    var script = scripts[i]; 
    if (script.getAttribute('data-requiremodule') === moduleName) { 
     script.parentNode.removeChild(script); 
     break; 
    } 
} 

Nota che il modulo può non essere garbage collection se un altro modulo lo trattiene tramite la funzione closure() {} che definisce quell'altro modulo. Anche quell'altro modulo dovrebbe essere rimosso.

Si può provare a limitare tale impatto non passando il modulo come argomento di funzione, ma basta usare require ("somemodule") all'interno della definizione della funzione ogni volta che si desidera ottenere una sospensione dei moduli dipendenti, e non tenere premuto a ciò richiede un valore di ritorno troppo lungo.

Inoltre, nel tuo esempio sopra, per i moduli che utilizzano require.def di definire se stessi, dovrebbe assomigliare a questo (senza il suffisso .js):

require(["somemodule"], function(m) { m.run(); }); 
+0

Grazie , Tornerò quando lo avrò testato di più.Usiamo ancora il nostro caricatore di script ma convertiremo in requirejs, ci sono alcuni refactoring in anticipo poiché l'app utilizza attualmente uno spazio dei nomi globale. Ho notato nel sorgente per requirejs che onScriptLoad non rimuove lo scriptTag, ma si consiglia di farlo nella risposta sopra. È per motivi di prestazioni lo scriptTag è mantenuto nell'albero DOM in requirejs? Ad esempio, dal momento che la rimozione di scriptag aggiungerebbe un'ulteriore elaborazione nel caricatore. Il nostro preloader rimuove sempre lo scriptTag nel callback onload per preservare la memoria. – Ernelli

+0

Non rimuovo il tag script per semplificare il debug (il mio script è stato effettivamente caricato? Da dove?) E anche cercando di mantenere la dimensione del codice del loader. Ho pensato che non ci sarebbero stati molti risparmi, in particolare su una pagina che aveva i tag script in linea nell'HTML. Tuttavia, prenderò nota per testare se fa la differenza per rimuoverlo e funziona su tutti i browser. Indichi che fa la differenza, forse dovrei fornire un'opzione per farlo. Qualsiasi informazione su come convalidare i risparmi di memoria è apprezzata. – jrburke

+2

Il browser che utilizziamo nel nostro sistema embedded (un box settop IPTV) è basato su Webkit. Anche quando i tag di script vengono rimossi dal documento, le origini delle eccezioni ecc. Sono etichettate correttamente. Devo fare altri test per vedere quanta rimozione di scriptTag influisce sull'utilizzo della memoria. Anche quando gli script di tag vengono rimossi, il motore JS è in grado di ricreare il codice sorgente per una determinata funzione (sebbene senza commenti). Facciamo tutto il nostro profilo di memoria basato sul monitoraggio della quantità di memoria disponibile nel sistema. – Ernelli

2
+2

dalla documentazione requirejs su undef: "[...] Tuttavia, non rimuoverà il modulo da altri moduli che sono già definiti e ha ottenuto un handle su quel modulo come dipendenza quando sono stati eseguiti. Quindi è davvero utile solo utilizzare in situazioni di errore quando nessun altro modulo ha ottenuto un handle su un valore del modulo " – Steen

Problemi correlati