~/wordpress-plugins/gutenberg-block-entwickeln/

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: html oder text: Der Wert wird aus dem gespeicherten HTML gelesen, im Beispiel oben aus dem p-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/hooks erweitern 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 build ausgeführt und build/ aktuell
  • Blockname mit eigenem Namensraum, nie core/ oder fremde Präfixe
  • Texte mit __() übersetzbar, textdomain in der block.json gesetzt
  • Ausgaben in render.php escaped
  • Block in Editor und Frontend mit einem Standard-Theme getestet
  • node_modules nicht im ausgelieferten ZIP
faq

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.