Gutenberg lernen: Einrichten einer benutzerdefinierten webpack Konfiguration

Avatar of Andy Bell
Andy Bell am

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

Gutenberg bringt den modernen JavaScript-Stack in das WordPress-Ökosystem, was bedeutet, dass einige neue Werkzeuge erlernt werden müssen. Obwohl Tools wie create-guten-block unglaublich nützlich sind, ist es auch hilfreich zu wissen, was unter der Haube vor sich geht.

Artikelserie

  1. Reihen-Einführung
  2. Was ist Gutenberg eigentlich?
  3. Eine Einführung mit create-guten-block
  4. Moderne JavaScript-Syntax
  5. React 101
  6. Einrichten einer benutzerdefinierten webpack-Konfiguration (Dieser Beitrag)
  7. Ein benutzerdefinierter "Card"-Block
Die Dateien, die wir hier konfigurieren werden, sollten Ihnen aus dem vertraut sein, was wir im Teil 2 Primer mit create-guten-block behandelt haben. Wenn Sie wie ich sind (bevor Sie Andy's Tutorial gelesen haben!), und sich noch nicht gleich in den Konfigurationsteil stürzen möchten, stimmt das von create-guten-block erstellte Gerüst mit dem überein, was wir hier erstellen werden, sodass Sie das auch sicherlich verwenden können.

Legen wir los!

Erste Schritte

Webpack nimmt die kleinen, modularen Aspekte Ihres Front-End-Codes und fasst sie zu einer effizienten Datei zusammen. Es ist hoch erweiterbar und konfigurierbar und das schlagende Herz einiger der beliebtesten Produkte und Projekte im Web. Es ist sehr viel ein JavaScript-Tool, obwohl es für praktisch alles verwendet werden kann, was Sie möchten. Für dieses Tutorial liegt der Fokus jedoch ausschließlich auf JavaScript.

Was wir von webpack tun lassen werden, ist, unsere Änderungen an einigen benutzerdefinierten Blockdateien zu beobachten und sie mit Babel zu kompilieren, um JavaScript-Dateien zu generieren, die von den meisten Browsern gelesen werden können. Es wird auch alle von uns importierten Abhängigkeiten zusammenführen.

Aber zuerst brauchen wir einen Ort, an dem wir unsere eigentliche webpack-Einrichtung und unsere Front-End-Dateien speichern können. In Teil 2 haben wir beim Durchsehen der von create-guten-block generierten Dateien gesehen, dass es eine Infrastruktur für ein WordPress-Plugin erstellt hat, das unsere Front-End-Dateien auf WordPress-Art in das System eingespielt und uns ermöglicht hat, das Plugin über WordPress zu aktivieren. Ich werde diesen nächsten Abschnitt dazu nutzen, Sie durch die Einrichtung der Infrastruktur für ein WordPress-Plugin für unseren benutzerdefinierten Block zu führen.

Einrichten eines Plugins

Hoffentlich haben Sie noch eine lokale WordPress-Instanz laufen, die von unserem Primer in Teil 2 stammt, aber wenn nicht, müssen Sie eine installiert haben, um mit dem fortzufahren, was wir als Nächstes tun werden. Navigieren Sie in dieser Installation zu wp-content/plugins und erstellen Sie ein neues Verzeichnis namens card-block (Spoiler-Alarm: Wir werden einen Kartenblock erstellen... wer mag keine Karten?).

Erstellen Sie dann innerhalb von card-block eine Datei namens card-block.php. Dies wird das Äquivalent zu plugin.php aus create-guten-block sein. Fügen Sie als Nächstes diesen Kommentarblock ein, um WordPress mitzuteilen, dass es dieses Verzeichnis als Plugin erkennen und es auf der Plugins-Seite des Dashboards anzeigen soll.

<?php
   /*
   Plugin Name: Card Block
   */

Vergessen Sie nicht das öffnende PHP-Tag, aber Sie können das schließende weglassen, da wir bald mehr zu dieser Datei hinzufügen werden.

WordPress sucht nach diesen Kommentaren, um ein Plugin zu registrieren, genauso wie es nach Kommentaren am Anfang von style.css in einem Theme sucht. Dies ist eine verkürzte Version dessen, was Sie am Anfang der Hauptdateien anderer Plugins finden werden. Wenn Sie planen würden, es im WordPress-Plugin-Repository zu veröffentlichen, würden Sie eine Beschreibung und eine Versionsnummer sowie Lizenz- und Autoreninformationen hinzufügen wollen.

Aktivieren Sie das Plugin über das WordPress-Dashboard, und ich übernehme das Steuer wieder, um Sie durch die Einrichtung unserer Webpack-Konfiguration zu führen!

Erste Schritte mit Webpack

Das Erste, was wir tun werden, ist die Initialisierung von npm. Führen Sie das im Stammverzeichnis Ihres Plugin-Ordners (wp-content/plugins/card-block) aus:

npm init

Dies wird Ihnen ein paar Fragen zu Ihrem Projekt stellen und letztendlich eine package.json-Datei generieren, die Abhängigkeiten auflistet und Kerninformationen über Ihr Projekt speichert.

Installieren wir als Nächstes webpack:

npm install webpack --save-dev

Sie haben vielleicht bemerkt, dass wir webpack lokal zu unserem Projekt installieren. Dies ist eine gute Praxis für entscheidende Pakete, die anfällig für große, umwälzende Änderungen sind. Es bedeutet auch, dass Sie und Ihr Team alle auf dem gleichen Stand sind.

Führen Sie dann dies aus:

npm install extract-text-webpack-plugin@next --save-dev

Dann diese Sass- und CSS-Abhängigkeiten:

npm install node-sass sass-loader css-loader --save-dev

# J Parenti wrote in to say that in Babel 7, it's different. You may need to:
npm uninstall --save-dev sass-loader
npm install --save-dev [email protected]

Jetzt NPX, um uns zu erlauben, unsere lokalen Abhängigkeiten anstelle von globalen zu verwenden:

npm install npx -g

Führen Sie zuletzt Folgendes aus:

npm install webpack-cli --save-dev

Dies wird das Webpack CLI für Sie installieren.

Jetzt, da wir dies installiert haben, sollten wir unsere Konfigurationsdatei erstellen. Immer noch im Stammverzeichnis Ihres Plugins, erstellen Sie eine Datei namens webpack.config.js und öffnen Sie diese Datei, damit wir codieren können.

Mit dieser webpack-Datei werden wir mit traditionellem ES5-Code für maximale Kompatibilität arbeiten, da er mit Node JS läuft. Sie können ES6 und Babel verwenden, aber wir werden die Dinge für dieses Tutorial so einfach wie möglich halten.

Okay, fügen wir einige Konstanten und Imports hinzu. Fügen Sie Folgendes ganz oben in Ihre Datei webpack.config.js ein:

var ExtractText = require('extract-text-webpack-plugin');
var debug = process.env.NODE_ENV !== 'production';
var webpack = require('webpack');

Die Variable debug deklariert, ob wir uns im debug-Modus befinden oder nicht. Dies ist unser Standardmodus, kann aber durch Voranstellen unserer webpack-Befehle mit NODE_ENV=production überschrieben werden. Das boolesche Flag debug bestimmt, ob webpack Sourcemaps generiert und den Code minimiert.

Wie Sie sehen können, fordern wir einige Abhängigkeiten an. Wir wissen, dass webpack benötigt wird, also überspringen wir das. Konzentrieren wir uns stattdessen auf ExtractText. Im Wesentlichen ermöglicht uns ExtractText, andere Dateien als JavaScript in den Mix einzubinden. Wir werden dies für unsere Sass-Dateien benötigen. Standardmäßig nimmt webpack an, dass alles JavaScript ist, daher *übersetzt* ExtractText die anderen Dateitypen.

Fügen wir nun einige Konfigurationen hinzu. Fügen Sie Folgendes nach der webpack-Definition ein:

var extractEditorSCSS = new ExtractText({
  filename: './blocks.editor.build.css'
});

var extractBlockSCSS = new ExtractText({
  filename: './blocks.style.build.css'
});

Dort haben wir zwei Instanzen von ExtractText instanziiert, indem wir ein Konfigurationsobjekt übergeben haben. Alles, was wir eingestellt haben, ist die Ausgabe unserer beiden Block-Stylesheets. Darauf werden wir in der nächsten Serie eingehen, aber im Moment müssen Sie nur wissen, dass dies der erste Schritt zur Kompilierung unseres Sass ist.

OK, fügen Sie nach dem letzten Code-Schnipsel Folgendes hinzu:

var plugins = [ extractEditorSCSS, extractBlockSCSS ];

Hier haben wir zwei Plugin-Arrays. Unsere ExtractText-Instanzen befinden sich im Kern-Plugin-Set, und wir haben ein paar Optimierungs-Plugins, die nur dann in das Kern-Plugin-Set integriert werden, wenn wir uns nicht im debug-Modus befinden. Wir führen diese Logik ganz am Ende aus.

Als Nächstes fügen Sie diese SCSS-Konfiguration hinzu:

var scssConfig = {
  use: [
    {
      loader: 'css-loader'
    },
    {
      loader: 'sass-loader',
      options: {
        outputStyle: 'compressed'
      }
    }
  ]
};

Dieses Objekt wird unserer webpack-Instanz sagen, wie sie sich verhalten soll, wenn sie auf scss-Dateien stößt. Wir haben es in einem Konfigurationsobjekt, um die Dinge so DRY wie möglich zu halten.

Zuletzt, das Herz und die Seele der Konfiguration:

module.exports = {
  context: __dirname,
  devtool: debug ? 'inline-sourcemap' : null,
  mode: debug ? 'development' : 'production',
  entry: './blocks/src/blocks.js',
  output: {
    path: __dirname + '/blocks/dist/',
    filename: 'blocks.build.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader'
          }
        ]
      },
      {
        test: /editor\.scss$/,
        exclude: /node_modules/,
        use: extractEditorSCSS.extract(scssConfig)
      },
      {
        test: /style\.scss$/,
        exclude: /node_modules/,
        use: extractBlockSCSS.extract(scssConfig)
      }
    ]
  },
  plugins: plugins
};

