Das Build-Tool für Frontend-Entwickler vorgestellt: Schnell, einfach, Gulp
Gulp [1] drängt sich als Build-Tool Webentwicklern förmlich auf. Es basiert auf Node.js und bietet schon alleine dadurch einen großen Vorteil gegenüber anderen Build-Tools: Gulp selbst ist in JavaScript geschrieben, die Plugins auch und selbst die Konfiguration erfolgt über eine JavaScript-Datei. Dennoch muss man kein JavaScript-Genie sein. Basis-Kenntnisse reichen aus, um die Konfiguration für den eigenen Anwendungsfall anzupassen. Die umfangreichen Dokumentationen zu den Plugins erleichtern die Einbindung zusätzlich.
Dafür bietet Gulp dann auch nahezu grenzenlose Möglichkeiten: Ob man einfach nur CSS-Präprozessoren (Sass, Less, Stylus) nutzen und die daraus kompilierten CSS-Dateien im Nachhinein minifizieren möchte oder ob es um komplexere Aufgaben geht – Gulp lässt sich für nahezu alle Projekte und Anforderungen konfigurieren. Das Tool kompiliert CoffeeScript in JavaScript, liefert SCSS-Lint und JSHint für eine erste Qualitätssicherung und minifiziert oder fusioniert je nach Anforderung Scripte mit UglifyJS oder RequireJS. Ein Watch-Task vervollständigt den Funktionsumfang und ruft die vom Nutzer definierten Tasks automatisch auf, sobald er eine Datei speichert.
Gulp installieren
Gulp basiert auf Node.js und wird daher als Node Package Modul (npm) installiert. Node.js kann man als grafischen Installer auf nodejs.org [2] für Windows, Mac OS X und Linux herunterladen. Nach der erfolgreichen Installation von Node.js steht im Terminal der Installer für Node-Module zur Verfügung.
npm install -g gulp
Listing 1
Zusätzlich benötigen Frontend-Entwickler Gulp im Projekt selbst. Dazu wechseln sie in den Projektordner und führen den Befehl dort ohne -g erneut aus:
npm install gulp
Listing 2
An dieser Stelle empfiehlt es sich jedoch, eher mit einer package.json-Datei [3] zu arbeiten. Diese Datei enthält die npm-Konfigurationen für das aktuelle Projekt. Eine solche Datei kann zum Beispiel wie folgt aussehen:
{ "name": "my-project-name", "version": "0.1.0", "devDependencies": { "gulp": "^3.8.6", "gulp-sass": "~0.7.2", "gulp-coffee": "~2.1.1", "gulp-jshint": "~1.7.1", "gulp-rename": "^1.2.0", "gulp-scss-lint": "^0.1.0", "gulp-sourcemaps": "~1.1.0", "gulp-uglify": "~0.3.1" } }
Listing 3
Der Vorteil einer package.json-Datei ist, dass der Nutzer nicht jedes Plugin [4] oder jede lokale Gulp-Version einzeln installieren muss. Sobald die Datei im Projekt angelegt ist, reicht ein Terminalbefehl, um Gulp und die gewünschten Plugins zu installieren:
npm install
Listing 4
Schritt für Schritt mit Gulp arbeiten
Die Konfiguration von Gulp – und damit aller Tasks – erfolgt in der JavaScript-Datei „gulpfile.js“. Dabei lassen sich Tasks einzeln konfigurieren oder auch beliebig kombinieren. Während ein Task die Kompilierung von Sass zu CSS übernimmt und ein anderer JavaScript auf Syntaxfehler prüft (etwa JSHint), können Gulp-Nutzer auch beide zusammen in einem Task ausführen.
/ benötigte Module laden. var gulp = require('gulp'), coffee = require('gulp-coffee'), jshint = require('gulp-jshint'), rename = require('gulp-rename'), sass = require('gulp-sass'), scsslint = require('gulp-scss-lint'), sourcemaps = require('gulp-sourcemaps'), uglify = require('gulp-uglify'); // Task für Sass definieren gulp.task('sass', function() { gulp.src('./dev/sass/**/*.scss') .pipe(scsslint()) .pipe(sass()) .pipe(sourcemaps.write()) .pipe(gulp.dest('./build/css/')); }); // Task für CoffeeScript gulp.task('coffee', function() { gulp.src('./dev/coffee/**/*.coffee') .pipe(coffee({bare: true})) .pipe(sourcemaps.write()) .pipe(gulp.dest('./build/js/')) .pipe(jshint()) .pipe(jshint.reporter('default')) .pipe(uglify()) .pipe(rename(function(path) { path.extname = '.min.js'; })) .pipe(gulp.dest('./build/js/')); }); // Default-Task als Watch-Task gulp.task('default', function () { gulp.watch(['./scss/**/*.scss', './coffee/**/*.coffee'], function() { gulp.run(['sass', 'coffee']); }); });
Listing 5
Der erste Block dieses Gulpfiles lädt die notwendigen Module und Gulp-Plugins. Dem folgt die Definition der Tasks in drei Blöcken: sass, coffee und default. Die beiden Tasks „sass“ und „coffee“ lassen sich im Terminal separat mit „gulp sass“ und „gulp coffee“ ausführen. Zuletzt kommt die Definition des Default-Tasks, welcher als Watch-Task angelegt ist und beim Speichern der Dateien die Tasks „sass“ und „coffee“ ausführt. Der Default-Task lässt sich als einziger Tasks im Terminal ohne weiteren Zusatz mit Gulp aufrufen.
Auffällig ist die Verwendung der Anweisung „pipe()“. Gulp arbeitet mit Streams und bezeichnet sich als „streaming build system“. Das bedeutet im Detail, dass ein Plugin selbst nur bereits eingelesene Daten erhält und diese dann in modifizierter Form wieder herausgibt. Dabei greift Gulp weder lesend noch schreibend direkt auf einzelne Dateien zu. Die Anweisung „gulp.src()“ liest zunächst eine oder mehrere Dateien ein. Die Anweisung „pipe()“ gibt dann den Inhalt von Plugin zu Plugin weiter.
Auf diese Weise erzielt das Tool eine hohe Performance bei der Verarbeitung – und liefert gleichzeitig eine Plugin-Struktur, die sehr losgelöst von Gulp existieren kann. Der Befehl „gulp.dest()“ schließt das Ergebnis ab und schreibt es in eine oder mehrere Dateien. Das muss allerdings nicht das Ende eines Tasks sein.
Der obenstehende Task „coffee“ zeigt, dass Gulp-User nach dem Erstellen der Dateien mit „pipe()“ weitere Aktionen vornehmen können, um das kompilierte JavaScript zusätzlich zu minifizieren und mit der Endung „.min.js“ abzuspeichern. Das zuvor kompilierte JavaScript muss das Tool dafür nicht einlesen, weil es noch immer innerhalb des Streams zur Verfügung steht.
Gulp, Grunt und Yeoman – Wesentliche Unterschiede
Neben Gulp gibt es weitere, leistungsfähige Build-Tools: allen voran Grunt [5], das bereits weit verbreitet ist und zum Beispiel bei jQuery und Modernizr zum Einsatz kommt. Gulp und Grunt sind sich augenscheinlich sehr ähnlich: Beide Build-Tools müssen vom Anwender als Node-Module installiert werden, beide sind in JavaScript geschrieben und sowohl Gulp als auch Grunt lassen sich mit JavaScript konfigurieren („gulpfile.js“ und „gruntfile.js“).
Es gibt jedoch auch zwei signifikante Unterschiede: Erstens verfolgen beide Tools unterschiedliche Paradigmen. Gulp setzt auf „code over configuration“ während sich Grunt über „configuration over code“ definiert. Vergleicht man gulpfile.js mit einer gruntfile.js-Datei wird deutlich, dass man in Grunt lediglich ein großes JavaScript-Objekt definiert.
Während dies Geschmacksfrage ist, liefert Gulp beim zweiten Unterschied einen echten Mehrwert, der sich auch in der deutlich höheren Geschwindigkeit von Gulp im Vergleich zu Grunt niederschlägt [6] : Gulp übergibt in seinen Streams die Daten als virtual file objects, was für hohe Geschwindigkeiten sorgt.
Grunt schreibt hingegen Daten immer direkt in Dateien und ist bei bestimmten Tasks damit auf temporäre Dateien angewiesen, um Daten zwischen Grunt-Plugins auszutauschen. Eine direkte Übergabe von Daten an andere Plugins ist mit Grunt nicht möglich. So benötigt Grunt temporäre Dateien für den Datenaustausch und trennt die Aufgaben von Plugins nicht konsequent – genau das ist der Grund dafür, warum Eric
Schoffstall (@contra) Gulp entwickelte [7].
Das andere Tool, das sich mit Gulp vergleichen lässt, ist Yeoman [8]. Es versteht sich nicht im eigentlichen Sinne als Build-Tool, sondern vereinigt die Tools Yo (Scaffolding), Grunt (Build Process) und Bower (Package Manager) zu einem Tool-Paket. Mittlerweile existiert für Yeoman auch ein offizieller Generator, mit dem man Gulp statt Grunt nutzen kann [9].
Fazit: einen Blick wert für jeden Frontend-Entwickler
Jeder Frontend-Entwickler sollte ein Build-Tool nutzen. Ob Gulp, Grunt oder ein anderes Tool die richtige Wahl ist, lässt sich nicht pauschal sagen. Gulp weist gegenüber Grunt zwar deutliche Vorteile auf, doch Grunt hat sich bereits weitgehend durchgesetzt. Das wiederum hat zur Folge, dass sehr viel mehr Grunt-Plugins als Gulp-Plugins existieren. Außerdem hat Grunt in seiner Roadmap [10] bereits angekündigt, Streams (pipe) für eine spätere Version zu nutzen. Trotz dieser Aspekte ist Gulp eine spannende Grunt-Alternative, die sich Frontend-Entwickler nicht zuletzt wegen der Performance-Vorteile anschauen sollten.