2011-07-13 11 views
42

Jestem ciekawy, czy istnieje jakiś dobry sposób na wyładowanie modułu po jego użyciu. Mam kilka przypadków, w których muszę używać modułów, które zawierają dużo kodu, ale są rzadko używane (powiedzmy jako narzędzie administratora), ale waham się ich użyć, ponieważ później prawdopodobnie po prostu marnują pamięć, która może być lepsza używane gdzie indziej. Czy istnieje sposób, aby je wyładować, jawnie lub poprzez zezwolenie systemu, aby to zrobić, gdy nie były używane przez jakiś czas?kod/moduły rozładowujące

Odpowiedz

64

Tak, to jest możliwe, aby uzyskać dostęp do pamięci podręcznej modułu bezpośrednio:

var name = require.resolve('moduleName'); 
delete require.cache[name]; 

pamiętać, że jeśli kod niesie odniesienie do tego, co zostało wystawione przez te moduły, które chcesz pozbyć, to nie będzie oczyszczone.

(Tak na marginesie: Pod powierzchnią, require.resolve i require.cache tylko pełnomocników do Module._resolveFilename i Module._cache odpowiednio, z Module jest ładowarka moduł podstawowy, tj require('module').)

+8

To nie jest kompletna odpowiedź. Niektóre wymagają załadowania pliku index.js, który następnie ładuje prawdziwe mięso z biblioteki. Na przykład spróbuj require ('async') to ładuje "... async/lib/async.js", ale również ładuje "..async/index.js", który można zobaczyć w wymaganiu .Pamięć podręczna. index.js jest rodzicem pliku async.js. Prawdopodobnie jest to możliwe, aby wyrejestrować, ale może wymagać funkcji rekursywnej, aby usunąć wiele modułów. –

+4

Po prostu wykonaj 'dla (klawisz var w Object.keys (require.cache)) {delete require.cache [key];}'. – Tower

+3

@Tower, To by wyładować wszystkie moduły. Lepszym rozwiązaniem może być sprawdzenie 'module.parent' - lub czegoś - i tylko wyładowanie modułów, które chcesz rozładować. Na przykład 'util' i' fs' prawdopodobnie nie powinny być rozładowywane. –

3

można zrobić coś takiego „rozładunku "moduł węzła:

/** 
* Deletes a node module and all associated children 
* from node require cache 
* @param {string} moduleName The name of the module or 
*       absolute/relative path to it 
*/ 
function deleteModule(moduleName) { 
    var solvedName = require.resolve(moduleName), 
    nodeModule = require.cache[solvedName]; 
    if (nodeModule) { 
    for (var i = 0; i < nodeModule.children.length; i++) { 
     var child = nodeModule.children[i]; 
     deleteModule(child.filename); 
    } 
    delete require.cache[solvedName]; 
    } 
} 

«Rozładunek»moduł węzła oznacza, że ​​jesteś«kasowanie»jego wejście od węzła wymagać cache. Fragment powyżej przechowuje przejściowo jeden moduł węzła z pamięci podręcznej i wszystkich powiązanych modułów (modułów potomnych).

W moim przypadku wymagałem "index.js", który jednocześnie wymagał "/lib/.js". Chciałem przetestować inicjalizację "index.js" (a więc jedyny wymagany moduł, który był /lib/.js). Usunięcie "index.js" z pamięci podręcznej nie było wystarczające, ponieważ pamięć podręczna zachowała oddzielne odniesienie do "/lib/.js", co spowodowało, że moduł "/lib/.js" nie został ponownie załadowany z pliku.

Powyższy kod z pewnością usunie z pamięci podręcznej innych modułów, od których moduł jest zależny (właściwie to chciałem, ALE może nie chcesz tego robić dla innych modułów, takich jak "fs", "ścieżka" czy nawet "podkreślenie").

Zawsze można rozszerzyć tę metodę, aby zaakceptować listę modułów, których nie chcesz usunąć, lub filtr, który można zastosować do "ścieżki" rozwiązanego modułu. Możesz powiedzieć: nie usuwaj podstawowych modułów węzłów (lista nazw modułów węzłów rdzenia jest dostępna jako pakiet npm: https://www.npmjs.com/package/node-core-module-names) lub nie usuwaj żadnego z pakietów pod węzłem_węzły, itd. Itd. Może to być filtr wewnątrz funkcja, ale jest to ta sama logika.

+0

Ta funkcja deleteModule skończy się na stosie okrągłe zależności. – Halt