Das ist unsere gesamte Konfiguration, also lassen Sie sie uns aufschlüsseln.

Das Skript beginnt mit module.exports, was im Wesentlichen bedeutet: „Wenn Sie mich importieren oder anfordern, bekommen Sie das.“ Wir können bestimmen, was wir demjenigen, der unseren Code importiert, zur Verfügung stellen, was bedeutet, dass wir Code über module.exports ausführen könnten, der z. B. schwere Berechnungen durchführt.

Betrachten wir als Nächstes einige der folgenden Eigenschaften:

  • context ist unsere Basis, von der aus Pfade aufgelöst werden. Wir haben __dirname übergeben, was das aktuelle Arbeitsverzeichnis ist.
  • devtool ist, wo wir definieren, welche Art von Sourcemap wir wollen oder nicht wollen. Wenn wir uns nicht im debug-Modus befinden, übergeben wir null mit einem ternären Operator.
  • entry ist, wo wir webpack sagen, dass es seine Pack-Reise beginnen soll. In unserem Fall ist dies der Pfad zu unserer blocks.js-Datei.
  • output ist, was draufsteht. Wir übergeben ein Objekt, das den Ausgabepfad und den Dateinamen definiert, den wir verwenden möchten.

Als Nächstes kommt module, auf das wir noch etwas detaillierter eingehen werden. Der Abschnitt module kann mehrere Regeln enthalten. In unserem Fall sucht die einzige rule nach JavaScript- und SCSS-Dateien. Dies geschieht durch Suchen mit einem regulären Ausdruck, der durch die Eigenschaft test definiert ist. Das Endziel der Regel ist es, die richtigen Dateitypen zu finden und sie an einen Loader zu übergeben, der in unserem Fall babel-loader ist. Wie wir in einem früheren Tutorial dieser Serie gelernt haben, konvertiert Babel unseren modernen ES6-Code in besser unterstützten ES5-Code.

Zuletzt kommt unser Plugins-Abschnitt. Hier übergeben wir unser Array von Plugin-Instanzen. In unserem Projekt haben wir Plugins, die Code minimieren, Duplikate entfernen und die Länge häufig verwendeter IDs reduzieren. Dies dient alles dazu, sicherzustellen, dass unser Produktionscode optimiert ist.

Zur Referenz, so sollte Ihre vollständige Konfigurationsdatei aussehen:

var ExtractText = require('extract-text-webpack-plugin');
var debug = process.env.NODE_ENV !== 'production';
var webpack = require('webpack');

var extractEditorSCSS = new ExtractText({
  filename: './blocks.editor.build.css'
});

var extractBlockSCSS = new ExtractText({
  filename: './blocks.style.build.css'
});

var plugins = [extractEditorSCSS, extractBlockSCSS];

var scssConfig = {
  use: [
    {
      loader: 'css-loader'
    },
    {
      loader: 'sass-loader',
      options: {
        outputStyle: 'compressed'
      }
    }
  ]
};

module.exports = {
  context: __dirname,
  devtool: debug ? 'inline-sourcemap' : null,
  mode: debug ? 'development' : 'production',
  entry: './blocks/src/blocks.js',
  output: {
    path: __dirname + '/blocks/dist/',
    filename: 'blocks.build.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader'
          }
        ]
      },
      {
        test: /editor\.scss$/,
        exclude: /node_modules/,
        use: extractEditorSCSS.extract(scssConfig)
      },
      {
        test: /style\.scss$/,
        exclude: /node_modules/,
        use: extractBlockSCSS.extract(scssConfig)
      }
    ]
  },
  plugins: plugins
};
Das ist webpack konfiguriert. Ich übernehme wieder das Mikrofon, um uns zu zeigen, wie wir unseren Block offiziell bei WordPress registrieren. Das sollte für diejenigen von Ihnen, die mit Aktionen und Filtern in WordPress vertraut sind, ziemlich vertraut vorkommen.

Registrieren unseres Blocks

Zurück in card-block.php ist unsere Hauptaufgabe nun, die JavaScript- und CSS-Dateien einzubinden, die wir mit webpack erstellen werden. In einem Theme würden wir dies tun, indem wir wp_enqueue_script und wp_enqueue_style innerhalb einer Aktion aufrufen, die zu wp_enqueue_scripts hinzugefügt wird. Wir tun im Wesentlichen dasselbe hier, außer dass wir die Skripte und Stile mit einer Funktion einbinden, die speziell für Blöcke ist.

Fügen Sie diesen Code unter dem öffnenden Kommentar in card-block.php ein:

function my_register_gutenberg_card_block() {

  // Register our block script with WordPress
  wp_register_script(
    'gutenberg-card-block',
    plugins_url('/blocks/dist/blocks.build.js', __FILE__),
    array('wp-blocks', 'wp-element', 'wp-editor')
  );

  // Register our block's base CSS  
  wp_register_style(
    'gutenberg-card-block-style',
    plugins_url( '/blocks/dist/blocks.style.build.css', __FILE__ ),
    array( 'wp-blocks' )
  );
  
  // Register our block's editor-specific CSS
  if( is_admin() ) :
     wp_register_style(
      'gutenberg-card-block-edit-style',
      plugins_url('/blocks/dist/blocks.editor.build.css', __FILE__),
      array( 'wp-edit-blocks' )
    );
  endif;
  
  // Enqueue the script in the editor
  register_block_type('card-block/main', array(
    'editor_script' => 'gutenberg-card-block',
    'editor_style' => 'gutenberg-card-block-edit-style',
    'style' => 'gutenberg-card-block-edit-style'
  ));
}

add_action('init', 'my_register_gutenberg_card_block');

Wie die obigen Kommentare anzeigen, registrieren wir zuerst unser Skript bei WordPress unter dem Handle gutenberg-card-block mit zwei Abhängigkeiten: wp-blocks und wp-elements. Diese Funktion registriert nur ein Skript, sie bindet es nicht ein. Wir tun etwas Ähnliches für unsere Edit- und Haupt-Stylesheets.

Unsere abschließende Funktion, register_block_type, übernimmt das Einbinden für uns. Sie gibt dem Block auch einen Namen, card-block/main, der diesen Block als den main-Block innerhalb des Namespace card-block identifiziert, und identifiziert dann das gerade registrierte Skript und die Styles als das Haupt-Editor-Skript, die Editor-Stylesheet und das primäre Stylesheet für den Block.

Wenn Sie mit der Theme-Entwicklung vertraut sind, haben Sie wahrscheinlich get_template_directory() verwendet, um Dateipfade in Hooks wie den oben genannten zu verarbeiten. Für die Plugin-Entwicklung verwenden wir die Funktion plugins_url(), die so ziemlich dasselbe tut, außer dass sie anstelle der Verkettung eines Pfads wie folgt: get_template_directory() . '/script.js', akzeptiert plugins_url() einen String-Pfad als Parameter und erledigt die Verkettung für uns. Der zweite Parameter, __FILE__, ist eine von PHP's Magic Constants, die dem vollständigen Dateipfad der aktuellen Datei entspricht.

Schließlich, wenn Sie weitere Blöcke zu diesem Plugin hinzufügen möchten, bräuchten Sie eine Version dieser Funktion für jeden Block. Sie könnten herausfinden, was variabel ist, und eine Art Schleife generieren, um es schön und DRY zu halten, weiter unten. Jetzt führe ich Sie durch das Einrichten von Babel.

Babel zum Laufen bringen

Babel wandelt unseren ES6-Code in besser unterstützten ES5-Code um, also müssen wir einige Abhängigkeiten installieren. Führen Sie im Stammverzeichnis Ihres Plugins (wp-content/plugins/card-block) Folgendes aus:

npm install babel-core babel-loader babel-plugin-add-module-exports babel-plugin-transform-react-jsx babel-preset-env --save-dev

Update April 2019: Wir hatten in den letzten Monaten viele Updates zu diesem Thema, aufgrund der großen Änderung in Babel von 6 auf 7. Danke an Nina Regli, Rick Hughs und Bryan Chong.<.p>

Nina hatte Glück mit:

npm install --save-dev @babel/core @babel/preset-env

Rick hatte Glück mit:

npm install @babel/core babel-loader babel-plugin-add-module-exports babel-plugin-transform-react-jsx @babel/preset-env --save-dev

Bryan hatte Glück mit:

npm install --save-dev @babel/preset-react babel-preset-minify @babel/core @babel/cli @babel/preset-en

Bryan hat auch `.babelrc` in `babel.config.js` umbenannt und es wie folgt konfiguriert:

module.exports = function (api) {
  return {
    presets: [
      [
        "@babel/preset-react",
        {
          "pragma": "wp.element.createElement"
        }
      ],
      "minify",
      "@babel/env"
    ]
  };
}

Dieses große npm install fügt alle Babel-Abhängigkeiten hinzu. Jetzt können wir unsere .babelrc-Datei hinzufügen, die einige Einstellungen für uns speichert. Sie erspart uns das wiederholte Angeben in der Befehlszeile.

Fügen Sie in Ihrem Theme-Ordner die folgende Datei hinzu: .babelrc.

Öffnen Sie sie jetzt und fügen Sie Folgendes ein:

{
  "presets": ["env"],
  "plugins": [
    ["transform-react-jsx", {
      "pragma": "wp.element.createElement"
    }]
  ]
}

Update April 2019: Mit Babel 7 benötigen Sie wahrscheinlich "presets": ["@babel/preset-env"],

Also, wir haben dort zwei Dinge:

"presets": ["env"] ist im Grunde Magie. Es bestimmt automatisch, welche ES-Features verwendet werden, um Ihren ES5-Code zu generieren. Früher mussten wir verschiedene Presets für alle verschiedenen ES-Versionen hinzufügen (z. B. ES2015), aber das wurde vereinfacht.

In den Plugins werden Sie feststellen, dass ein React JSX Transformer vorhanden ist. Dieser kümmert sich um unser JSX und wandelt es in korrektes JavaScript um, aber wir sagen ihm, dass er WordPress-Elemente generieren soll, anstatt React-Elemente, mit denen JSX häufiger assoziiert wird.

Generieren von Stub-Dateien

Das Letzte, was wir tun werden, ist die Generierung einiger Stub-Dateien und das Testen, ob unsere webpack- und WordPress-Einrichtung in Ordnung ist.

Gehen Sie in Ihr Plugin-Verzeichnis und erstellen Sie einen Ordner namens blocks und darin zwei Ordner: einen namens src und einen namens dist.

Erstellen Sie im Ordner src die folgenden Dateien. Wir haben auch die Pfade hinzugefügt, damit Sie sie an der richtigen Stelle platzieren:

  • blocks.js
  • common.scss
  • block/block.js
  • block/editor.scss
  • block/style.scss

Nachdem Sie diese Dateien erstellt haben, öffnen Sie blocks.js und fügen Sie diese Einzeiler hinzu und speichern Sie:

import './block/block';

Okay, jetzt haben wir die minimale Menge an Dingen generiert. Lassen Sie uns webpack ausführen. Öffnen Sie Ihr Terminal und wechseln Sie in Ihr aktuelles Plugin-Verzeichnis – dann können wir Folgendes ausführen, was webpack starten wird:

npx webpack

Ziemlich geradlinig, oder? Wenn Sie in Ihren dist-Ordner schauen, sollten Sie einige kompilierte Goodies darin sehen!

Zusammenfassung

Viel Einrichtung wurde geleistet, aber alle unsere Enten sind in einer Reihe. Wir haben webpack, Babel und WordPress so eingerichtet, dass sie als Team zusammenarbeiten, um unseren benutzerdefinierten Gutenberg-Block (und zukünftige Blöcke) zu erstellen. Hoffentlich fühlen Sie sich jetzt mit webpack wohler und haben das Gefühl, dass Sie sich hineinstürzen und Anpassungen vornehmen können, die zu Ihren Projekten passen.


Artikelserie

  1. Reihen-Einführung
  2. Was ist Gutenberg eigentlich?
  3. Eine Einführung mit create-guten-block
  4. Moderne JavaScript-Syntax
  5. React 101
  6. Einrichten einer benutzerdefinierten webpack-Konfiguration (Dieser Beitrag)
  7. Ein benutzerdefinierter "Card"-Block