Im Dezember 2020 hat Flo eine neue Version dieses Artikel hier im KrautPress-Blog geschrieben.

Um einen Gutenberg-Block zu entwickeln, braucht es theoretisch nichts außer einem Text-Editor. Wer sich das Leben aber etwas leichter machen möchte (oder mindestens zunächst schwerer, wenn die Tools noch nicht bekannt sind), kann

  • Babel einsetzen, um mit modernem JavaScript zu entwickeln, das nach Kompilierung trotzdem auch von älteren Browsern verstanden wird
  • SASS einsetzen, um sich Schreibarbeit bei den Styles zu sparen und
  • ein Tool wie Webpack nutzen, um Babel und die SASS-Kompilierung (und eventuelle weitere Dinge, wie automatische Generierung eines SVG-Sprites aus vielen einzelnen SVG-Icons, et cetera) nicht immer manuell anstoßen zu müssen.

Hier zeige ich am Beispiel von Webpack ein minimales Setup, das modernes JavaScript mit Babel kompiliert und SASS zu CSS macht.

Update vom 1. Juni 2019: Der Beitrag zeigt jetzt die Nutzung des NPM-Pakets @wordpress/scripts, was die Einrichtung von Webpack und Babel deutlich erleichtert.

Voraussetzungen

Ich gehe davon aus, dass ihr

Außerdem könnt ihr innerhalb des wp-content/plugins-Ordners schon mal ein leeres Verzeichnis für das Plugin anlegen (oder zum Verzeichnis eines existierenden Plugins wechseln), für das ihr später Webpack nutzen wollt.

package.json erstellen und Abhängigkeiten installieren

Begebt euch über die Kommandozeile in das gerade erstellte Plugin-Verzeichnis und führt den Befehl npm init aus. Jetzt solltet ihr einige Dinge zum Ausfüllen bekommen und am Ende bestätigen können, dass eine package.json mit dem angezeigten Inhalt erstellt werden soll.

Nachdem ihr eine package.json vorliegen habt, müssen wir uns ans Installieren der Abhängigkeiten machen. Überlegen wir kurz, was wir brauchen:

  • Webpack
  • Babel
  • SASS-Kompilierer

Webpack und Babel installieren

Bis vor Kurzem mussten wir uns noch um die Installation der ganzen Abhängigkeiten selbst kümmern. Inzwischen bringt das NPM-Paket @wordpress/scripts alle Tools für einen grundlegenden Babel-Workflow via Webpack mit. Im Beitrag »Building JavaScript« auf make.wordpress.org gibt es nähere Details dazu.

Alles, was wir für die Installation von Webpack und Babel machen müssen, ist also:

npm install --save-dev @wordpress/scripts
Code-Sprache: Bash (bash)

SASS installieren

Kommen wir zum SASS-Teil. Wir brauchen zunächst verschiedene Loader, um das SASS über Webpack zu verarbeiten und als eigene Datei auszugeben. Mit PostCSS wollen wir automatisch den Autoprefixer über das Ergebnis laufen lassen.

npm install --save-dev css-loader extract-loader file-loader postcss-loader sass-loader
Code-Sprache: Bash (bash)

Jetzt kommen noch die Abhängigkeiten node-sass, autoprefixer und postcss-cli:

npm install --save-dev autoprefixer postcss-cli node-sassCode-Sprache: Bash (bash)

Konfigurationsdateien erstellen

Nachdem wir jetzt alle Abhängigkeiten installiert haben, machen wir uns an das Erstellen zweier Konfigurationsdateien. Eine für PostCSS und eine für Webpack, die die Standard-Konfiguration erweitert, die mit @wordpress/scripts geliefert wird. Die beiden Dateien kommen auf dieselbe Ebene wie die package.json.

PostCSS konfigurieren

Die postcss.config.js sieht so aus:

module.exports = {
	plugins: {
		autoprefixer: { grid: true }
	}
}
Code-Sprache: JavaScript (javascript)

Wir möchten den Autoprefixer nutzen und auch alte CSS-Grid-Syntax nachrüsten. Die Liste der unterstützten Browser geben wir über die package.json an:

"browserslist": [
  "extends @wordpress/browserslist-config"
],
Code-Sprache: JSON / JSON mit Kommentaren (json)

Damit werden dieselben Browser berücksichtigt, die offiziell von WordPress unterstützt werden. Über npx autoprefixer --info könnt ihr euch anzeigen lassen, welche Browser das sind und welche Eigenschaften und Werte betroffen sind.

Damit das funktioniert, müssen wir dieses NPM-Paket noch installieren:

npm install --save-dev @wordpress/browserslist-config
Code-Sprache: Bash (bash)

