Ha valaha is láttál már „A blokk üresen renderelt” hibát a szerkesztőben, vagy egy olyan blokkot, ami lokálisan működik, de éles környezetben eltűnik, a probléma szinte mindig ugyanonnan ered: egy rosszul csatlakoztatott build, rosszul mentett eszközök vagy egy hiányzó szerver render, amitől a blokkod függ.

A probléma / A szükséglet

Akarsz teremt egy tiszta, karbantartható és kompatibilis, egyedi Gutenberg blokk WordPress 6.9.4 (2026. április), anélkül, hogy minden iterációhoz manuálisan szkriptlekérdezést kellene létrehozni. A tipikus követelmény: egy „Figyelmeztető doboz” blokk (vagy „CTA”, „GYIK”, „Termék” stb.) a következőkkel:

  • un React szerkesztő (Inspector vezérlők, színek, opciók)
  • un megbízhatóvá tett elülső rész (anélkül, hogy látogatóoldali JS futási környezetre támaszkodnánk),
  • egyesít modern építési lánc keresztül @wordpress/scripts (Webpack/Babel használatra kész),
  • egyesít vagyonnyilvántartás robusztus keresztül block.json és a metaadatok.

Végül tudni fogja, hogyan kell egy komplett blokkot a következő formában szállítani: csatlakoztata builddel, verziókezeléssel, internacionalizálással és szerveroldali rendereléssel (dinamikus blokk), ahol releváns. A dinamikus blokkokat azért hangsúlyozom, mert gyakran láttam, hogy a "statikus" blokkok kezelhetetlenné válnak, amint a tartalomnak globális beállításoktól, egy CPT-től vagy egy kontextustól kell függenie.

Gyors összefoglaló

  • Létrehozunk egy bővítményt, amely elment egy blokkot a következőn keresztül: block.json et register_block_type().
  • Használjuk @wordpress/scripts épülethez src/index.js hogy build/index.js + fájl .asset.php.
  • Egy blokkot írunk a következővel: szerkesztőoldali felhasználói felület (JS) és szerveroldali renderelés (PHP), hogy elkerüljük a front-end/szerkesztői eltéréseket.
  • A CSS/JS-t a mezőkön keresztül töltjük be. editorScript, style, editorStyle du block.json.
  • Az éles környezetben felmerülő problémákat tárgyaljuk: elérési utak, gyorsítótár, függőségek, PHP verzió és regisztrációs hookok.

Mikor kell használni ezt a megoldást

  • Egy blokkot akarsz réutilisable sur számos webhelyek, bővítményként elérhetők.
  • Kell egy stabillá tették A felhasználói felületen (SEO, teljesítmény, gyorsítótár-kompatibilitás): a dinamikus blokk használata ajánlott.
  • El szeretné kerülni a lekérdezéskódrészlet másolását és beillesztését, és a szokásos folyamatot szeretné alkalmazni. WordPress : block.json + épít.
  • A blokkodnak fejlődnie kell (új lehetőségek, variációk, stílusok) a meglévő tartalom sértése nélkül.
  • Csapatként dolgoztok: az építkezésen keresztül @wordpress/scripts szabványosítja a környezetet.

Mikor NEM szabad ezt a megoldást használni

  • Csak egyszerű tartalomra van szükséged: a blokkminta (blokkminta) gyakran elegendő, JS nélkül. Lásd Blokk minták.
  • Egy bonyolult, de logikátlan elrendezést keresel: a csoportblokk + globális stílusok + a variációk helyettesíthetik az egyéni blokkot.
  • Nem kezelhetsz építési lépést (CI/CD, Node): ebben az esetben használj egy építő bővítményt (scaffold), majd véglegesítse a build mappát és kerüld a Node futtatását éles környezetben.
  • Egy zárolt környezetben vagy, ahol a Node használata tiltott: csak a létrehozott fájlokat küldheted el, de elveszíted a fejlesztői ciklust.

Előfeltételek / kezdés előtt

Feltételezem, hogy WordPress 6.9.4-re és PHP 8.1+-ra fejlesztesz. Sok régebbi oktatóanyag manapság azért nem működik, mert nem használják... block.json helyesen, vagy felejtsd el .asset.php.

  • WordPress : 6.9.4 (vagy újabb).
  • PHP 8.1+ (ajánlott). Referencia: PHP támogatott verziók.
  • node.js : egy újabb LTS (18/20/22 a stackedtől függően). Kerüld az EOL verziókat.
  • Hozzáférés : egy átmeneti/helyi környezet. Ne teszteljen blokk-buildet közvetlenül éles környezetben biztonsági mentés nélkül.
  • Tools :
    • WP-CLI (opcionális, de hasznos).
    • Egy naplóbővítmény (vagy hozzáférési debug.log).

