Während wir einen kleinen Server bauten, um Auditlogging auf unserem Hadoop-Cluster zu ermöglichen (mehr dazu in einem zukünftigen Blogpost), brauchten wir eine Möglichkeit, unsere Anwendung zu verteilen. In diesem Blog geht es um die Paketierung dieser Anwendung. Die Anwendung wird mit Nodejs erstellt und die Paketierung und das Abhängigkeitsmanagement erfolgt hauptsächlich mit npm (dem Node-Paketmanager). Natürlich sollte die Installation dieser Anwendung in der Produktionsumgebung genauso einfach sein wie die Einrichtung auf unseren eigenen Laptops, oder? Falsch! Auf unseren Laptops war es ein einfacher Git-Clone, gefolgt von einer npm-Installation und voila, wir hatten eine laufende Anwendung. Wie schwer kann es also sein, dies auf einem Server auf dem Client zu tun? Das kann ich Ihnen sagen....
Dieser Server ist nicht mit dem Internet verbunden, so dass der Git-Klon gar nicht erst funktionieren würde. Das ist nicht wirklich ein Problem, denn es handelt sich um eine kleine Anwendung und wir könnten einfach einen Tarball erstellen und ihn auf den Server schicken. Als Nächstes waren alle unsere Abhängigkeiten dran. Wir verwendeten einige Module, die in unserer package.json-Datei als Abhängigkeiten aufgeführt waren, so dass npm mit dem install-Befehl seine Arbeit tun konnte. Die npm-Installationsmagie besteht unter anderem darin, die Module aus der npm-Registry zu holen, und das schlägt fehl, wenn Sie nicht mit dem Internet verbunden sind. Auf der Suche nach einer Möglichkeit, dies anders zu machen, fand ich heraus, dass npm ein Cache-Verzeichnis hat und dachte, ich könnte die Sachen von dort holen. Das hätte vielleicht funktioniert, aber bei dieser Lösung würden mir die Abhängigkeiten fehlen, von denen diese Module abhängen. Und es wäre ein chaotisches Skript, das ich erstellen müsste. Das Durchstöbern des Internets hat mir zwar nicht die richtige Antwort geliefert, aber es hat mich auf den Weg zur npm pack-Funktion geführt. Damit wird Ihr Modul zusammen mit allen Abhängigkeiten gepackt. Das Einzige, was Sie brauchen, um sie richtig zu konfigurieren, ist ein separates Array mit den Abhängigkeiten, die mit Ihrer App gebündelt werden sollen. So weit, so gut. Ich habe also einen Abschnitt bundleDependencies in meine package.json eingefügt und npm pack ausgeführt. Das Ergebnis war eine schöne .tgz-Datei, die alle für die Anwendung benötigten Dateien sowie alle Module enthielt, von denen sie abhing. Zumindest die wichtigsten Module, von denen sie abhing. Meine kriminellen Programmierer, von denen ich diese Module erhalten habe, hatten sich nicht die Mühe gemacht, diesen zusätzlichen Abschnitt hinzuzufügen, so dass npm keine Kenntnis von den Modulen hatte, von denen sie abhängig waren. Das war einfach zu lösen. Fügen Sie einfach einen korrekten Abschnitt von bundleDependencies zu allen package.json-Dateien hinzu. Es klang nach einer langweiligen Aufgabe, dies manuell zu tun, und da ich meine Arbeit als Programmierer liebe, beschloss ich, ein Programm dafür zu schreiben. Meine offensichtliche Wahl der Programmiersprachen war: awk, grep und sed. Und warum? Weil ich es kann. Ohne Umschweife, hier ist es: [sourcecode language="bash"] awk '/Abhängigkeiten/,/]|}/' $file | grep -o '".".:' | sed 's/^.{//g' | sed 's/"abhängigkeiten.://g' | grep -v -e '^$' | uniq | sed 's/"[ ^I]:/",/g' | sed 's/":/",/g' | sed '$ s/,/ ]/' | sed '1 s/"/"bundleDependencies" : [ "/" | sed 's/"/"/g' | tr -d 'n' [/sourcecode] Sie fragen sich, was es bewirkt? Ich erkläre es Ihnen Zeile für Zeile: Zeile1: holt den Teil mit den Abhängigkeiten (ein Array oder ein json-Objekt) aus der Datei (der package.json-Datei) ex: "dependencies" : { "express": "0.2.2", "findit" : "0.0.1" } line2: holt nur das Zeug von diesem Objekt zwischen den Anführungszeichen vor dem Doppelpunkt (und entfernt den Teil der Versionsnummer der Abhängigkeit) ex: "express": "findit": Zeile3: Entfernen Sie alles, was vor dem { Zeile4: Entfernen Sie den ursprünglichen Abhängigkeitstext Zeile5: Entfernen Sie alle leeren Zeilen Zeile6: Entfernen Sie Duplikate Zeile7 und Zeile8: Ersetzen Sie das ": durch ", damit wir daraus ein Array erstellen können ex: "express", "findit", Zeile9: Ersetzen Sie das letzte , durch ein ], um das Array zu schließen ex: "express", "findit"] Zeile10: ersetzen Sie das erste " durch "bundleDependencies" : [ " ex: "bundleDependencies" : [ "express", "findit"] Zeile11: stellen Sie allen Anführungszeichen einen Backslash voran, damit es sicher im sed-Befehl verwendet werden kann, um es der Datei hinzuzufügen Zeile12: entfernen Sie alle Zeilenumbrüche ex: "bundleDependencies" : [ "express", "findit"] Dies wird zu der package.json Datei hinzugefügt, die wir gerade verarbeiten, und wenn wir dies für alle package.json Dateien getan haben, können wir npm pack verwenden, um unseren Tarball zu erstellen. Funktioniert ziemlich gut, könnte ich sagen. Aber ich bin der Erste, der zugibt, dass dies nicht das lesbarste Programm ist, das je geschrieben wurde. Wenn Sie eine Node-Anwendung erstellen, haben Sie vielleicht Node zur Hand, um Ihnen dabei zu helfen, also habe ich auch eine Javascript-Version erstellt: [sourcecode language="javascript"] var fs=require('fs') var findit=require('findit') findit.find('.', function(name) { if (endsWith(name,'package.json')) { handleDatei(Name) } }).on('end', bundleApp) Funktion handleFile(file) { var data = fs.readFile(file, function(err, data) { if (err) { console.log('Not processesed '+file+' bo the following error: '+err) } sonst { var arr = [] var packageFile = JSON.parse(data) if (packageFile.bundleDependencies) { console.log('Bundledeps bereits vorhanden. Überspringen') } sonst { for (var d in packageFile.dependencies) { arr.push(d+"") } wenn (arr.length > 0) { packageFile['bundleDependencies'] = arr fs.writeFile(file, JSON.stringify(packageFile, null, 4)) } } } }) } function bundleApp() { console.log('Fertig. Vorbereitung der package.json-Dateien für die Paketierung. Führen Sie jetzt npm pack aus, um den vollständigen Tarball zu erstellen') //Überlassen Sie dem Leser die Aufgabe, require('npm') und den Befehl pack auszuführen } function endsWith(str, suffix) { return str.indexOf(suffix, str.length - suffix.length) !== -1; } [/sourcecode] Ich hoffe, jemand kann in Zukunft davon profitieren.
Verfasst von
Kris Geusebroek
Unsere Ideen
Weitere Blogs
Contact


