Gulp für Anfänger

Avatar of Zell Liew
Zell Liew am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Gulp ist ein Tool, das bei der Webentwicklung bei verschiedenen Aufgaben hilft. Es wird häufig für Frontend-Aufgaben wie die folgenden verwendet:

  • Einen Webserver starten
  • Den Browser automatisch neu laden, wenn eine Datei gespeichert wird
  • Präprozessoren wie Sass oder LESS verwenden
  • Assets wie CSS, JavaScript und Bilder optimieren

Wichtiger Hinweis! Dieser Artikel wurde für Gulp 3.x geschrieben, aber jetzt ist Gulp 4.x verfügbar und wird empfohlen. Wie bei jeder größeren Versionsänderung gibt es API-Änderungen, die nicht abwärtskompatibel sind. Wenn Sie Gulp 4 installieren und versuchen, einige der Dinge in diesem Artikel zu tun, funktionieren diese nicht. Wir werden hier Notizen einstreuen, um Sie daran zu erinnern. Dies scheint ein ziemlich guter Gulp 4-Starter zu sein.

Dies ist keine vollständige Liste dessen, was Gulp kann. Wenn Sie verrückt genug sind, können Sie mit Gulp sogar einen Generator für statische Websites erstellen (ich habe es getan!). Ja, Gulp ist extrem leistungsstark, aber Sie müssen lernen, wie Sie Gulp verwenden, wenn Sie Ihre eigenen angepassten Build-Prozesse erstellen möchten.

Dafür ist dieser Artikel gedacht. Er hilft Ihnen, die Grundlagen von Gulp so gut zu beherrschen, dass Sie beginnen können, alles andere selbst zu erkunden.

Bevor wir uns mit der Arbeit mit Gulp befassen, sprechen wir darüber, warum Sie Gulp anstelle anderer ähnlicher Tools verwenden sollten.

Warum Gulp?

Tools wie Gulp werden oft als „Build-Tools“ bezeichnet, weil es sich um Tools handelt, die die Aufgaben zum Erstellen einer Website ausführen. Die beiden beliebtesten Build-Tools sind derzeit Gulp und Grunt. (Chris hat hier einen Beitrag zum Einstieg in Grunt). Aber es gibt natürlich auch andere. Broccoli konzentriert sich auf die Asset-Kompilierung, eine der häufigsten Aufgaben von Build-Tools.

Es gibt bereits mehrere Artikel, die den Unterschied zwischen Grunt und Gulp behandeln und erklären, warum man das eine dem anderen vorziehen könnte. Sie können diesen Artikel, diesen oder diesen lesen, wenn Sie mehr erfahren möchten. Brunch konzentriert sich ebenfalls auf Assets und bündelt einige der gängigsten anderen Aufgaben wie einen Server und einen Dateiwächter.

Der Hauptunterschied besteht darin, wie Sie einen Workflow damit konfigurieren. Gulp-Konfigurationen sind in der Regel viel kürzer und einfacher als Grunt-Konfigurationen. Gulp läuft auch tendenziell schneller.

Lassen Sie uns nun fortfahren und herausfinden, wie man einen Workflow mit Gulp einrichtet.

Was wir einrichten

Am Ende dieses Artikels werden Sie einen Workflow haben, der die Aufgaben erledigt, die wir am Anfang dieses Artikels skizziert haben:

  • Startet einen Webserver
  • Kompiliert Sass zu CSS
  • Aktualisiert den Browser automatisch, wenn Sie eine Datei speichern
  • Optimiert alle Assets (CSS, JS, Schriftarten und Bilder) für die Produktion

Sie werden auch lernen, wie Sie verschiedene Aufgaben zu einfachen Befehlen verketten, die leicht zu verstehen und auszuführen sind.

Beginnen wir mit der Installation von Gulp auf Ihrem Computer.

Gulp installieren

Sie müssen Node.js (Node) auf Ihrem Computer installiert haben, bevor Sie Gulp installieren können.

Wenn Sie Node noch nicht installiert haben, können Sie es über die Node-Website herunterladen.

Wenn Sie die Installation von Node abgeschlossen haben, können Sie Gulp mit dem folgenden Befehl in der Befehlszeile installieren:

$ sudo npm install gulp -g

Hinweis: Nur Mac-Benutzer benötigen das Schlüsselwort sudo. (Siehe den ersten Kommentar von Pawel Grzybek, wenn Sie sudo nicht verwenden möchten). Und denken Sie daran, dass das „$“ im obigen Code nur die Eingabeaufforderung symbolisiert. Es ist nicht wirklich Teil des Befehls, den Sie ausführen.

Der Befehl npm install, den wir hier verwendet haben, ist ein Befehl, der Node Package Manager (npm) verwendet, um Gulp auf Ihrem Computer zu installieren.

Das Flag -g in diesem Befehl weist npm an, Gulp global auf Ihrem Computer zu installieren, sodass Sie den Befehl gulp überall auf Ihrem System verwenden können.

Mac-Benutzer benötigen das zusätzliche Schlüsselwort sudo im Befehl, da sie Administratorrechte benötigen, um Gulp global zu installieren.

Nachdem Sie Gulp installiert haben, erstellen wir ein Projekt, das Gulp verwendet.

Ein Gulp-Projekt erstellen

Zuerst erstellen wir einen Ordner namens project, der als Stammverzeichnis unseres Projekts dient, während wir dieses Tutorial durchgehen. Führen Sie den Befehl npm init in diesem Verzeichnis aus:

# ... from within our project folder
$ npm init

Der Befehl npm init erstellt eine package.json-Datei für Ihr Projekt, in der Informationen über das Projekt gespeichert werden, wie z. B. die im Projekt verwendeten Abhängigkeiten (Gulp ist ein Beispiel für eine Abhängigkeit).

npm init fragt Sie:

Sobald die Datei package.json erstellt ist, können wir Gulp mit dem folgenden Befehl in das Projekt installieren:

$ npm install gulp --save-dev

Dieses Mal installieren wir Gulp im Ordner project, anstatt es global zu installieren, weshalb es einige Unterschiede im Befehl gibt.

Sie werden sehen, dass das Schlüsselwort sudo nicht erforderlich ist, da wir Gulp nicht global installieren, sodass -g ebenfalls nicht notwendig ist. Wir haben --save-dev hinzugefügt, was dem Computer mitteilt, gulp als Entwicklungsabhängigkeit in package.json hinzuzufügen.

Wenn Sie den Projektordner überprüfen, nachdem der Befehl ausgeführt wurde, sollten Sie sehen, dass Gulp einen Ordner node_modules erstellt hat. Sie sollten auch einen gulp-Ordner innerhalb von node_modules sehen.

Wir sind fast bereit, mit der Arbeit mit Gulp zu beginnen. Zuvor müssen wir uns jedoch darüber im Klaren sein, wie wir Gulp für das Projekt verwenden werden, und dazu gehört die Entscheidung über eine Verzeichnisstruktur.

Ordnerstruktur festlegen

Gulp ist flexibel genug, um mit jeder Ordnerstruktur zu arbeiten. Sie müssen nur die inneren Abläufe verstehen, bevor Sie sie für Ihr Projekt anpassen.

Für diesen Artikel verwenden wir die Struktur einer generischen Webanwendung:

  |- app/
      |- css/
      |- fonts/
      |- images/ 
      |- index.html
      |- js/ 
      |- scss/
  |- dist/
  |- gulpfile.js
  |- node_modules/
  |- package.json

In dieser Struktur verwenden wir den Ordner app für Entwicklungszwecke, während der Ordner dist (von „distribution“) optimierte Dateien für die Produktions-Website enthält.

Da app für Entwicklungszwecke verwendet wird, wird unser gesamter Code in app abgelegt.

Wir müssen diese Ordnerstruktur im Hinterkopf behalten, wenn wir an unseren Gulp-Konfigurationen arbeiten. Beginnen wir nun mit der Erstellung Ihrer ersten Gulp-Aufgabe in gulpfile.js, die alle Gulp-Konfigurationen speichert.

Ihre erste Gulp-Aufgabe schreiben

Der erste Schritt zur Verwendung von Gulp besteht darin, es im gulpfile zu requiren.

var gulp = require('gulp');

Die Anweisung require weist Node an, im Ordner node_modules nach einem Paket namens gulp zu suchen. Sobald das Paket gefunden wurde, weisen wir seinen Inhalt der Variablen gulp zu.

Wir können nun mit dieser gulp-Variable eine Gulp-Aufgabe schreiben. Die grundlegende Syntax einer Gulp-Aufgabe lautet:

gulp.task('task-name', async function() {
  // Stuff here
});

task-name bezieht sich auf den Namen der Aufgabe, die immer dann verwendet wird, wenn Sie eine Aufgabe in Gulp ausführen möchten. Sie können dieselbe Aufgabe auch in der Befehlszeile ausführen, indem Sie gulp task-name eingeben.

Um es auszuprobieren, erstellen wir eine hello-Aufgabe, die Hello Zell! ausgibt.

gulp.task('hello', async function() {
  console.log('Hello Zell');
});

Wir können diese Aufgabe mit gulp hello in der Befehlszeile ausführen.

$ gulp hello

Die Befehlszeile gibt ein Protokoll mit der Meldung Hello Zell! zurück.

Gulp-Aufgaben sind normalerweise etwas komplexer als das. Sie enthalten normalerweise zwei zusätzliche Gulp-Methoden sowie eine Vielzahl von Gulp-Plugins.

So könnte eine echte Aufgabe aussehen:

gulp.task('task-name', async function () {
  return gulp.src('source-files') // Get source files with gulp.src
    .pipe(aGulpPlugin()) // Sends it through a gulp plugin
    .pipe(gulp.dest('destination')) // Outputs the file in the destination folder
})

Wie Sie sehen können, verwendet eine echte Aufgabe zwei zusätzliche Gulp-Methoden – gulp.src und gulp.dest.

gulp.src teilt der Gulp-Aufgabe mit, welche Dateien für die Aufgabe verwendet werden sollen, während gulp.dest Gulp mitteilt, wohin die Dateien ausgegeben werden sollen, sobald die Aufgabe abgeschlossen ist.

Versuchen wir, eine echte Aufgabe zu erstellen, bei der wir Sass-Dateien in CSS-Dateien kompilieren.

Präprozessieren mit Gulp

Wir können Sass mit Hilfe eines Plugins namens gulp-sass in Gulp in CSS kompilieren. Sie können gulp-sass in Ihr Projekt installieren, indem Sie den Befehl npm install verwenden, wie wir es für gulp getan haben.

Wir möchten auch das Flag --save-dev verwenden, um sicherzustellen, dass gulp-sass zu devDependencies in package.json hinzugefügt wird.

$ npm install gulp-sass --save-dev

Wir müssen gulp-sass aus dem Ordner node_modules requiren, genau wie wir es mit gulp getan haben, bevor wir das Plugin verwenden können.

var gulp = require('gulp');
// Requires the gulp-sass plugin
var sass = require('gulp-sass');

Wir können gulp-sass verwenden, indem wir aGulpPlugin() durch sass() ersetzen. Da die Aufgabe Sass in CSS kompilieren soll, nennen wir sie sass.

gulp.task('sass', async function(){
  return gulp.src('source-files')
    .pipe(sass()) // Using gulp-sass
    .pipe(gulp.dest('destination'))
});

Wir müssen der sass-Aufgabe Quelldateien und ein Ziel zuweisen, damit die Aufgabe funktioniert. Erstellen wir also eine Datei styles.scss im Ordner app/scss. Diese Datei wird der sass-Aufgabe in gulp.src hinzugefügt.

Wir möchten die endgültige Datei styles.css in den Ordner app/css ausgeben, der das destination für gulp.dest wäre.

gulp.task('sass', async function(){
  return gulp.src('app/scss/styles.scss')
    .pipe(sass()) // Converts Sass to CSS with gulp-sass
    .pipe(gulp.dest('app/css'))
});

Wir möchten testen, ob die sass-Aufgabe wie gewünscht funktioniert. Dazu können wir eine Sass-Funktion in styles.scss hinzufügen.

// styles.scss
.testing {
  width: percentage(5/7);
}

Wenn Sie gulp sass in der Befehlszeile ausführen, sollten Sie jetzt sehen können, dass eine Datei styles.css in app/css erstellt wurde. Außerdem enthält sie den Code, bei dem percentage(5/7) zu 71.42857% ausgewertet wurde.

/* styles.css */
.testing {
  width: 71.42857%; 
}

So wissen wir, dass die sass-Aufgabe funktioniert!

Manchmal müssen wir mehr als eine .scss-Datei gleichzeitig in CSS kompilieren. Dies können wir mit Hilfe von Node-Globs tun.

Zu Ihrer Information: Gulp-sass verwendet LibSass, um Sass in CSS zu konvertieren. Es ist viel schneller als Ruby-basierte Methoden. Wenn Sie möchten, können Sie trotzdem Ruby-Methoden mit Gulp verwenden, indem Sie stattdessen gulp-ruby-sass oder gulp-compass verwenden.

Globbing in Node

Globs sind Suchmuster für Dateien, die es Ihnen ermöglichen, mehr als eine Datei in gulp.src hinzuzufügen. Es ist wie reguläre Ausdrücke, aber speziell für Dateipfade.

Wenn Sie einen Glob verwenden, überprüft der Computer Dateinamen und Pfade auf das angegebene Muster. Wenn das Muster vorhanden ist, wird eine Datei abgeglichen.

Die meisten Workflows mit Gulp erfordern in der Regel nur 4 verschiedene Globbing-Muster:

  1. *.scss: Das Muster * ist ein Platzhalter, der mit jedem Muster im aktuellen Verzeichnis übereinstimmt. In diesem Fall gleichen wir alle Dateien ab, die mit .scss im Stammordner (project) enden.
  2. **/*.scss: Dies ist eine extremere Version des Musters *, die mit jeder Datei übereinstimmt, die mit .scss im Stammordner und in allen untergeordneten Verzeichnissen endet.
  3. !not-me.scss: Das ! zeigt an, dass Gulp das Muster von seinen Übereinstimmungen ausschließen soll, was nützlich ist, wenn Sie eine Datei von einem übereinstimmenden Muster ausschließen mussten. In diesem Fall würde not-me.scss von der Übereinstimmung ausgeschlossen.
  4. *.+(scss|sass): Das Plus + und die Klammern () ermöglichen es Gulp, mehrere Muster abzugleichen, wobei die verschiedenen Muster durch das Pipe-Zeichen | getrennt sind. In diesem Fall gleicht Gulp alle Dateien ab, die mit .scss oder .sass im Stammordner enden.

Da wir jetzt Globbing kennen, können wir app/scss/styles.scss durch ein scss/**/*.scss-Muster ersetzen, das mit jeder Datei mit der Erweiterung .scss in app/scss oder einem untergeordneten Verzeichnis übereinstimmt.

gulp.task('sass', async function() {
  return gulp.src('app/scss/**/*.scss') // Gets all files ending with .scss in app/scss and children dirs
    .pipe(sass())
    .pipe(gulp.dest('app/css'))
})

Jede andere Sass-Datei, die in app/scss gefunden wird, würde mit dieser Änderung automatisch in die sass-Aufgabe aufgenommen. Wenn Sie eine Datei print.scss zum Projekt hinzufügen, sehen Sie, dass print.css in app/css generiert wird.

Wir haben es jetzt geschafft, alle Sass-Dateien mit einem einzigen Befehl in CSS-Dateien zu kompilieren. Die Frage ist, was nützt es, wenn wir jedes Mal, wenn wir Sass in CSS kompilieren möchten, gulp sass manuell ausführen müssen?

Glücklicherweise können wir Gulp anweisen, die sass-Aufgabe automatisch auszuführen, wenn eine Datei gespeichert wird, durch einen Prozess namens „Watching“.

Auf Änderungen von Sass-Dateien achten

Hinweis! Gulp Watch hat sich von 3.x zu 4.x stark verändert. Siehe die Dokumentation.

Gulp bietet uns eine watch-Methode, die überprüft, ob eine Datei gespeichert wurde. Die Syntax für die watch-Methode lautet:

// Gulp 3.x watch syntax
gulp.watch('files-to-watch', ['tasks', 'to', 'run']);

// NOTE! Gulp 4.x watch syntax (all the rest of the examples would need to be like this for Gulp 4
gulp.watch('files-to-watch', gulp.series(['tasks', 'to', 'run']));

Wenn wir alle Sass-Dateien beobachten und die sass-Aufgabe ausführen möchten, wenn eine Sass-Datei gespeichert wird, müssen wir files-to-watch nur durch app/scss/**/*.scss und ['tasks', 'to', 'run'] durch ['sass'] ersetzen:

// Gulp watch syntax
gulp.watch('app/scss/**/*.scss', ['sass']); 

Häufiger möchten wir jedoch mehrere Dateitypen gleichzeitig beobachten. Dazu können wir mehrere Watch-Prozesse zu einer watch-Aufgabe gruppieren:

gulp.task('watch', async function(){
  gulp.watch('app/scss/**/*.scss', ['sass']); 
  // Other watchers
})

Wenn Sie den Befehl gulp watch jetzt ausführen, sehen Sie, dass Gulp sofort mit dem Beobachten beginnt.

Und dass es die sass-Aufgabe automatisch ausführt, wenn Sie eine .scss-Datei speichern.

Gehen wir noch einen Schritt weiter und lassen Gulp den Browser neu laden, wenn wir eine .scss-Datei speichern, mithilfe von Browser Sync.

Live-Neuladen mit Browser Sync

Browser Sync erleichtert die Webentwicklung, indem es einen Webserver startet, der uns beim Live-Neuladen hilft. Es hat auch andere Funktionen, wie z. B. das Synchronisieren von Aktionen auf mehreren Geräten.

Wir müssen zuerst Browser Sync installieren:

$ npm install browser-sync --save-dev

Möglicherweise ist Ihnen aufgefallen, dass es kein gulp--Präfix gibt, wenn wir Browser Sync installieren. Das liegt daran, dass Browser Sync mit Gulp funktioniert, sodass wir kein Plugin verwenden müssen.

Um Browser Sync zu verwenden, müssen wir Browser Sync requiren.

var browserSync = require('browser-sync').create();

Wir müssen eine browserSync-Aufgabe erstellen, damit Gulp einen Server mit Browser Sync starten kann. Da wir einen Server betreiben, müssen wir Browser Sync mitteilen, wo sich der Stammordner des Servers befinden soll. In unserem Fall ist es der Ordner app:

gulp.task('browserSync', async function() {
  browserSync.init({
    server: {
      baseDir: 'app'
    },
  })
})

Wir müssen auch unsere sass-Aufgabe geringfügig ändern, damit Browser Sync neue CSS-Stile in den Browser injizieren (das CSS aktualisieren) kann, wenn die sass-Aufgabe ausgeführt wird.

gulp.task('sass', async function() {
  return gulp.src('app/scss/**/*.scss') // Gets all files ending with .scss in app/scss
    .pipe(sass())
    .pipe(gulp.dest('app/css'))
    .pipe(browserSync.reload({
      stream: true
    }))
});

Wir sind mit der Konfiguration von Browser Sync fertig. Jetzt müssen wir sowohl die watch- als auch die browserSync-Aufgabe gleichzeitig ausführen, damit das Live-Neuladen stattfindet.

Es wäre umständlich, zwei Befehlszeilenfenster zu öffnen und gulp browserSync und gulp watch separat auszuführen. Lassen wir Gulp sie also zusammen ausführen, indem wir der watch-Aufgabe mitteilen, dass browserSync abgeschlossen sein muss, bevor watch ausgeführt werden darf.

Wir können dies tun, indem wir der watch-Aufgabe ein zweites Argument hinzufügen. Die Syntax lautet:

gulp.task('watch', ['array', 'of', 'tasks', 'to', 'complete','before', 'watch'], async function (){
  // ...
})

Und in diesem Fall fügen wir die browserSync-Aufgabe hinzu.

gulp.task('watch', ['browserSync'], async function (){
  gulp.watch('app/scss/**/*.scss', ['sass']); 
  // Other watchers
})

Wir möchten auch sicherstellen, dass sass vor watch ausgeführt wird, damit das CSS bereits das neueste ist, wenn wir einen Gulp-Befehl ausführen.

gulp.task('watch', ['browserSync', 'sass'], async function (){
  gulp.watch('app/scss/**/*.scss', ['sass']); 
  // Other watchers
});

Wenn Sie nun gulp watch in der Befehlszeile ausführen, sollte Gulp sowohl die sass- als auch die browserSync-Aufgabe gleichzeitig starten. Wenn beide Aufgaben abgeschlossen sind, wird watch ausgeführt.

Gleichzeitig sollte ein Browserfenster geöffnet werden, das auf app/index.html verweist. Wenn Sie die Datei styles.scss ändern, sehen Sie, dass der Browser automatisch neu geladen wird.

Es gibt noch eine Sache, bevor wir diesen Abschnitt zum Live-Neuladen beenden. Da wir bereits auf .scss-Dateien achten, um neu zu laden, warum nicht einen Schritt weiter gehen und den Browser neu laden, wenn eine HTML- oder JavaScript-Datei gespeichert wird?

Wir können dies tun, indem wir zwei weitere Watch-Prozesse hinzufügen und die Funktion browserSync.reload aufrufen, wenn eine Datei gespeichert wird:

gulp.task('watch', ['browserSync', 'sass'], async function (){
  gulp.watch('app/scss/**/*.scss', ['sass']); 
  // Reloads the browser whenever HTML or JS files change
  gulp.watch('app/*.html', browserSync.reload); 
  gulp.watch('app/js/**/*.js', browserSync.reload); 
});

Bisher haben wir in diesem Tutorial drei Dinge erledigt:

  1. Starten eines Webservers für die Entwicklung
  2. Verwenden des Sass-Präprozessors
  3. Neuladen des Browsers, wenn eine Datei gespeichert wird

Gehen wir im nächsten Abschnitt auf die Optimierung von Assets ein. Wir beginnen mit der Optimierung von CSS- und JavaScript-Dateien.

CSS- und JavaScript-Dateien optimieren

Entwickler müssen zwei Aufgaben ausführen, wenn wir versuchen, CSS- und JavaScript-Dateien für die Produktion zu optimieren: Minifizierung und Verkettung.

Ein Problem, mit dem Entwickler bei der Automatisierung dieses Prozesses konfrontiert sind, ist die Schwierigkeit, ihre Skripte in der richtigen Reihenfolge zu verketten.

Angenommen, wir haben 3 Skript-Tags in index.html eingefügt.

  
  <script src="js/lib/a-library.js"></script>
  <script src="js/lib/another-library.js"></script>
  <script src="js/main.js"></script>

Diese Skripte befinden sich in zwei verschiedenen Verzeichnissen. Es wird schwierig sein, sie mit herkömmlichen Plugins wie gulp-concatenate zu verketten.

Glücklicherweise gibt es ein nützliches Gulp-Plugin, gulp-useref, das dieses Problem löst.

Gulp-useref verkettet beliebig viele CSS- und JavaScript-Dateien in eine einzige Datei, indem es nach einem Kommentar sucht, der mit „<!--build:“ beginnt und mit „<!--endbuild-->“ endet. Die Syntax lautet:


... HTML Markup, list of script / link tags.

kann entweder js, css oder remove sein. Es ist am besten, type auf den Dateityp einzustellen, den Sie verketten möchten. Wenn Sie type auf remove einstellen, entfernt Gulp den gesamten Build-Block, ohne eine Datei zu generieren.

bezieht sich hier auf den Zielpfad der generierten Datei.

Wir möchten, dass die endgültige JavaScript-Datei im Ordner js als main.min.js generiert wird. Daher lautet das Markup:


<script src="js/lib/a-library.js"></script>
<script src="js/lib/another-library.js"></script>
<script src="js/main.js"></script>

Konfigurieren wir nun das gulp-useref-Plugin im gulpfile. Wir müssen das Plugin installieren und im gulpfile anfordern.

$ npm install gulp-useref --save-dev
var useref = require('gulp-useref');

Das Einrichten der useref-Aufgabe ähnelt den anderen Aufgaben, die wir bisher erledigt haben. Hier ist der Code:

gulp.task('useref', async function(){
  return gulp.src('app/*.html')
    .pipe(useref())
    .pipe(gulp.dest('dist'))
});

Wenn Sie diese useref-Aufgabe jetzt ausführen, durchläuft Gulp die 3 Skript-Tags und verkettet sie zu dist/js/main.min.js.

Die Datei ist derzeit jedoch nicht minifiziert. Wir müssen das Plugin gulp-uglify verwenden, um JavaScript-Dateien zu minifizieren. Wir benötigen auch ein zweites Plugin namens gulp-if, um sicherzustellen, dass wir nur versuchen, JavaScript-Dateien zu minifizieren.

$ npm install gulp-uglify --save-dev 
// Other requires...
var uglify = require('gulp-uglify');
var gulpIf = require('gulp-if');

gulp.task('useref', function(){
  return gulp.src('app/*.html')
    .pipe(useref())
    // Minifies only if it's a JavaScript file
    .pipe(gulpIf('*.js', uglify()))
    .pipe(gulp.dest('dist'))
});

Gulp sollte jetzt automatisch die Datei main.min.js minifizieren, wenn Sie die useref-Aufgabe ausführen.

Eine tolle Sache, die ich noch nicht über Gulp-useref verraten habe, ist, dass es automatisch alle Skripte innerhalb von „<!--build:“ und „<!--endbuild-->“ in eine einzige JavaScript-Datei ändert, die auf js/main.min.js verweist.

Wunderbar, nicht wahr?

Wir können dieselbe Methode auch verwenden, um CSS-Dateien zu verketten (wenn Sie sich entschieden haben, mehr als eine hinzuzufügen). Wir folgen demselben Prozess und fügen einen build-Kommentar hinzu.




Wir können auch die verkettete CSS-Datei minifizieren. Wir müssen ein Paket namens gulp-cssnano verwenden, um uns bei der Minifizierung zu helfen.

$ npm install gulp-cssnano
var cssnano = require('gulp-cssnano');

gulp.task('useref', async function(){
  return gulp.src('app/*.html')
    .pipe(useref())
    .pipe(gulpIf('*.js', uglify()))
    // Minifies only if it's a CSS file
    .pipe(gulpIf('*.css', cssnano()))
    .pipe(gulp.dest('dist'))
});

Jetzt erhalten Sie eine optimierte CSS-Datei und eine optimierte JavaScript-Datei, wenn Sie die useref-Aufgabe ausführen.

Fahren wir nun fort und optimieren als Nächstes Bilder.

Bilder optimieren

Sie haben es wahrscheinlich schon erraten: Wir müssen gulp-imagemin verwenden, um uns bei der Optimierung von Bildern zu helfen.

$ npm install gulp-imagemin --save-dev
var imagemin = require('gulp-imagemin');

Wir können png, jpg, gif und sogar svg mit Hilfe von gulp-imagemin minifizieren. Erstellen wir eine images-Aufgabe für diesen Optimierungsprozess.

gulp.task('images', async function(){
  return gulp.src('app/images/**/*.+(png|jpg|gif|svg)')
  .pipe(imagemin())
  .pipe(gulp.dest('dist/images'))
});

Da verschiedene Dateitypen unterschiedlich optimiert werden können, möchten Sie möglicherweise Optionen zu imagemin hinzufügen, um anzupassen, wie jede Datei optimiert wird.

Sie können beispielsweise interlaced GIFs erstellen, indem Sie den Optionsschlüssel interlaced auf true setzen.

gulp.task('images', async function(){
  return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)')
  .pipe(imagemin({
      // Setting interlaced to true
      interlaced: true
    }))
  .pipe(gulp.dest('dist/images'))
});

Sie können auch mit anderen Optionen spielen, wenn Sie möchten.

Die Optimierung von Bildern ist jedoch ein extrem langsamer Prozess, den Sie nicht unnötig wiederholen möchten. Dazu können wir das Plugin gulp-cache verwenden.

$ npm install gulp-cache --save-dev
var cache = require('gulp-cache');

gulp.task('images', async function(){
  return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)')
  // Caching images that ran through imagemin
  .pipe(cache(imagemin({
      interlaced: true
    })))
  .pipe(gulp.dest('dist/images'))
});

Wir sind fast fertig mit dem Optimierungsprozess. Es gibt noch einen Ordner, den wir aus dem Verzeichnis app in dist übertragen müssen, das Schriftarten-Verzeichnis. Tun wir das jetzt.

Schriftarten nach Dist kopieren

Da Schriftartdateien bereits optimiert sind, müssen wir nichts weiter tun. Wir müssen die Schriftarten nur in dist kopieren.

Wir können Dateien mit Gulp kopieren, indem wir einfach gulp.src und gulp.dest ohne Plugins angeben.

gulp.task('fonts', async function() {
  return gulp.src('app/fonts/**/*')
  .pipe(gulp.dest('dist/fonts'))
})

Jetzt kopiert Gulp fonts von app nach dist, wenn Sie gulp fonts ausführen.

Wir haben jetzt 6 verschiedene Aufgaben im Gulpfile, und jede von ihnen muss einzeln über die Befehlszeile aufgerufen werden, was etwas umständlich ist, also möchten wir alles zu einem einzigen Befehl zusammenfassen.

Bevor wir das tun, sehen wir uns an, wie man generierte Dateien automatisch bereinigt.

Generierte Dateien automatisch bereinigen

Da wir Dateien automatisch generieren, möchten wir sicherstellen, dass nicht mehr verwendete Dateien nirgendwo verbleiben, ohne dass wir es wissen.

Dieser Prozess wird als Bereinigen (oder einfacher ausgedrückt, Löschen von Dateien) bezeichnet.

Wir müssen del verwenden, um uns beim Bereinigen zu helfen.

npm install del --save-dev
var del = require('del');

Die Funktion del verwendet ein Array von Node-Globs, das ihr mitteilt, welche Ordner gelöscht werden sollen.

Die Einrichtung mit einer Gulp-Aufgabe ähnelt fast dem ersten „hello“-Beispiel, das wir hatten.

gulp.task('clean:dist', async function() {
  return del.sync('dist');
})

Jetzt löscht Gulp den Ordner dist für Sie, wenn gulp clean:dist ausgeführt wird.

Hinweis: Wir müssen uns keine Sorgen um das Löschen des Ordners dist/images machen, da gulp-cache die Caches der Bilder bereits auf Ihrem lokalen System gespeichert hat.

Um die Caches von Ihrem lokalen System zu löschen, können Sie eine separate Aufgabe namens cache:clear erstellen:

gulp.task(‘cache:clear’, async function (callback) {
return cache.clearAll(callback)
})

Puh, das war eine Menge. Kombinieren wir nun alle unsere Aufgaben!

Gulp-Aufgaben kombinieren

Fassen wir zusammen, was wir getan haben. Bisher haben wir zwei verschiedene Sätze von Gulp-Aufgaben erstellt.

Der erste Satz ist für einen Entwicklungsprozess, bei dem wir Sass zu CSS kompiliert, auf Änderungen geachtet und den Browser entsprechend neu geladen haben.

Der zweite Satz ist für einen Optimierungsprozess, bei dem wir alle Dateien für die Produktions-Website vorbereiten. Wir haben Assets wie CSS, JavaScript und Bilder in diesem Prozess optimiert und Schriftarten von app nach dist kopiert.

Wir haben den ersten Satz von Aufgaben bereits zu einem einfachen Workflow mit dem Befehl gulp watch zusammengefasst:

gulp.task('watch', ['browserSync', 'sass'], function (){
  // ... watchers
})

Der zweite Satz besteht aus Aufgaben, die wir ausführen müssen, um die Produktions-Website zu erstellen. Dazu gehören clean:dist, sass, useref, images und fonts.

Wenn wir derselben Logik folgen würden, könnten wir eine build-Aufgabe erstellen, um alles zusammenzufassen:

gulp.task('build', [`clean`, `sass`, `useref`, `images`, `fonts`], async function (){
  console.log('Building files');
})

Leider könnten wir die build-Aufgabe nicht auf diese Weise schreiben, da Gulp alle Aufgaben im zweiten Argument gleichzeitig aktiviert.

Es besteht die Möglichkeit, dass useref, images oder sogar fonts abgeschlossen wird, bevor clean dies tut, was bedeutet, dass der gesamte Ordner dist gelöscht wird.

Um sicherzustellen, dass das Bereinigen vor dem Rest der Aufgaben abgeschlossen ist, müssen wir ein zusätzliches Plugin namens Run Sequence verwenden.

$ npm install run-sequence --save-dev

Hier ist die Syntax einer Aufgabenfolge mit Run Sequence:

var runSequence = require('run-sequence');

gulp.task('task-name', async function(callback) {
  runSequence('task-one', 'task-two', 'task-three', callback);
});

Wenn task-name aufgerufen wird, führt Gulp zuerst task-one aus. Wenn task-one beendet ist, startet Gulp automatisch task-two. Wenn task-two abgeschlossen ist, führt Gulp schließlich task-three aus.

Run Sequence ermöglicht es Ihnen auch, Aufgaben gleichzeitig auszuführen, wenn Sie sie in einem Array platzieren:

gulp.task('task-name', async function(callback) {
  runSequence('task-one', ['tasks','two','run','in','parallel'], 'task-three', callback);
});

In diesem Fall führt Gulp zuerst task-one aus. Wenn task-one abgeschlossen ist, führt Gulp jede Aufgabe im zweiten Argument gleichzeitig aus. Alle Aufgaben in diesem zweiten Argument müssen abgeschlossen sein, bevor task-three ausgeführt wird.

Wir können jetzt eine Aufgabe erstellen, die sicherstellt, dass clean:dist zuerst ausgeführt wird, gefolgt von allen anderen Aufgaben:

gulp.task('build', async function (callback) {
  runSequence('clean:dist', 
    ['sass', 'useref', 'images', 'fonts'],
    callback
  )
})

Um konsistent zu sein, können wir dieselbe Sequenz auch mit der ersten Gruppe erstellen. Verwenden wir dieses Mal default als Aufgabennamen:

gulp.task('default', async function (callback) {
  runSequence(['sass','browserSync', 'watch'],
    callback
  )
})

Warum default? Denn wenn Sie eine Aufgabe namens default haben, können Sie sie einfach ausführen, indem Sie den Befehl gulp eingeben, was einige Tastenanschläge spart.

Schließlich, hier ist ein GitHub-Repo für all unsere Arbeit!

Zusammenfassung

Wir haben die absoluten Grundlagen von Gulp durchgearbeitet und einen Workflow erstellt, der Sass in CSS kompilieren kann, während er gleichzeitig HTML- und JS-Dateien auf Änderungen überwacht. Wir können diese Aufgabe mit dem Befehl gulp in der Befehlszeile ausführen.

Wir haben auch eine zweite Aufgabe, build, erstellt, die einen Ordner dist für die Produktions-Website erstellt. Wir haben Sass in CSS kompiliert, alle unsere Assets optimiert und die notwendigen Ordner in den Ordner dist kopiert. Um diese Aufgabe auszuführen, müssen wir nur gulp build in die Befehlszeile eingeben.

Zuletzt haben wir eine clean-Aufgabe, die alle erstellten Bild-Caches aus dem generierten dist-Ordner entfernt, sodass wir alle alten Dateien entfernen können, die versehentlich in dist aufbewahrt wurden.

Wir haben bisher einen robusten Workflow erstellt, der für die meisten Webentwickler ausreichend ist. Es gibt noch viel mehr über Gulp und Workflows zu entdecken, um diesen Prozess noch besser zu machen. Hier sind einige Ideen für Sie:

Für die Entwicklung:

Für die Optimierung:

  • Entfernen von ungenutztem CSS mit unCSS
  • Weitere Optimierung von CSS mit CSSO
  • Generieren von Inline-CSS für die Leistung mit Critical

Zusätzlich zu Entwicklungs- oder Optimierungsprozessen können Sie auch JavaScript-Unit-Tests mit gulp-jasmine schreiben und Ihren Ordner dist sogar automatisch mit gulp-rync auf Ihrem Produktionsserver bereitstellen.

Wie Sie sehen, kann noch viel mehr getan werden, auch wenn der von uns erstellte Workflow bereits einiges leistet. Die Erstellung eines Workflows, der Ihren Anforderungen entspricht, kann äußerst spannend und erfüllend sein, aber es kann viel zu verarbeiten sein, wenn Sie neu darin sind.

Es gibt so viel mehr über Gulp zu sagen, dass es unmöglich ist, es in diesem Blogbeitrag oder sogar in einer Reihe von Beiträgen abzudecken. Aus diesem Grund habe ich ein Buch über die Automatisierung Ihres Workflows geschrieben, und ich lade Sie ein, zehn Kapitel kostenlos herunterzuladen, wenn Sie mehr erfahren möchten :)

Lassen Sie mich in den Kommentaren unten wissen, was Sie von diesem Artikel halten! Oh ja, zögern Sie nicht, mich zu kontaktieren, wenn Sie Fragen zum Workflow haben. Ich antworte gerne!