Óvintézkedések:

  • engedélyezése WP_DEBUG et WP_DEBUG_LOG a tesztkörnyezetedben.
  • Ha gyorsítótárat használsz (plugin, Varnish, Cloudflare), tervezd meg a kiürítést: Gyakran láttam, hogy a blokk CSS „nem töltődik be”, amikor az csak egy agresszív gyorsítótár volt.

Hasznos hivatalos dokumentumok:

A naiv megközelítés (és miért kerülendő)

A klasszikus, amit még 2026-ban is látok: egy "kézzel készített" blokk nagy wp_enqueue_script -ban wp_enqueue_scripts, nélkül .asset.php, deklarált függőségek nélkül, sőt néha anélkül is block.json"Nekem" működik, aztán egy WordPress/Gutenberg frissítés után elromlik.

Egy naiv példa (nem ismételhető)

<?php
// Mauvaise pratique : charge partout, pas seulement dans l'éditeur, dépendances non gérées.
add_action( 'wp_enqueue_scripts', function () {
	wp_enqueue_script(
		'mon-bloc',
		plugins_url( 'build/index.js', __FILE__ ),
		array( 'wp-blocks', 'wp-element', 'wp-editor' ), // Souvent faux/incomplet.
		'1.0.0',
		true
	);
} );

Miért jelent ez problémát:

  • Teljesítmény : a blokk JS-e a teljes front-endre vonatkozik, még akkor is, ha nem használunk blokkot.
  • Függőségek A manuálisan összeállított lista mindig hibásnak bizonyul. A WordPress generál egy .asset.php pontosan ezért.
  • Karbantartás : a metaadatok használata helyett megkettőzöd az eszközregisztrációs logikát.
  • Konfliktusok kockázata globális azonosító, ütközések és rossz kontextusban betöltött szkriptek.

A helyes megközelítés – lépésről lépésre bemutató

Cél: egy bővítmény bpca-riasztásblokk amely hozzáad egy „Figyelmeztető doboz” blokkot a következővel:

  • cím + tartalom,
  • egy szint (info/siker/figyelem/hiba),
  • „ikon” opció (igen/nem),
  • PHP-ben (dinamikus blokk) történő front-end renderelés a konzisztencia biztosítása és a jövőbeli fejlesztések lehetővé tétele érdekében.

1. lépés – A bővítmény struktúrájának létrehozása

Dans wp-content/plugins/ :

mkdir -p bpca-alert-block/src bpca-alert-block/build bpca-alert-block/assets

Hozd létre a fő fájlt:

<?php
/**
 * Plugin Name: BPCA Alert Block
 * Description: Bloc Gutenberg "Encart Alerte" (dynamic block) avec build via @wordpress/scripts.
 * Version: 1.0.0
 * Requires at least: 6.9
 * Requires PHP: 8.1
 * Author: BPCA
 * License: GPL-2.0-or-later
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

define( 'BPCA_ALERT_BLOCK_FILE', __FILE__ );
define( 'BPCA_ALERT_BLOCK_DIR', __DIR__ );

require_once BPCA_ALERT_BLOCK_DIR . '/includes/class-bpca-alert-block.php';

add_action( 'init', array( 'BPCA\AlertBlock\Plugin', 'init' ) );

teremt includes/class-bpca-alert-block.php :

<?php
namespace BPCAAlertBlock;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

final class Plugin {

	public static function init(): void {
		// Enregistre le bloc via block.json + render_callback.
		add_action( 'init', array( __CLASS__, 'register_block' ) );
	}

	public static function register_block(): void {
		$block_json = BPCA_ALERT_BLOCK_DIR . '/block.json';

		// register_block_type() sait lire block.json et enregistrer les assets déclarés.
		register_block_type(
			$block_json,
			array(
				'render_callback' => array( __CLASS__, 'render' ),
			)
		);
	}

	/**
	 * Rendu serveur (dynamic block).
	 *
	 * @param array  $attributes Attributs du bloc.
	 * @param string $content    Contenu interne (InnerBlocks), non utilisé ici.
	 * @return string HTML rendu.
	 */
	public static function render( array $attributes, string $content ): string {
		$level   = isset( $attributes['level'] ) ? sanitize_key( $attributes['level'] ) : 'info';
		$title   = isset( $attributes['title'] ) ? sanitize_text_field( $attributes['title'] ) : '';
		$message = isset( $attributes['message'] ) ? wp_kses_post( $attributes['message'] ) : '';
		$icon    = ! empty( $attributes['showIcon'] );

		$allowed_levels = array( 'info', 'success', 'warning', 'error' );
		if ( ! in_array( $level, $allowed_levels, true ) ) {
			$level = 'info';
		}

		$classes = array(
			'bpca-alert',
			'bpca-alert--' . $level,
		);

		$icon_html = '';
		if ( $icon ) {
			// Icônes simples en SVG inline (pas de dépendance externe).
			$icon_html = '<span class="bpca-alert__icon" aria-hidden="true">' . self::get_icon_svg( $level ) . '</span>';
		}

		$title_html = '';
		if ( $title !== '' ) {
			$title_html = '<div class="bpca-alert__title">' . esc_html( $title ) . '</div>';
		}

		// Note : $message est déjà filtré via wp_kses_post() mais on l'échappe en contexte HTML.
		$message_html = '';
		if ( $message !== '' ) {
			$message_html = '<div class="bpca-alert__message">' . $message . '</div>';
		}

		$html  = '<div class="' . esc_attr( implode( ' ', $classes ) ) . '" role="note">';
		$html .= $icon_html;
		$html .= '<div class="bpca-alert__body">' . $title_html . $message_html . '</div>';
		$html .= '</div>';

		return $html;
	}

	private static function get_icon_svg( string $level ): string {
		// SVG minimalistes. Vous pouvez les remplacer par vos propres assets.
		switch ( $level ) {
			case 'success':
				return '<svg viewBox="0 0 24 24" width="20" height="20" focusable="false"><path d="M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z"></path></svg>';
			case 'warning':
				return '<svg viewBox="0 0 24 24" width="20" height="20" focusable="false"><path d="M1 21h22L12 2 1 21zm12-3h-2v2h2v-2zm0-8h-2v6h2V10z"></path></svg>';
			case 'error':
				return '<svg viewBox="0 0 24 24" width="20" height="20" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"></path></svg>';
			case 'info':
			default:
				return '<svg viewBox="0 0 24 24" width="20" height="20" focusable="false"><path d="M11 17h2v-6h-2v6zm0-8h2V7h-2v2zm1-7C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2z"></path></svg>';
		}
	}
}