Webpack konfigurieren

Wenn man mit Webpack nur JavaScript kompilieren möchte und nur eine Datei hätte, bräuchte man keine eigene Konfiguration zu erstellen. @wordpress/scripts bringt bereits eine mit, die eine src/index.js zu einer build/index.js kompiliert.

Das reicht uns allerdings nicht, deshalb erstellen wir für Webpack eine webpack.config.js-Datei und füllen sie mit dem folgenden Inhalt, um die Standard-Konfiguration zu erweitern (diese Basis-Webpack-Konfiguration findet ihr im GitHub-Repo des @wordpress/scripts-Pakets):

const defaultConfig = require("./node_modules/@wordpress/scripts/config/webpack.config");
const path = require('path');
module.exports = {
	...defaultConfig,
	entry: ['./blocks/index.js', './blocks/editor.scss', './blocks/frontend.scss'],
	output: {
		path: path.resolve(__dirname, 'assets'),
		filename: 'js/editor.blocks.js',
	},
	module: {
		rules: [
			/**
			 * Running Babel on JS files.
			 */
			...defaultConfig.module.rules,
			{
				test: /\.scss$/,
				use: [
					{
						loader: 'file-loader',
						options: {
							name: 'css/[name].blocks.css',
						}
					},
					{
						loader: 'extract-loader'
					},
					{
						loader: 'css-loader?-url'
					},
					{
						loader: 'postcss-loader'
					},
					{
						loader: 'sass-loader'
					}
				]
			}
		]
	}
};
Code-Sprache: JavaScript (javascript)

Gehen wir die Datei der Reihe nach durch:

  1. In defaultConfig speichern wir die Konfigurationsdatei des @wordpress/scripts-Pakets, auf die wir aufbauen wollen.
  2. In path speichern wir uns das Node-Modul path, um später den Pfad zum Ausgabeverzeichnis der Dateien anzugeben.
  3. Innerhalb von module.exports leben die konkreten Angaben zur Konfiguration von Webpack.
  4. Über ...defaultConfig kippen wir erst mal die Werte der Standard-Konfiguration rein. Es folgen die Punkte, die wir im Vergleich zum Standard anpassen wollen.
  5. Mit entry geben wir als Array die Quelldateien an (die könnt ihr in dem Zuge direkt einmal erstellen). Wir haben im blocks-Verzeichnis eine JavaScript-Datei sowie zwei SASS-Dateien.
  6. Über output legen wir fest, dass der Ausgabepfad assets sein soll und die JavaScript-Datei innerhalb von assets in ein Unterverzeichnis js mit dem Namen editor.blocks.js abgespeichert wird.
  7. In module legen wir die Regeln fest, die für die entry-Dateien angewandt werden sollen.
    1. Wir beginnen mit den Regeln der Standard-Konfiguration, die wir über ...defaultConfig.module.rules einfügen. Damit ist die Kompilierung der JavaScript-Datei bereits erledigt.
    2. Für alle .scss-Dateien sollen mehrere Loader ausgeführt werden, die letztlich das SASS in CSS kompilieren und das Ergebnis nach dem Schema [name].blocks.css innerhalb des css-Verzeichnisses ablegen. Wir haben also dann zwei CSS-Dateien assets/css/editor.blocks.css und assets/css/frontend.blocks.css als Ergebnis. Ich bin nicht ganz sicher, warum zum Beispiel der extract-loader notwendig ist, aber ohne funktioniert es nicht 🙂

Einfach und intuitiv ist die Webpack-Konfiguration nicht wirklich, aber wenn man sich erst mal ein funktionierendes Grund-Setup zusammengesucht hat, kann man es ja in neuen Projekten wiederverwenden und bei Bedarf erweitern/anpassen.

NPM-Skripte für den Einsatz von Webpack erstellen

Für den Aufruf von Webpack erstellen wir jetzt noch zwei NPM-Skripte und schreiben dafür folgendes in die package.json, wie es im Beitrag zu dem @wordpress/scripts-Package beschrieben ist:

"scripts": {
  "start": "wp-scripts start",
  "build": "wp-scripts build"
}
Code-Sprache: JSON / JSON mit Kommentaren (json)

Über npm run start können wir Webpack für die Entwicklung ausführen lassen, wobei dann auch gleich auf Änderungen an den Dateien gewartet wird. Mit npm run build kompilieren wir die Dateien für den Live-Betrieb. Eventuell werdet ihr beim ersten mal aufgefordert, ein Webpack-CLI zu wählen, das dann global installiert wird.

Jetzt können wir mit den Dateien blocks/index.js, blocks/editor.scss und blocks/frontend.scss arbeiten und bekommen durch den Aufruf von Webpack Ausgabedateien in assets, die das Plugin einbinden kann.

Im nächsten Artikel werden wir um die Konfiguration ein kleines funktionierendes Plugin erstellen.

24 Kommentare zu “Einrichtung von Webpack für die Gutenberg-Entwicklung

  1. Deutlich einfacher (genau genommen zwei Zeilen) ist die Konfiguration von Webpack & Babel mit Hilfe von Laravel Mix (einem Wrapper um Webpack, Laravel hat sonst damit erst einmal nichts zu tun). Funktioniert auch für die Entwicklung von Gutenberg-Plugins wunderbar.

    Einfach wie hier vorgegeben für ein Stand-Alone-Project im Plugin-Ordner installieren (genau wie Webpack): https://laravel-mix.com/docs/4.0/installation#stand-alone-project

    und im webpack.mix.js folgendes Eintragen:

    let mix = require(‚laravel-mix‘);
    mix.react(‚blocks/index.js‘, ‚js/editor.blocks.js‘);

    mix.react (https://laravel-mix.com/docs/4.0/mixjs#react-support) sorgt für das passende JSX-Babel-Plugin.

    Die passenden NPM-Scripts findet man hier: https://laravel-mix.com/docs/4.0/installation#npm-scripts

    Natürlich kann man auch beliebige CSS Preprocessors mit Laravel Mix nutzen: https://laravel-mix.com/docs/4.0/css-preprocessors Ebenfalls einfach und deutlich weniger fehleranfällig als

    • Hi Johannes,

      danke für deinen Kommentar und das Aufzeigen der Alternative! Ja, von Laravel Mix habe ich auch schon das ein oder andere Mal gehört. Falls möglich gehe ich aber gerne den direkten Weg, ohne mir noch mehr Abhängigkeiten aufzuladen als Webpack und Co. sowieso schon mitbringen 🙂

      Viele Grüße
      Florian

    • Tatsächlich finde ich Ahmad Awais‘ create-guten-block noch einfacher zu nutzen. Und Ahmads Toolkit hat den Vorteil, dass es neben den Webpack und co keine zusätzlichen Abhängigkeiten eingeführt werden. Es bietet sogar die explizite Option, ein Projekt mit den grundlegenden Tools weiter zu entwickeln und auf das Toolkit zu verzichten.

      Aber weil es nie schaden kann, sich mit dem Handwerkszeug auszukennen, mit dem man täglich arbeitet, halte ich den Weg, den Flo hier beschrieben hat, erstmal für den, mit dem man sich beschäftigen sollte.

  2. Schön geschrieben. Bliebe zu ergänzen, dass die Richtung „macht Blöcke statt Meta-Boxen“ nicht nur mit erhöhtem Aufwand, sondern auch mit verminderter Funktionalität einhergeht, z.B. bei Validierung von Daten. s. z.B. https://github.com/WordPress/gutenberg/issues/4063

    Wenn dann noch die für die Abbildung komplexer Informationsmodelle eh wenig taugliche Datenhaltung durch Gutenberg und seine Kommentar-Speicherung noch verschlimmert wird, ist WordPress für viele Agenturen als Plattform für anspruchsvollere Web-Applikationen tot. Ist aber wahrscheinlich auch gar nicht gewollt.

    Reales Beispiel:
    Kunde: „Können wir im News-Archiv die erste Pullquote dazuschreiben?“
    Anderes CMS: „Klar. Gib mir 10 Minuten“
    WordPress mit Gutenberg: „Nein. Ich kann leider meine eigenen Daten nicht verarbeiten. Aber du kannst den Hintergrund bunt machen!“

    • Hallo Werner,

      danke für deinen Kommentar und das Lob 🙂

      Zu den Meta-Boxen: damit habe ich mich bisher noch nicht auseinandergesetzt, aber ist ein wichtiger Punkt, das stimmt.

      Ja, das mit der Datenspeicherung ist auch ein Punkt den ich schade finde. Es gibt die Möglichkeit, die Blöcke eines Eintrags als Array zu bekommen ($blocks = parse_blocks( get_the_content() );) und dann beispielsweise das erste Pullquote woanders anzuzeigen, aber ist halt ein Umweg.

      Viele Grüße
      Florian

      • Korrigiert mich: Der eigentliche Pullquote-Inhalt steht irgendwo im HTML-Klumpen und muss da erst rausgeparst werden. Die Definition dazu hat aber nur der Client per Javascript und nicht der Server. Und selbst per Hand das erste p-tag im ersten blockquote-tag im ersten figure-tag rausfieseln möchte ich gar nicht erst anfangen. Von Performance in einer Liste von 30 News-Artikeln mal gar nicht zu reden. Und von ‚deprecated blocks‘ auch nicht.

        Ich will da nicht drauf rumreiten, aber ein halbwegs systemtechnisch bewanderter Business-Kunde bewertet sowas als (Zitat) „konzeptionell absurd“ und landet bei einer WP-Alternative. Und das m.E. zu Recht.

        Grüße und lasst euch von mir nicht die Laune verderben.
        Werner

        • Hallo Werner,

          ja, ein Beitrag ist weiterhin ein HTML-Klumpen in einem DB-Eintrag, korrekt. Aber du kannst über die von mir gepostete Code-Zeile via PHP ein Array bekommen, das alle Blöcke als Untereinträge enthält. Und in jedem Untereintrag hast du dann den Typ des jeweiligen Blocks, Inhalt, et cetera. Das macht WordPress intern – meine ich – grob genau so bevor es den Beitrag anzeigt. Und aus dem Array könnte man sich dann den Pullquote-Eintrag raussuchen und den im Theme dann irgendwo anzeigen. Ich habe das für ein Projekt genutzt, um einen Slider-Shortcode vor dem Titel eines Beitrags auszugeben, statt normal an der Stelle, wo er im Inhalt steht.

          Zur Performance: Ja, die wird darunter vermutlich ein wenig leiden. Eventuell könnte man einfach den Core-Filter für das Parsen abstellen, dann hätte man nur noch den aus dem Theme. Aber wie gesagt: klar, das ist ein Umweg und nicht so schön wie es bei anderen CMS möglich ist, die die Inhaltsblöcke getrennt in der DB speichern.

          »Grüße und lasst euch von mir nicht die Laune verderben.«

          Keine Sorge, lass ich nicht 😀 Sind ja alles auch berechtigte Punkte, die du ansprichst, die ich selbst auch störend finde.

          Viele Grüße
          Florian

          • Schick, aber dröselt das auch den HTML-Inhalt eines einzelnen Blocks auf, wenn ich nicht den gesamten Block verwenden, sondern nur auf ein einzelnes im „innerHTML“ enthaltenes Attribut zugreifen will?

          • Nein, da gibt es nur das gesamte HTML des Blocks zurück (ohne die Kommentare). Du bekommst die Block-Attribute als Unter-Array (also zum Beispiel bei einem Bild die Ausrichtung), aber nicht alle HTML-Elemente noch mal aufgedröselt.

        • Hi Werner,

          Ich will da nicht drauf rumreiten, aber ein halbwegs systemtechnisch bewanderter Business-Kunde bewertet sowas als (Zitat) „konzeptionell absurd“ und landet bei einer WP-Alternative. Und das m.E. zu Recht.

          falls du auf Anhieb 1-2 Alternativen nennen könntest, dann wäre das super. Ist zwar schon was länger her, dass ich was getestet habe, aber irgendwie hat mich nicht wirklich etwas überzeugt. Vielleicht hat sich in den letzten Jahren was getan.

          • Hallo Vlad,

            für die individuelleren Projekte ist für uns Craft CMS die erste Wahl. https://craftcms.com/ und ein Überblick in https://nystudio107.com/blog/craft-cms-3-orientation-guide-welcome

            Typischer Fall wäre z.B. eine Site für ein internationales Filmfestival, wo es ein sehr individuelles Layout, Mehrsprachigkeit und stark strukturierten, vernetzten Content gibt (sowas wie „Frau X spielt im romänischen Kurzfilm Y von 2017 die Rolle Z und wird deutsch von Frau A synchronisiert, er wird am … im Kino … gezeigt und läuft in der Reihe .. unter dem Jurypräsidenten …). Das bitte in allen Richtungen abfragbar.

            Ist also dann eine Alternative, wenn WordPress mit der Kunst am Ende ist. Projekte bei denen es mit WP genauso geht, werden auch weiterhin damit gemacht.

            Zu den Drupals & Co. dieser Welt kann ich nichts sagen, ProcessWire könnte man sich auch genauer anschauen.

            Gruß
            Werner

  3. Toll! Wie ich so oft sehe, funktioniert der Webpack Watcher leider nicht mit der üblichen Konfiguration. Dies muss ich üblicherweise mit `watchOptions.poll` in der webpack.config.js umgehen, was bei deinem Beispiel aber auch nicht funktionierte. Ist das ein Missverständnis auf meiner Seite, oder ein übliches Problem?

    Mentions

  • User Avatar 💬 WordCamp Osnabrück, Pluginkollektiv und Gutenberg – WP Letter

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert