Gutenberg-Block entwickeln mit @wordpress/create-block
Mit einem Befehl zum lauffähigen Block: was create-block erzeugt, wie block.json, Edit- und Save-Funktion zusammenspielen und wann ein dynamischer Block besser ist.
Den schnellsten und offiziell empfohlenen Weg zu einem eigenen Gutenberg-Block bietet das Paket @wordpress/create-block. Ein Befehl erzeugt ein vollständiges Plugin mit Blockdefinition, Editor-Code, Styles und fertigem Build-Setup. Sie starten den Entwicklungsmodus, aktivieren das Plugin und finden Ihren Block sofort im Editor. Dieser Artikel zeigt den Ablauf und erklärt, was die erzeugten Dateien tun.
Voraussetzungen
- Node.js mit npm in einer aktuellen LTS-Version.
- Eine lokale WordPress-Installation, in deren Plugin-Ordner Sie arbeiten, oder
@wordpress/env, das eine Docker-Umgebung startet. - Grundkenntnisse in JavaScript und React. PHP brauchen Sie für statische Blöcke kaum, für dynamische Blöcke etwas.
Wie ein klassisches Plugin aufgebaut ist, also Header und Hauptdatei, zeigt der Artikel WordPress-Plugin erstellen.
Schritt 1: Gerüst erzeugen
Wechseln Sie in wp-content/plugins/ und führen Sie aus:
npx @wordpress/create-block@latest hinweis-block
Der Befehl legt einen Ordner hinweis-block an, installiert die Abhängigkeiten und erzeugt eine Plugin-Hauptdatei. Ohne weitere Optionen entsteht ein statischer Block. Nützliche Optionen sind:
| Option | Wirkung |
|---|---|
--variant=dynamic |
erzeugt einen dynamischen Block mit render.php |
--namespace=meinprefix |
legt den Namensraum im Blocknamen fest |
--no-plugin |
erzeugt nur den Block, etwa für ein bestehendes Plugin |
| ohne Namen | startet einen interaktiven Dialog mit Rückfragen |
Weitere Vorlagen, etwa für Blöcke mit der Interactivity API, lassen sich über die Option --template einbinden.
Schritt 2: Die erzeugte Struktur
hinweis-block/
├── hinweis-block.php Plugin-Hauptdatei, registriert den Block
├── package.json
├── src/
│ └── hinweis-block/
│ ├── block.json Blockdefinition
│ ├── index.js Registrierung im Editor
│ ├── edit.js Darstellung und Bedienung im Editor
│ ├── save.js gespeichertes HTML (nur statisch)
│ ├── style.scss Styles für Editor und Frontend
│ └── editor.scss Styles nur im Editor
└── build/ entsteht beim Build
Je nach Version des Pakets kann die Struktur leicht abweichen. In aktuellen Gerüsten liegt jeder Block in einem eigenen Unterordner von src/, und die PHP-Datei registriert alle Blöcke aus build/ gesammelt.
Schritt 3: Entwicklungsmodus starten
cd hinweis-block
npm start
npm start beobachtet die Dateien in src/ und baut bei jeder Änderung neu. Aktivieren Sie nun das Plugin im Adminbereich, öffnen Sie einen Beitrag und fügen Sie den Block über den Inserter ein. Für die Auslieferung erzeugt npm run build optimierte Dateien. Mit npm run plugin-zip packen Sie ein installierbares ZIP.
block.json: das Herzstück
Die block.json beschreibt den Block maschinenlesbar. WordPress liest sie sowohl in PHP als auch in JavaScript, lädt passende Dateien und kann den Block im Verzeichnis anzeigen.
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "meinprefix/hinweis-block",
"title": "Hinweis",
"category": "text",
"icon": "info",
"description": "Ein farbiger Hinweiskasten.",
"attributes": {
"text": { "type": "string", "source": "html", "selector": "p" }
},
"supports": { "html": false, "color": { "background": true } },
"textdomain": "hinweis-block",
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css"
}
Die wichtigsten Felder:
- name: eindeutige Kennung aus Namensraum und Blockname. Sie wird im Beitragsinhalt gespeichert und sollte sich nie ändern.
- attributes: die Daten des Blocks. Hier wird der Text aus dem
p-Element des gespeicherten HTML gelesen. - supports: schaltet eingebaute Funktionen frei, etwa Farb-, Abstands- oder Typografie-Einstellungen, ohne dass Sie eigenen Code schreiben.
- editorScript, style, render: verweisen mit
file:auf die Dateien im Build-Ordner.
Schritt 4: Edit und Save
Die Edit-Funktion bestimmt, wie der Block im Editor aussieht und bedient wird:
import { useBlockProps, RichText } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
export default function Edit( { attributes, setAttributes } ) {
return (
<div { ...useBlockProps( { className: 'hinweis' } ) }>
<RichText
tagName="p"
value={ attributes.text }
onChange={ ( text ) => setAttributes( { text } ) }
placeholder={ __( 'Hinweis eingeben …', 'hinweis-block' ) }
/>
</div>
);
}
Die Save-Funktion legt fest, welches HTML im Beitrag gespeichert wird:
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function save( { attributes } ) {
return (
<div { ...useBlockProps.save( { className: 'hinweis' } ) }>
<RichText.Content tagName="p" value={ attributes.text } />
</div>
);
}
useBlockProps() fügt Klassen und Attribute hinzu, die WordPress für Auswahl, Ausrichtung und die per supports aktivierten Einstellungen braucht. Lassen Sie es nie weg.
Zusätzliche Einstellungen für die Seitenleiste setzen Sie mit InspectorControls und Komponenten aus @wordpress/components um, etwa einem Umschalter oder einer Auswahlliste.
Wo Attribute gespeichert werden
Blöcke landen als HTML mit speziellen Kommentaren im Beitragsinhalt, etwa <!-- wp:meinprefix/hinweis-block {"typ":"warnung"} -->. Wie ein Attribut gespeichert wird, legt source in der block.json fest:
- ohne
source: Der Wert steht als JSON im Blockkommentar. Das ist robust und passt für Einstellungen wie Farben, Schalter oder IDs. source: htmlodertext: Der Wert wird aus dem gespeicherten HTML gelesen, im Beispiel oben aus demp-Element. So steht kein Text doppelt im Inhalt.source: attribute: Der Wert stammt aus einem HTML-Attribut, etwa der Adresse eines Links oder Bildes.
Für dynamische Blöcke speichern Sie Attribute grundsätzlich im Kommentar, da es kein gespeichertes HTML gibt, aus dem sie gelesen werden könnten.
Statisch oder dynamisch?
| Statischer Block | Dynamischer Block | |
|---|---|---|
| Ausgabe | HTML wird beim Speichern im Beitrag abgelegt | HTML entsteht bei jedem Aufruf per PHP |
| Datei | save.js |
render.php |
| Geeignet für | Texte, Layouts, feste Inhalte | aktuelle Daten, etwa neueste Beiträge oder Werte aus Einstellungen |
| Markup ändern | alte Inhalte brauchen Deprecations | wirkt sofort auf alle Vorkommen |
| Ohne Plugin | HTML bleibt sichtbar | Block gibt nichts mehr aus |
Bei einem dynamischen Block gibt save null zurück, und die block.json verweist mit "render": "file:./render.php" auf eine PHP-Datei. Darin stehen $attributes, $content und $block zur Verfügung:
<?php
$text = $attributes['text'] ?? '';
?>
<div <?php echo get_block_wrapper_attributes( array( 'class' => 'hinweis' ) ); ?>>
<p><?php echo esc_html( $text ); ?></p>
</div>
Escaping gilt hier genauso wie in jedem anderen PHP-Code. Mehr dazu im Artikel WordPress-Plugin absichern.
Block-Validierung und Deprecations
Ändern Sie bei einem statischen Block die Save-Funktion, erzeugt sie für bestehende Inhalte anderes HTML als gespeichert. Der Editor meldet dann ungültige Inhalte und bietet eine Reparatur an. Damit Nutzer das nie sehen, beschreiben Sie alte Varianten in einem deprecated-Array: Jede Variante enthält die alten Attribute und die alte Save-Funktion, optional eine Migration. Für Blöcke, deren Markup sich häufig ändert, ist ein dynamischer Block oft die einfachere Wahl.
Build-Werkzeug: @wordpress/scripts
Das Gerüst nutzt @wordpress/scripts, eine vorkonfigurierte Sammlung aus Bundler, Babel, Linting und Testwerkzeugen. Abhängigkeiten zu WordPress-Paketen wie @wordpress/block-editor werden dabei nicht in Ihr Bundle gepackt, sondern als vorhandene Skripte von WordPress geladen. Die automatisch erzeugte Datei index.asset.php listet diese Abhängigkeiten samt Versionshash.
Wer andere Build-Werkzeuge gewohnt ist, sollte im Block-Umfeld trotzdem bei @wordpress/scripts bleiben, weil diese Abhängigkeitsauflösung sonst von Hand nachgebaut werden muss. Allgemeine Hinweise zu Build-Setups mit TypeScript und Vite für andere Plattformen finden Sie im Artikel TypeScript und Vite für Erweiterungen einrichten.
Bestehende Blöcke erweitern statt neu bauen
Nicht jede Idee braucht einen eigenen Block. Oft reicht es, vorhandene Blöcke anzupassen:
- Block-Stile fügen einem Kernblock eine alternative Darstellung hinzu, etwa einen Rahmen für Bilder.
- Block-Varianten sind vorkonfigurierte Versionen eines Blocks mit eigenem Namen im Inserter.
- Block-Vorlagen (Patterns) kombinieren mehrere Blöcke zu einem wiederverwendbaren Abschnitt, ganz ohne JavaScript.
- JavaScript-Filter aus
@wordpress/hookserweitern bestehende Blöcke um eigene Einstellungen. Das Prinzip entspricht den PHP-Hooks, die der Artikel WordPress-Hooks erklärt beschreibt.
Checkliste vor der Auslieferung
npm run buildausgeführt undbuild/aktuell- Blockname mit eigenem Namensraum, nie
core/oder fremde Präfixe - Texte mit
__()übersetzbar,textdomainin derblock.jsongesetzt - Ausgaben in
render.phpescaped - Block in Editor und Frontend mit einem Standard-Theme getestet
node_modulesnicht im ausgelieferten ZIP
Fragen und Antworten
- Brauche ich React-Kenntnisse für einen Gutenberg-Block?
- Grundkenntnisse helfen sehr. Die Editor-Seite eines Blocks ist eine React-Komponente, allerdings nutzen Sie die WordPress-Pakete wie @wordpress/block-editor und @wordpress/components, die viel abnehmen. Für einfache Blöcke reichen JSX, Props und das Prinzip von Zustand und Rendern.
- Was bedeutet die Meldung, der Block enthalte unerwartete oder ungültige Inhalte?
- Bei statischen Blöcken vergleicht der Editor das gespeicherte HTML mit dem, was die aktuelle Save-Funktion erzeugen würde. Haben Sie die Save-Funktion geändert, passt alter Inhalt nicht mehr. Abhilfe schaffen Deprecations in der Blockdefinition, die alte Varianten beschreiben, oder ein dynamischer Block, der gar kein HTML speichert.
- Kann ich mehrere Blöcke in einem Plugin bündeln?
- Ja. Jeder Block bekommt einen eigenen Ordner mit block.json im src-Verzeichnis, der Build erzeugt daraus passende Ordner unter build. Das Plugin registriert dann alle Blöcke, aktuelle Gerüste tun das gesammelt über eine Manifest-Datei.
- Muss ich den build-Ordner ausliefern?
- Ja. WordPress lädt im Betrieb nur die gebauten Dateien. Der Ordner node_modules und in der Regel auch src gehören nicht in das ausgelieferte Plugin. Im offiziellen Verzeichnis ist es aber gern gesehen, den Quellcode öffentlich zugänglich zu machen, etwa über ein Repository.
Weiterlesen
- Plugin erstellen
Vom leeren Ordner zum funktionierenden Plugin: Header, Ordnerstruktur, Aktivierungs-Hook, ein Shortcode mit Einstellung und eine saubere uninstall.php.
- TypeScript und Vite einrichten
Ein Build-Setup für Erweiterungen: TypeScript-Konfiguration, Typen für die Browser-APIs, mehrere Einstiegspunkte mit Vite, die Sonderrolle der Content Scripts und Alternativen wie WXT.
- Actions und Filter
Actions führen Code aus, Filter verändern Werte: wie add_action und add_filter funktionieren, was Priorität und Argumentzahl bewirken und wie Sie eigene Hooks anbieten.