2016-04-05 11 views
0

Unser Jenkins/CI-Server läuft Hunderte von Builds pro Tag für unsere Node/Js-Projekt, und ich würde gerne jeden Build in einem völlig sauberen Arbeitsbereich ausführen können . Der Schritt npm install kann jedoch> 10 Minuten dauern, was einfach viel zu langsam ist. Da sich unsere npm-Abhängigkeiten nur für eine kleine Anzahl von Builds ändern (ca. 1% aller Builds), möchte ich nur npm install einmal jedes Mal ausführen, wenn sich npm-shrinkwrap.json ändert (überprüfe md5sum bei jedem Build). Wenn sich die Shrinkwrap-Datei nicht geändert hat, verwenden Sie ein zwischengespeichertes Verzeichnis node_modules/.Verwenden einer gemeinsamen npm node_module/für mehrere Arbeitsbereiche auf dem gleichen Server

Dieser Plan funktioniert gut genug, wenn ich die zwischengespeicherten node_modules/ kopieren, aber auch diese Operation kann bis zu einer Minute dauern. Um unsere Build-Zeiten weiter zu optimieren, wäre ich in der Lage, Symlinks zu dem zwischengespeicherten node_modules/ zu erstellen, was unsere Build-Performance drastisch verbessern sollte.

ln -s /path/to/cache/ /path/to/workspace/node_modules 

jedoch einfach auf den Pfad des Cache SymLink funktioniert nicht in einem Fall, in dem eine Abhängigkeit auf mehreren Ebenen der Abhängigkeitsstruktur vorhanden ist. Als Beispiel hängt unser Top-Level-Projekt sowohl von gulp als auch gulp-util ab. Die Abhängigkeit auf oberster Ebene hängt auch von gulp-util ab. Nach einer npm install wird gulp-util in der obersten Ebene node_modules/ installiert, aber nicht in node_modules/gulp/node_modules.

Wenn die Abhängigkeiten existieren im lokalen Arbeitsbereich (das heißt ein echtes Verzeichnis /path/to/workspace/node_modules/), dann ist jede Instanz von require('gulp-util') innerhalb node_modules/gulp wird (glaube ich) Rekursion die Abhängigkeit Baum, bis sie einen geeigneten gulp-util Modul findet. Das heißt, es beginnt in /path/to/workspace/node_modules/gulp/node_modules/gulp-util suchen, findet nichts, dann sieht in /path/to/workspace/node_modules/gulp-util, findet ein entsprechendes Modul, importiert es und bewegt sich weiter.

Wenn dies jedoch ein Symlink ist werde ich einen Fehler wie erhalten:

module.js:339 
    throw err; 
    ^

Error: Cannot find module 'gulp-util' 
    at Function.Module._resolveFilename (module.js:337:15) 
    at Function.Module._load (module.js:287:25) 
    at Module.require (module.js:366:17) 
    at require (module.js:385:17) 
    at Object.<anonymous> (/path/to/cache/gulp/index.js:4:15) 
    at Module._compile (module.js:435:26) 
    at Object.Module._extensions..js (module.js:442:10) 
    at Module.load (module.js:356:32) 
    at Function.Module._load (module.js:311:12) 
    at Module.require (module.js:366:17) 
    at require (module.js:385:17) 

Ich gehe davon aus, dass dies das gleiche ist wie die andere Version zu tun versucht, aber ich kann nicht sehen, warum es nicht Finde gulp-util. Ob es in /path/to/workspace/node_modules/gulp-util oder /path/to/cache/gulp-util aussieht, sollte es das Modul finden und importieren können.

Ich habe versucht, dies zu lösen, indem Sie manuell das Modul gulp/node_modules/gulp-util installieren, aber ich begegne Dutzenden solcher Fehler und der Umgang mit diesem manuell auf einem Build-Server ist nicht machbar. Es ist möglich, Code zu schreiben, um nach Abhängigkeiten dieses Typs zu suchen und sie zu installieren, aber es fühlt sich an, als sei es falsch, etwas zu tun.

npm muss irgendwie einen solchen Workflow unterstützen, oder? Fehle ich etwas Offensichtliches? Habe ich etwas in der Dokumentation beschönigt?

+0

Es ist möglich, dass dies funktioniert, indem Sie zu NPM 3.x wechseln, was die Struktur node_modules von 'node_modules/parent/node_modules/child' in nur' node_modules/child' ändert. – Katana314

+0

Huh, ich habe es mit der neusten Version npm 3.x probiert und ich hatte genau das gleiche Problem. – laffoyb

+0

@laffoyb Überprüfen Sie diese Antwort http://StackOverflow.com/A/18974546/1341008 kurz gesagt, versuchen Sie, alle Module auf Ihre NODE_PATH –

Antwort

2

Dank einer Antwort von @ amol-m-kulkarni here (hilfreich von @ darko-rodic oben verwiesen), erkannte ich meinen Fehler.

Wenn das angegebene Modul nicht ein Kernmodule ist (z. Http, fs, etc.), Node.js wird dann beginnen, für ein Verzeichnis mit dem Namen, node_modules zu suchen.

Es im aktuellen Verzeichnis (bezogen auf die aktuell ausführende Datei in Node.JS) und arbeitet dann seinen Weg nach oben die Ordnerhierarchie beginnen wird, auf jede Ebene für einen node_modules Ordner zu überprüfen. Einmal Knoten.JS findet den Ordner node_modules und versucht dann das angegebene Modul entweder als JavaScript-Datei (.js) oder als Unterverzeichnis zu laden; Wenn es das benannte Unterverzeichnis findet, versucht es die Datei auf verschiedene Arten zu laden. So zum Beispiel

Mein Fehler war in dem Namen, den ich den Cache-Pfad gab. Wie es hieß /path/to/cache, require hörte auf nach oben nach dem letzten node_modules Dir es in den Pfad gefunden. In diesem Fall stoppte es bei /path/to/cache/gulp/node_modules und erkannte nicht, dass /path/to/cache/gulp-util bei der Suche berücksichtigt werden sollte.

Ich habe das behoben, indem ich den Cache in /path/to/cache/node_modules umbenannte, also wird require weiter suchen, bis es dieses Niveau erreicht, und wird danach /path/to/cache/node_modules/gulp-util finden.

Ich werde wieder auf die Dokumente verweisen, um zu sehen, ob dies für mich klar sein sollte oder nicht.

+1

Ich habe das gleiche Problem. Nachdem ich den Ordner node_modules im Cache-Ordner erstellt habe, funktioniert es. Danke vielmals!!! –