2. lépés – block.json hozzáadása (metaadatok + eszközök)

teremt block.json a bővítmény gyökerében:

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "bpca/alert",
	"title": "Encart Alerte (BPCA)",
	"category": "widgets",
	"icon": "warning",
	"description": "Affiche un encart d'alerte avec niveau et option d'icône.",
	"textdomain": "bpca-alert-block",
	"attributes": {
		"level": { "type": "string", "default": "info" },
		"title": { "type": "string", "default": "" },
		"message": { "type": "string", "default": "" },
		"showIcon": { "type": "boolean", "default": true }
	},
	"supports": {
		"anchor": true,
		"html": false
	},
	"editorScript": "file:./build/index.js",
	"style": "file:./build/style-index.css",
	"editorStyle": "file:./build/index.css"
}

Gyakorlati megjegyzések:

  • apiVersion: 3 a modern blokkok jelenlegi alapja.
  • területén file: elindítja az eszközök automatikus mentését a verziókkal együtt a .asset.php generált.
  • supports.html: false megakadályozza a felhasználót a „HTML-ben szerkesztésben” és a struktúra megszakításában.

3. lépés – Telepítse a @wordpress/scripts fájlt, és konfigurálja a package.json fájlt

A bővítmény mappájában:

npm init -y
npm install --save-dev @wordpress/scripts

Cserélje package.json (vagy adaptáld):

{
	"name": "bpca-alert-block",
	"version": "1.0.0",
	"private": true,
	"scripts": {
		"start": "wp-scripts start",
		"build": "wp-scripts build",
		"lint:js": "wp-scripts lint-js",
		"format": "wp-scripts format"
	},
	"devDependencies": {
		"@wordpress/scripts": "^30.0.0"
	}
}

Referencia: @wordpress/scripts.

4. lépés — Írd meg a blokk (szerkesztő) kódját az src/ könyvtárban

teremt src/index.js :

import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import {
	InspectorControls,
	useBlockProps,
	RichText,
} from '@wordpress/block-editor';
import {
	PanelBody,
	SelectControl,
	ToggleControl,
	TextControl,
} from '@wordpress/components';

import './editor.css';
import './style.css';

