Suche
Kolumne: Webentwicklung mit Angular 2

Angular 2 und Yarn: Kein Seemannsgarn

Karsten Sitterberg
Angular 2 Tutorial

In dieser Folge der Kolumne Webentwicklung mit Angular 2 nimmt sich Karsten Sitterberg den neuen Paketmanager Yarn vor, der von Facebook in Kooperation mit Google, Exponent und Tilde entwickelt wurde.

Angular 2 und Yarn: Kein Seemannsgarn

Diese Situation dürfte jeder JavaScript-Entwickler bereits einmal erlebt haben: Man hat ein größeres Projekt gerade frisch ausgecheckt und stößt den npm install-Prozess an. Daraufhin kann man – bevor es mit der eigentlichen Entwicklungsarbeit losgehen kann – sich dann erstmal einen Kaffee holen, da auf dem Rechner der NPM-Client zunächst das halbe Internet runterladen muss. Ärgerlich daran ist auch, dass alle Abhängigkeiten für jedes Projekt neu heruntergeladen werden – auch, wenn man diese vorher bereits (z.B. in einem anderen Projekt) einmal heruntergeladen hatte.

Gerade im Enterprise-Umfeld ist das Herunterladen von Daten aus dem wilden Internet nicht ganz unproblematisch: Firewalls und Sicherheitsvorgaben der Firma lassen oft keinen uneingeschränkten Zugriff zu. Das gilt umso mehr für Build-Server, auf denen mit allerlei Hacks gearbeitet werden muss, damit Projekte auch dort funktionieren.

Für all diese Probleme soll der neue Paketmanager Yarn Abhilfe schaffen, der von Facebook in Kooperation mit Google, Exponent und Tilde entwickelt wurde.

Angular 2 Yarn

Vorweg zur Philosophie von NPM: Der Node Package Manager sorgt dafür, dass notwendige Abhängigkeiten bereitgestellt werden. Ein Problem dabei ist, dass jede Abhängigkeit beliebig viele weitere Abhängigkeiten haben kann, die ihrerseits wieder installiert werden müssen, was schnell zu großen Abhängigkeitsbäumen führen kann. Dem wurde zwar entgegengewirkt, indem gleiche Abhängigkeiten so gut wie möglich zusammengefasst werden. Dabei kann aber dieselbe Abhängigkeit trotzdem zweimal installiert werden, wenn sie in unterschiedlichen Versionen angefragt wird.

Dieser Ansatz hat zudem den Nachteil, dass sich das Installationsergebnis bei jedem Durchlauf unterscheiden kann, da die Reihenfolge, in welcher die Abhängigkeiten aufgelöst, werden, nicht festgelegt ist. Ein Bug, welcher durch unterschiedliche Installationsreihenfolge der Abhängigkeiten ausgelöst wird, kann schwer zu diagnostizieren und beheben sein, da er in manchen Umgebungen auftreten kann, in anderen dafür nicht.

Yarn behebt auch dieses Problem und ermöglicht dabei gleichzeitig einen schnelleren Installationsprozess. Erreicht wird dies durch einen dreistufigen Prozess, der sauber voneinander getrennte Phasen aufweist. Zunächst werden alle Abhängigkeiten durch entsprechende Abfragen ermittelt.

Erst im zweiten Schritt werden dann die abhängigen Artefakte beschafft. Dafür wird zunächst in einem globalen Cache gesucht. Ist die Abhängigkeit dort noch nicht vorhanden, wird sie heruntergeladen und für spätere Benutzung im Cache abgelegt, sodass jede Abhängigkeit, auch bei anderen Installationsvorgängen, nur einmal heruntergeladen werden muss.

Der letzte Schritt ist dann das Verlinken, indem alle angeforderten Abhängigkeiten im Verzeichnis node_modules des Projektes abgelegt werden.

Vorteil dieses Schritt-für-Schritt Vorgehens ist die hohe Parallelisierbarkeit innerhalb der einzelnen Schritte. Dadurch können bestehende Ressourcen besser ausgenutzt werden, was den Installationsvorgang drastisch beschleunigt. Facebook redet hier bei einigen seiner Projekte von Unterschieden einer ganzen Größenordnung zwischen dem NPM- und dem Yarn-Vorgang. Dadurch, dass eine deterministische Auflösung der Abhängigkeiten erfolgt, wird eine konsistente Installation in unterschiedlichen Umgebungen sichergestellt.

Der Vorteil von Yarn wird besonders bei Projekten mit vielen Abhängigkeiten deutlich. Dies trifft zum Beispiel auf Angular-2-Projekte sehr häufig zu, denn in diesem Fall sind nicht nur die Angular-2-Bibliotheken herunterzuladen, sondern auch noch weitere Abhängigkeiten wie RxJS oder Zone.js. Hinzu kommen die für den Buildprozess notwendigen Abhängigkeiten wie TypeScript, Sass, Jasmine, Karma, Gulp, Webpack und so weiter.

Yarn versus NPM

Yarn nutzt das bestehende package.json-Format von NPM und versteht sich (zur Zeit) als voll kompatibles Frontend für NPM. Somit ist Experimentieren mit Yarn risikolos in jedem Projekt machbar. (Eine Ausnahme bilden hier Angular-2-Projekte, die das Angular 2 CLI verwenden, da dies den Aufruf von NPM fest eingebaut hat. Für die Verwendung von Yarn in Angular CLI gibt es bereits eine entsprechende Issue auf GitHub).

Zum Vergleich von Yarn und NPM schauen wir uns nun die Installation des Angular-Seed-Projektes (https://github.com/mgechev/angular-seed) mit npm und yarn an. Zunächst installieren wir dafür Yarn als globale NPM-Abhängigkeit:

npm install -g yarn

Dann klonen wir das Angular-2-Seed-Projekt und messen die Zeit für einen normalen NPM install. Unter Linux kann dazu das Kommando ‘time’ verwendet werden, wie hier gezeigt:

git clone git@github.com:mgechev/angular-seed.git
cd angular-seed
time npm install

Die dafür benötigte Zeit beträgt 2 Minuten 41,94 Sekunden. Um dies mit Yarn zu testen, wird das Projekt ein weiteres Mal ausgecheckt und der Install-Vorgang mit Yarn gestartet.

git clone git@github.com:mgechev/angular-seed.git angular-yarn
cd angular-yarn
yarn

Dafür wird im Test von Yarn bei kaltem Cache, und damit abhängig von der verfügbaren Internetbandbreite, eine Zeit von 1 Minute 38,99 Sekunden benötigt. Bei warmem Cache und aufgelösten Dependencies verringert sich diese Zeit dann auf sagenhafte 15 Sekunden. (Ohne das Dependency-Lock File sind es noch rund 50 Sekunden.) Letztere Zeit wird dabei durch die verwendete Festplatte und das Dateisystem dominiert, landen hier doch rund 45.000 Dateien und Ordner im node_modules-Ordner.

image00

Angular-2-Projekte nutzen viele Abhängigkeiten, so dass sich Yarn hier schnell bezahlt macht. Dies wird am Beispiel eines neuen Projektes deutlich. Was Yarn im Gegensatz zu NPM nicht erledigt, sind NPM postinstall Scripte. Postinstall Scripte werden genutzt, um nach der Installation von Abhängigkeiten noch Nachverarbeitungen durchzuführen, normalerweise werden hier jedoch keine oder nur noch wenige Abhängigkeiten nachgeladen.

Lesen Sie auch:  Angular CLI Webpack – das bringt’s!

Fazit

Gerade bei umfangreichen JavaScript-Projekten wie bei Angular 2 verspricht Yarn eine Menge Vorteile. Durch die erheblich erhöhte Geschwindigkeit werden deterministische und reproduzierbare Builds deutlich einfacher. Sogar offline arbeiten wird prinzipiell ermöglicht. Da Yarn als JavaScript bereitgestellt wird, ist die Ablösung von NPM als Standard Dependency Manager nur noch eine Frage der Zeit. Auch daran, dass innerhalb von nur einem Tag fast 200 Issues für Yarn gemeldet worden sind, zeigt sich, wie enthusiastisch die Community auf das neue Werkzeug aufspringt. Fehler und Unzulänglichkeiten werden mit Sicherheit bald ausgeräumt.

Geschrieben von
Karsten Sitterberg
Karsten Sitterberg
Karsten Sitterberg ist als freiberuflicher Entwickler, Trainer und Berater für Java und Webtechnologien tätig. Karsten ist Physiker (MSc) und Oracle-zertifizierter Java Developer. Seit 2012 arbeitet er mit trion zusammen.
Kommentare

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht.