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
- Reihen-Einführung
- Was ist Gutenberg eigentlich?
- Eine Einführung mit create-guten-block
- Moderne JavaScript-Syntax
- React 101
- Einrichten einer benutzerdefinierten webpack-Konfiguration (Dieser Beitrag)
- Ein benutzerdefinierter "Card"-Block
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.
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.
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:
contextist unsere Basis, von der aus Pfade aufgelöst werden. Wir haben__dirnameübergeben, was das aktuelle Arbeitsverzeichnis ist.devtoolist, wo wir definieren, welche Art von Sourcemap wir wollen oder nicht wollen. Wenn wir uns nicht imdebug-Modus befinden, übergeben wirnullmit einem ternären Operator.entryist, wo wir webpack sagen, dass es seine Pack-Reise beginnen soll. In unserem Fall ist dies der Pfad zu unsererblocks.js-Datei.outputist, 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
};
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.
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.jscommon.scssblock/block.jsblock/editor.scssblock/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
- Reihen-Einführung
- Was ist Gutenberg eigentlich?
- Eine Einführung mit create-guten-block
- Moderne JavaScript-Syntax
- React 101
- Einrichten einer benutzerdefinierten webpack-Konfiguration (Dieser Beitrag)
- Ein benutzerdefinierter "Card"-Block
Ich hatte einige Probleme, WebPack dazu zu bringen, die Dateien ordnungsgemäß im dist-Ordner zu generieren. Nach einiger Recherche scheint es, dass der Einstiegspunkt für die webpack-Konfigurationsdatei blocks/blocks.js ist, aber diese Datei ist leer. Ich habe
import './block/block.js';zu dieser Datei hinzugefügt, um den von Ihnen skizzierten Code zu importieren, und jetzt funktioniert es. Ich bin mir nicht sicher, ob ich etwas übersehen habe oder ob Tutorial 5 oder 6 erwähnen sollten, etwas in die Datei block/blocks.js einzufügen.Guter Fang, Justin. Danke.
Ich habe diese jetzt aktualisiert :)
Hallo Leute. Ich bin verwirrt... Siehe hier.
Ich bin wirklich verwirrt. Der Einstiegspunkt in webpack.config.js ist auf
/blocks/src/block.jsgesetzt, aber Ihr Tutorial hat angegeben, eine Datei im Ordner "src" namens "blocks.js" zu erstellen, nicht "block.js". Vielleicht folge ich einfach nicht richtig?Hallo Josiah, entschuldigen Sie das. Das ist mein Fehler. Ich habe mich mit dem obigen Kommentar verwirrt.
Es ist definitiv
blocks.js, weil diese Datei alle Blockdateien (falls erforderlich) importiert.Cool! Dann werde ich nicht verrückt, haha.