registerBlockType( 'bpca/alert', {
	edit: ( { attributes, setAttributes } ) => {
		const { level, title, message, showIcon } = attributes;

		const blockProps = useBlockProps( {
			className: `bpca-alert bpca-alert--${ level }`,
		} );

		return (
			<>
				<InspectorControls>
					<PanelBody title={ __( 'Réglages', 'bpca-alert-block' ) }>
						<SelectControl
							label={ __( 'Niveau', 'bpca-alert-block' ) }
							value={ level }
							options={ [
								{ label: __( 'Info', 'bpca-alert-block' ), value: 'info' },
								{ label: __( 'Succès', 'bpca-alert-block' ), value: 'success' },
								{ label: __( 'Attention', 'bpca-alert-block' ), value: 'warning' },
								{ label: __( 'Erreur', 'bpca-alert-block' ), value: 'error' },
							] }
							onChange={ ( next ) => setAttributes( { level: next } ) }
						/>

						<ToggleControl
							label={ __( 'Afficher une icône', 'bpca-alert-block' ) }
							checked={ !! showIcon }
							onChange={ ( next ) => setAttributes( { showIcon: !! next } ) }
						/>

						<TextControl
							label={ __( 'Titre (optionnel)', 'bpca-alert-block' ) }
							value={ title }
							onChange={ ( next ) => setAttributes( { title: next } ) }
						/>
					</PanelBody>
				</InspectorControls>

				<div { ...blockProps }>
					{ showIcon && (
						<span className="bpca-alert__icon" aria-hidden="true">
							<span className="bpca-alert__icon-placeholder">!</span>
						</span>
					) }

					<div className="bpca-alert__body">
						{ title ? (
							<div className="bpca-alert__title">{ title }</div>
						) : null }

						<RichText
							tagName="div"
							className="bpca-alert__message"
							value={ message }
							allowedFormats={ [ 'core/bold', 'core/italic', 'core/link' ] }
							placeholder={ __( 'Votre message…', 'bpca-alert-block' ) }
							onChange={ ( next ) => setAttributes( { message: next } ) }
						/>
					</div>
				</div>
			</>
		);
	},

	// Dynamic block : save() doit retourner null.
	save: () => null,
} );

Két CSS fájl:

/* src/style.css - CSS front + éditeur (partagé) */
.bpca-alert{
	display:flex;
	gap:12px;
	padding:14px 16px;
	border-radius:10px;
	border:1px solid transparent;
	align-items:flex-start;
}
.bpca-alert__icon svg{ display:block; fill: currentColor; }
.bpca-alert__title{ font-weight: 650; margin-bottom: 6px; }
.bpca-alert__message a{ text-decoration: underline; }

.bpca-alert--info{ background:#eef6ff; border-color:#cfe6ff; color:#0b3d91; }
.bpca-alert--success{ background:#eafff1; border-color:#c9f2d7; color:#0b5d2a; }
.bpca-alert--warning{ background:#fff7e6; border-color:#ffe3a3; color:#7a4a00; }
.bpca-alert--error{ background:#ffecec; border-color:#ffc2c2; color:#7a0000; }
/* src/editor.css - uniquement éditeur */
.wp-block-bpca-alert .bpca-alert__icon-placeholder{
	display:inline-flex;
	width:20px;
	height:20px;
	border-radius:4px;
	align-items:center;
	justify-content:center;
	background: rgba(0,0,0,.08);
	font-weight: 700;
}

5. lépés – Építő

Dob:

npm run build

A következőket kell beszereznie:

  • build/index.js
  • build/index.asset.php (kritikai)
  • build/index.css
  • build/style-index.css

6. lépés – Aktiválja a bővítményt és tesztelje azt

  • Aktiváld a bővítményt az admin felületen.
  • A blokkszerkesztőben keresse meg az „Alert Box (BPCA)” kifejezést.
  • Add hozzá, változtasd meg a szintet, teszteld ikonnal/ikon nélkül, publikáld.

Teljes kód

A következő egy működő másolás-beillesztés (teljes bővítmény). Figyeljük meg, hogy a build (build/) nem szerepel itt: futtatnia kell npm run build a fájlok létrehozásához.

1) bpca-alert-block.php

<?php
/**
 * Plugin Name: BPCA Alert Block
 * Description: Bloc Gutenberg "Encart Alerte" (dynamic block) avec build via @wordpress/scripts.
 * Version: 1.0.0
 * Requires at least: 6.9
 * Requires PHP: 8.1
 * Author: BPCA
 * License: GPL-2.0-or-later
 * Text Domain: bpca-alert-block
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

define( 'BPCA_ALERT_BLOCK_FILE', __FILE__ );
define( 'BPCA_ALERT_BLOCK_DIR', __DIR__ );

require_once BPCA_ALERT_BLOCK_DIR . '/includes/class-bpca-alert-block.php';

add_action( 'init', array( 'BPCA\AlertBlock\Plugin', 'init' ) );

2) tartalmazza a/class-bpca-alert-block.php fájlt

<?php
namespace BPCAAlertBlock;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

final class Plugin {

	public static function init(): void {
		add_action( 'init', array( __CLASS__, 'register_block' ) );
	}

	public static function register_block(): void {
		register_block_type(
			BPCA_ALERT_BLOCK_DIR . '/block.json',
			array(
				'render_callback' => array( __CLASS__, 'render' ),
			)
		);
	}

	public static function render( array $attributes, string $content ): string {
		$level   = isset( $attributes['level'] ) ? sanitize_key( $attributes['level'] ) : 'info';
		$title   = isset( $attributes['title'] ) ? sanitize_text_field( $attributes['title'] ) : '';
		$message = isset( $attributes['message'] ) ? wp_kses_post( $attributes['message'] ) : '';
		$icon    = ! empty( $attributes['showIcon'] );

		$allowed_levels = array( 'info', 'success', 'warning', 'error' );
		if ( ! in_array( $level, $allowed_levels, true ) ) {
			$level = 'info';
		}

		$classes = array( 'bpca-alert', 'bpca-alert--' . $level );

		$icon_html = '';
		if ( $icon ) {
			$icon_html = '<span class="bpca-alert__icon" aria-hidden="true">' . self::get_icon_svg( $level ) . '</span>';
		}

		$title_html = $title !== '' ? '<div class="bpca-alert__title">' . esc_html( $title ) . '</div>' : '';
		$message_html = $message !== '' ? '<div class="bpca-alert__message">' . $message . '</div>' : '';

		return '<div class="' . esc_attr( implode( ' ', $classes ) ) . '" role="note">'
			. $icon_html
			. '<div class="bpca-alert__body">' . $title_html . $message_html . '</div>'
			. '</div>';
	}

	private static function get_icon_svg( string $level ): string {
		switch ( $level ) {
			case 'success':
				return '<svg viewBox="0 0 24 24" width="20" height="20" focusable="false"><path d="M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z"></path></svg>';
			case 'warning':
				return '<svg viewBox="0 0 24 24" width="20" height="20" focusable="false"><path d="M1 21h22L12 2 1 21zm12-3h-2v2h2v-2zm0-8h-2v6h2V10z"></path></svg>';
			case 'error':
				return '<svg viewBox="0 0 24 24" width="20" height="20" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"></path></svg>';
			case 'info':
			default:
				return '<svg viewBox="0 0 24 24" width="20" height="20" focusable="false"><path d="M11 17h2v-6h-2v6zm0-8h2V7h-2v2zm1-7C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2z"></path></svg>';
		}
	}
}

3) blokk.json

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "bpca/alert",
	"title": "Encart Alerte (BPCA)",
	"category": "widgets",
	"icon": "warning",
	"description": "Affiche un encart d'alerte avec niveau et option d'icône.",
	"textdomain": "bpca-alert-block",
	"attributes": {
		"level": { "type": "string", "default": "info" },
		"title": { "type": "string", "default": "" },
		"message": { "type": "string", "default": "" },
		"showIcon": { "type": "boolean", "default": true }
	},
	"supports": {
		"anchor": true,
		"html": false
	},
	"editorScript": "file:./build/index.js",
	"style": "file:./build/style-index.css",
	"editorStyle": "file:./build/index.css"
}

4) src/index.js + src/style.css + src/editor.css

Menj vissza, és nézd át a lépésenkénti útmutatóban található fájlokat.

Kód magyarázata

Miért egyszerűsíti le igazán az életet a block.json?

block.json vált a központi ponttá. A WordPress beolvassa a metaadatokat, menti a blokkot, és tudja, hogyan töltse be az elemeket a megfelelő helyre (szerkesztő vs. front-end). Amikor ezt használod "file:./build/index.js"A WordPress a fájlra támaszkodik build/index.asset.php a build által generálva a következőhöz:

  • kijelentem a pontos függőségek (például: wp-element, wp-i18n, wp-block-editor),
  • kijelentem a változat (hash) a gyorsítótár-feltöréshez.

Hivatalos hivatkozás: Metaadatok blokkolása.

Miért kerüli el a valódi hibákat egy dinamikus blokk (mentés: null)?

Statikus blokk esetén fenn kell tartani két látványterv :

  • a JSX renderelés edit(),
  • szerializált HTML save().

A gyakorlatban, amint hozzáadsz egy opciót, elfelejted frissíteni. save()és végül "régi formátumú" tartalommal találod magad az adatbázisban. Dinamikus blokkarchitektúrával a kezelőfelület PHP-t használ, tehát:

  • A HTML-t tartalom migrálása nélkül is fejlesztheted.
  • Központosítod a kipufogó- és szennyvízkezelő rendszereket,
  • Jobban kezeled a kontextusokat (többnyelvű webhely, globális beállítások, A/B tesztelés stb.).

A hátránya: a renderelés a szervertől függ, ezért szigorúnak kell lenni a teljesítmény és a gyorsítótárazás tekintetében (erre még visszatérünk).

Horgok és időzítés

Elmentjük a blokkot initEz a várható időzítés: a blokktípusokat elég korán, de a mag betöltése után kell regisztrálni. Referencia: regiszter_blokk_típusa().

Fertőtlenítés és menekülés

  • sanitize_key() mert level (érték „slug”).
  • sanitize_text_field() mert title.
  • wp_kses_post() mert message mivel a HTML egy részhalmaza (linkek, hangsúly) megengedett. Dokumentum: wp_kses_post().
  • esc_attr() a CSS osztályról, esc_html() a címen.

Ennél a blokktípusnál a fő kockázat a HTML-befecskendezés, ha megbízunk az attribútumokban. Még ha a szerkesztő „admin”, sem szeretnénk állandó XSS sebezhetőséget, ha egy alacsonyabb szintű felhasználó publikálhat.

Változatok és használati esetek

1. lehetőség – Statikus blokk (ha ragaszkodsz a szerializált HTML-hez)

Eset: Azt szeretné, hogy a tartalom 100%-ban hordozható legyen a bővítménytől való függés nélkül (pl. egy másik webhelyre exportálás bővítmény nélkül). Megvalósíthatja save() és távolítsa el render_callback.

Mit teszek ebben az esetben: Minimális HTML-t használok. save() És korlátozom a lehetőségeket. Különben a vártnál hamarabb kell foglalkoznod a blokk verziók migrációjával.

2. lehetőség – Blokkstílusok (stílusvariációk) hozzáadása a felhasználói felület bonyolítása nélkül

Stílusokat deklarálhatsz JS-en keresztül (registerBlockStyle) vagy ezen keresztül block.json a stratégiádtól függően. Haladó bloggerek számára gyakran egyszerűbb, ha a felhasználó választhat a „Vázlat” és a „Kitöltött” között anélkül, hogy váltókapcsolót adnának hozzá az Inspectorban.

Dokumentum: Blokkstílusok.

3. változat – Globális beállítástól függő megjelenítés (Beállítások API)

Példa: egyszer konfigurálni szeretné a „Márkaszínek” opciót. render()Keress ki egy opciót, és állítsd be az osztályokat vagy az inline stílust (az egyszerűség kedvéért). Figyelem: ha blokkonként kezded el generálni az inline CSS-t, drasztikusan megnövelheted a HTML méretét a hosszú oldalakon.

Divi 5 / Elementor / Avada kompatibilitás

Lényeges pont: A Divi 5, az Elementor és az Avada együtt tud működni a blokkszerkesztővel, de a tartalom a saját szerkesztőikkel generálható. A Gutenberg blokkod továbbra is használható marad.

  • a natív blokkszerkesztőben,
  • a „Gutenberg”/„Blokkszerkesztő” területeken, amelyeket ezek a témák/bővítmények tesznek elérhetővé,
  • néha dedikált modulokban (a készítőtől függően).

Divi 5

A Divi 5 jobban tud együttműködni a blokkokkal, de továbbra is problémákat tapasztaltam a Divi globális CSS-ével a blokkstílusok (sormagasság, dobozméret) felülbírálásakor. A blokkod robusztus, ha:

  • az osztályok elé helyezzük (bpca-alert),
  • Kerüld a túlságosan általános szelektorokat.

Ha "Divi modulként" szeretnéd integrálni, akkor megadhatsz egy rövid kódot (tartalékkódot), amely ugyanazt a renderelési függvényt használja újra, de nem duplikálja a logikát. Tarts meg egyetlen igazságforrást (PHP).

Elementor

Az Elementor lehetővé teszi rövidkódok beszúrását, és a konfigurációtól függően blokkokat is beszúrhat WordPress widgeteken keresztül. Haladó használathoz:

  • javasoljon egy rövidkódot [bpca_alert] amely ugyanazt a renderelési módszert igényli,
  • vagy tegyen elérhetővé egy dedikált Elementor widgetet (a karbantartás hosszabb időt vesz igénybe).

A rövidkódot könnyűsúlyú átjáróként ajánlom, ha a közönséged vegyes.

Avada (fúziós építő)

Az Avada történelmileg sok globális CSS-sel rendelkezett. Különösen a következő teszteket érdemes megvizsgálni:

  • az alapértelmezett margók div,
  • linkstílusok,
  • az örökölt színek.

Ütközés esetén adjon hozzá egy pontosabb CSS réteget src/style.css (anélkül, hogy beleesnénk a háborúba !important).

Telepítés utáni ellenőrzések

  • kiadó A blokk megjelenik, és a vezérlők helyesen módosítják az előnézetet.
  • Front A HTML renderelés tartalmaz bpca-alert et bpca-alert--{level}.
  • Eszközök :
    • a szerkesztőben: build/index.js + build/index.css töltött,
    • az előlapon: build/style-index.css csak akkor töltődik be, ha a blokk jelen van.
  • Gyorsítótár Utána npm run build, gyorsítótár-ürítő bővítmény/CDN + böngésző kemény frissítése.
  • Naplók : nincs „nem sikerült betölteni az erőforrást” hiba a blokk CSS/JS-ében.

Gyors diagnosztikai táblázat

tünet Valószínű ok igazolás Megoldás
A blokk nem jelenik meg a betétlapon. Bővítmény inaktív vagy PHP hiba betöltéskor Admin > Bővítmények, + debug.log Javítsa ki a hibát, ellenőrizze a névteret/belefoglalt fájlt
Látható, de „üres” blokk elöl Dinamikus blokk nélkül render_callback hatékony, vagy hiba a render() függvényben HTML forrás + PHP naplók megtekintése ellenőrzés register_block_type(... render_callback ...) és higiénia
Hiányzik a CSS a kezelőfelületről style helytelenül deklarálva block.json vagy hiányzó build Hálózat fül, fájl style-index.css Újraindítás npm run build, ellenőrizze az útvonalakat file:
JavaScript hiba a szerkesztőben Megoldatlan függőségek / hibás build Böngésző konzol a szerkesztőben Távolítsuk build/újraindítjuk az építést, ellenőrizzük index.asset.php
A változások nem láthatók az építés után Böngésző gyorsítótár/CDN Hasonlítsa össze az eszközhasheket Gyorsítótár törlése + kemény újratöltés

Ha ez nem működik

1) Először is, ellenőrizd a felépítést

  • build/index.asset.php Létezik? Ha hiányzik, a WordPress nem fogja tudni kezelni a függőségeket.
  • Jól csináltad npm run build a bővítmény mappában (nem a projekt gyökérkönyvtárában)?

2) Ellenőrizd az utakat

területén "file:./build/index.js" kapcsolatban áll block.jsonHa elköltöztél block.json Minden egy almappában hibásodik meg. Ez egy gyakori hiba egy adattár átszervezésekor.

3) Ellenőrizd a horgot

Regisztráció initHa túl korán mentesz (például hook nélküli betöltésekor), olyan függvényekkel találkozhatsz, amelyek nem a betöltési sorrendnek megfelelően állnak készen.

4) Ellenőrizd a PHP verzióját

Még mindig látok olyan tárhelyfiókokat, ahol az oldal PHP 7.4/8.0-n fut, pedig a bővítmény 8.1-re íródott. Az eredmény: végzetes hibák. Ellenőrizd az Eszközök > Webhely állapota menüpontot, vagy a következőn keresztül: phpinfo().

5) Bővítmény/kódrészlet ütközések

Egy „kódrészletbővítmény” hibásan működhet, ha hiányzó zárójellel illesztesz be egy kódot. Ha az oldalad összeomlik az aktiválás után:

  • Tiltsa le a bővítményt FTP-n keresztül (nevezze át a mappát),
  • javítsd ki a hibát a debug.log,
  • Újraaktiválás.

Gyakori buktatók és hibák

Hiba Okoz Megoldás
Másold be a PHP kódot a functions.php bővítmény helyett A téma megváltozik, a blokk eltűnik Csomagold be bővítményként, verziózd le, és telepítsd tisztán.
Parse error: syntax error, unexpected ... Hiányzó pontosvessző/zárójel Olvasd újra a különbséget, aktiválj egy PHP lintert, ellenőrizd debug.log
A blokk megjelenik, de a vezérlők nem reagálnak Helytelenül deklarált attribútumok vagy elgépelések a következőben: setAttributes ellenőrzés block.json vs attributes JS-ben használják
Failed to load resource sur index.js Hiányzó build, helytelen elérési út, vagy a fájl nincs telepítve telepíteni build/ Éles környezetben ellenőrizd az engedélyeket.
A kirakott blokk CSS-e Elrejtés, vagy style/editorStyle fordított Gyorsítótár törlése, ellenőrzés block.json, tesztelje privát böngészési módban
A részvények és a szűrők közötti összezavarodás A ... haszna add_filter helyett add_action sur init használat add_action( 'init', ... )
Frissítés után „hibás” blokk Hardcoded függőségek helyett .asset.php Menj át file: + szabványos felépítés
Közvetlen tesztelés éles környezetben biztonsági mentés nélkül Végzetes hiba és leállás kockázata Ellenőrzött előkészítés, biztonsági mentés és telepítés (zip/release)
„Regenerálódó” állandó linkek (mellékhatás) Ritka, de egyes bővítmények módosítják az átírást aktiváláskor. Mentse újra a permalinkeket, ha aktiválás után furcsa viselkedés jelentkezik

Biztonsági, teljesítménybeli és karbantartási tippek

Biztonság

  • Élvezet minden Az attribútumok megbízhatatlanként vannak megjelölve. Még ha a felhasználói felület az adminisztrációs panelen van is, a tartalom REST-en vagy importáláson keresztül befecskendezhető.
  • Ha REST végpontokat adsz hozzá a blokkodhoz, használd a következőt: visszahívási jogosultságok, nunciusok és megfelelő kapacitások.
  • Kerülje a nyers HTML renderelését attribútumok nélkül wp_kses_*.

Teljesítmény

  • Dinamikus blokk: megtart render() gyors, nehéz blokk lekérdezések nélkül.
  • Ha lekérdezésre van szükséged (pl. CPT), használj objektumgyorsítótárat és kerüld az N+1-et.
  • Tartsa minimális CSS-sel. A blokkok ismétlődnek: 20 riasztás egy oldalon = a CSS-nek konzisztensnek kell maradnia.

Karbantartás (tényleges telepítés)

  • Ne építsd éles környezetbe. Építsd CI-ben, és a bővítményt a következővel szállítsd: build/ verziózott (vagy kiadáshoz csatolt).
  • A fejlesztés alatt álló Node verziójának zárolása (nvm, volta), hogy elkerüljük a géptől függő eltérő buildeket.
  • Figyeljük a Gutenberg fejlesztéseit: a legjobb jelzés továbbra is a PR-ek github.com/WordPress/gutenberg.

erőforrás

FAQ

Miért használok @wordpress/scripts-et a saját Webpackem helyett?

Mert csökkented a karbantartási területet. @wordpress/scripts betartja a WordPress konvenciókat (Babel, WP függőségek, generálás) .asset.php). Egy egyedi fejlesztésű webcsomag gyakran eltér és megszakad a következő nagyobb ugrásnál.

Be kell commitolnom a build/ mappát a Gitbe?

Egy webhelyen telepített bővítmény esetében igen, kézbesíteni kell build/Akár véglegesíted, akár egy CI kiadáshoz csatolod, mindegy, de az éles környezetnek nem szabad Node buildtől függenie.

Miért nem tölti be a blokkom a stílusait a kezelőfelületen?

Az esetek 80%-ában: style helytelenül deklarálva block.json, nem telepített build vagy gyorsítótár. Ellenőrizze, hogy build/style-index.css létezik és hozzáférhető.

Dinamikus blokk: káros a gyorsítótárra?

Nem feltétlenül. A HTML-kód az oldal generálásakor jelenik meg, majd minden máshoz hasonlóan gyorsítótárazódik. Az igazi probléma az, ha a render() nehéz, gyorsítótárból kivont kéréseket küld, vagy a felhasználói állapottól függ (ebben az esetben a gyorsítótárat töredezi).

Használhatom az InnerBlocks-ot ezzel a megközelítéssel?

Igen. A következőket kell tennie: (1) nyilatkoznia kell supports.inserter az igényeidtől függően, (2) kezeld $content -ban render() és helyesen meneküljön (gyakran a következőn keresztül: do_blocks() (ha blokkos tartalmat kezelsz). Csak akkor tedd ezt, ha valóban szükséged van rá, különben megsokszorozod a szélsőséges eseteket.

Hogyan kell megfelelően kezelni a nemzetköziesítést (i18n)?

A JS oldalon használd a következőt: __() és meghatározza textdomain -ban block.jsonA PHP oldalon használd a következőt: __()/esc_html__()Ezután hozza létre a fájljait. .po/.mo a szokásos csatornádon keresztül. Doc i18n blokk: Nemzetköziesítés a Blokkszerkesztőben.

A szerkesztőm összeomlik a következő üzenettel: „Nem lehet beolvasni a nem definiált tulajdonságokat”

Általában: hiányzó attribútum (hibás név) vagy váratlan típus. Ellenőrizze a konzisztenciát. block.json ↔ JS. Hibakeresési módban naplózza a attributes -ban edit() és nézd meg a tényleges állapotot.

Hozzáadhatunk egy REST API-t a blokk betáplálásához?

Igen, de győződjön meg róla, hogy biztonságos. Használja register_rest_route() -val permission_callbackBeállítások ellenőrzése és a képességek kezelése. Dokumentáció: Egyéni REST API végpontok hozzáadása.

Hogyan tudom ezt a kódot megfelelően tesztelni?

Három menetben tesztelem:

  • Egység/Integráció legalább a renderelés PHP-tesztje (render()) érvénytelen attribútumokkal (ismeretlen szint, HTML a címben stb.).
  • E2E : cikk létrehozása, blokk beszúrása, közzététel, HTML + CSS ellenőrzése.
  • Kompat : aktiválj egy „nehéz” témát (Avada/Divi) egy stagingen, és ellenőrizd, hogy az osztályaid nincsenek-e felülírva.

Hol tudom nyomon követni azokat a változásokat, amelyek hatással lehetnek a blokkjaimat?

A Gutenberg adattárban (GitHub) és a Core Trac-en (lámpaláz), amikor egy módosítást beolvasztanak a WordPress magjába. Itt láthatod az elavult változtatásokat és az API-változásokat.