Dynamic Block da 0 a 100 in 5 minuti

I blocchi hanno la reputazione di essere complicati. Troppi file di configurazione, troppi tutorial del 2019, troppa magia npm. Ma è ancora così? In questo tutorial ti mostro che il percorso da una cartella vuota a un Dynamic Block funzionante richiede circa 5 minuti. Nessuna conoscenza pregressa, nessun file di configurazione infinito: solo l’essenziale per iniziare subito.

Perché è importante adesso

C’è un altro motivo per cui vale la pena capire le basi. Se hai usato strumenti AI per generare blocchi, avrai notato che usano tutti lo stesso tooling: create-block, wp-scripts, block.json, render.php. Anche se un LLM scrive il codice al posto tuo, devi comunque capire cosa sta facendo. Ed è esattamente lo scopo di questo corso.

Cos’è un Dynamic Block?

Un Static Block salva il suo output HTML direttamente nel database. Quello che si vede nell’editor è esattamente quello che viene memorizzato.

Un Dynamic Block funziona diversamente. Salva solo gli attributi, cioè le impostazioni configurate dall’utente. L’HTML effettivo viene generato da PHP a ogni caricamento della pagina. L’output è sempre aggiornato.

Nessun save.js necessario. Solo un file render.php. Per la maggior parte dei casi d’uso reali, è esattamente quello che serve.

AspettoStatic BlockDynamic Block
OutputHTML salvato nel databaseRenderizzato da PHP a ogni richiesta
save.jsNecessarioNon utilizzato
render.phpNon utilizzatoNecessario
Caso d’usoContenuto fissoDati live/calcolati

Scaffolding: tre comandi e via

WordPress fornisce uno strumento ufficiale di scaffolding: create-block. Tre comandi, e si ottiene un plugin blocco funzionante con un setup di build moderno:

npx @wordpress/create-block@latest my-block --variant=dynamic
cd my-block
npm start

Nessuna configurazione Webpack, tutto è gestito da wp-scripts.

Alcune opzioni del comando

FlagDescrizione
--variant=dynamicCrea un blocco dinamico (con render.php)
--namespace=my-namespaceNamespace personalizzato
--wp-envInclude wp-env per un ambiente Docker locale
--no-pluginCrea solo i file del blocco, senza wrapper plugin

I quattro file che contano

Dopo lo scaffolding, la struttura del plugin si presenta così:

my-block/
├── block.json           # Definizione e metadati del blocco
├── src/
│   ├── index.js         # Registrazione lato client
│   ├── edit.js          # Componente UI per l'editor
│   ├── editor.scss      # Stili editor (opzionale)
│   └── style.scss       # Stili frontend (opzionale)
├── build/               # Output compilato (generato)
│   ├── index.js
│   ├── index.css
│   └── render.php
├── my-block.php         # File principale del plugin
└── package.json         # Dipendenze npm e script

I quattro file fondamentali:

block.json è il manifesto, la fonte di verità del blocco.
index.js registra il blocco lato client.
edit.js è un componente React che controlla l’aspetto del blocco nell’editor.
render.php è dove avviene la magia sul frontend: rendering server-side con PHP.

block.json: il manifesto del blocco

Per i Dynamic Block, il campo più importante è render:

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "my-namespace/my-block",
  "version": "0.1.0",
  "title": "My Dynamic Block",
  "category": "widgets",
  "icon": "smiley",
  "description": "Un blocco con rendering dinamico server-side.",
  "supports": {
    "html": false
  },
  "textdomain": "my-block",
  "editorScript": "file:./index.js",
  "render": "file:./render.php"
}

La riga che fa la differenza

"render": "file:./render.php"

Questa singola riga dice a WordPress: non cercare una funzione save in JavaScript, renderizza questo blocco con PHP. È l’intera differenza tra un blocco statico e uno dinamico.

index.js: registrazione lato client

import Edit from './edit';
import metadata from './block.json';

registerBlockType(metadata.name, {
  edit: Edit,
});

Cosa fa: importa i metadati da block.json, importa il componente Edit, e chiama registerBlockType(). Non c’è nessuna proprietà save, perché il rendering è gestito da render.php.

edit.js: React nell’editor

Il file edit.js è un componente React. Tre cose da ricordare:

useBlockProps(): va sempre applicato con spread sull’elemento root. È il modo in cui WordPress applica classi e stili corretti.
InspectorControls: per aggiungere un pannello di impostazioni nella sidebar.
setAttributes(): da chiamare ogni volta che l’utente modifica qualcosa.

Questo è il pattern. Una volta visto, si può costruire qualsiasi UI per l’editor.

render.php: sempre aggiornato

Il file render.php viene eseguito a ogni caricamento della pagina. Tre cose da sapere:

$attributes: contiene tutto ciò che l’utente ha configurato nell’editor.
get_block_wrapper_attributes(): genera il markup wrapper corretto. Da usare sempre.
esc_html(): per fare l’escape dell’output. Sempre.

<?php
/**
 * PHP file to use when rendering the block.
 */
?>
<p <?php echo get_block_wrapper_attributes(); ?>>
  <?php echo esc_html( $attributes['message'] ?? 'Hello World' ); ?>
</p>

Block Supports: non costruire ciò che WordPress ti dà gratis

Invece di costruire color picker, font size control e spacing UI personalizzati, basta dichiarare nella block.json quello che serve:

"supports": {
  "color": {
    "text": true,
    "background": true
  },
  "typography": {
    "fontSize": true,
    "lineHeight": true
  },
  "spacing": {
    "margin": true,
    "padding": true
  }
}

WordPress genera i controlli nell’editor e applica gli stili nel frontend automaticamente, nell’editor e nel frontend.

Cosa offre ogni Block Support?

Color: color picker per testo e sfondo, verifica contrasto.
Typography: selettore dimensione font, controllo altezza riga.
Spacing: controlli per margine e padding.

L’elenco dei block support è in continua crescita. Per una panoramica completa e aggiornata, consultare la documentazione ufficiale dei Block Supports.

Attributi: la memoria del blocco

Gli attributi definiscono i dati che un blocco memorizza. Si definiscono nella block.json:

"attributes": {
  "message": {
    "type": "string",
    "default": "Hello World"
  },
  "count": {
    "type": "integer",
    "default": 0
  },
  "isVisible": {
    "type": "boolean",
    "default": true
  },
  "items": {
    "type": "array",
    "default": []
  }
}

Tipi disponibili

TipoDescrizioneEsempio
stringValori testuali"Hello"
booleanVero/falsotrue
integerNumeri interi42
numberCome integer3.14
arrayLista di valori["a", "b"]
objectCoppie chiave-valore{"key": "val"}
enumSet fisso di valori"small"

Per i Dynamic Block, gli attributi vengono passati automaticamente a render.php. Non serve collegare nulla manualmente.

Workflow di sviluppo

Due comandi per il lavoro quotidiano:

# Sviluppo (watch mode + hot reload)
npm start

# Build per la produzione
npm run build

Alcuni script disponibili

ScriptScopo
npm startServer di sviluppo con hot reload
npm run buildBuild di produzione
npm run formatFormattazione con Prettier
npm run lint:jsLint JavaScript/TypeScript
npm run lint:cssLint CSS/SCSS

Tutto è alimentato da @wordpress/scripts. Zero configurazione.

Ambiente di sviluppo locale

Per un ambiente Docker locale, si può includere wp-env:

npx @wordpress/create-block@latest my-block --variant=dynamic --wp-env
npm run wp-env start

Il blocco sarà disponibile su http://localhost:8888.

Blocchi solo PHP

Si può registrare un blocco interamente in PHP, senza JavaScript:

register_block_type('my-plugin/server-block', [
  'attributes' => [
    'message' => [
      'type' => 'string',
      'default' => 'Ciao da PHP!'
    ]
  ],
  'render_callback' => function($attributes, $content, $block) {
    $wrapper_attributes = get_block_wrapper_attributes();
    return sprintf(
      '<div %1$s>%2$s</div>',
      $wrapper_attributes,
      esc_html($attributes['message'] ?? 'Ciao!')
    );
  },
]);

Nessun build step, nessun npm, nessun node_modules. Il blocco appare nell’editor tramite ServerSideRender. Per i casi d’uso più semplici, è un’opzione solida.

Bonus: autoRegister (WordPress 7.0)

WordPress 7.0 introduce il flag autoRegister. Quando lo si imposta su true nei supports, il blocco PHP appare automaticamente nell’editor. E WordPress genera i controlli Inspector dalle definizioni degli attributi:

  • string → campo testo
  • boolean → toggle
  • integer → campo numerico
  • enum → dropdown
register_block_type( 'my-plugin/example', [
    'title'           => 'My Block',
    'attributes'      => [
        'title'   => [
            'type'    => 'string',
            'default' => 'Hello World',
        ],
        'count'   => [
            'type'    => 'integer',
            'default' => 5,
        ],
        'enabled' => [
            'type'    => 'boolean',
            'default' => true,
        ],
        'size'    => [
            'type'    => 'string',
            'enum'    => ['small', 'medium', 'large'],
            'default' => 'medium',
        ],
    ],
    'render_callback' => function ( $attributes ) {
        return sprintf(
            '<div>%s: %d items (%s)</div>',
            esc_html( $attributes['title'] ),
            $attributes['count'],
            $attributes['size']
        );
    },
    'supports' => [ 'autoRegister' => true ],
] );

Zero JavaScript. Nessuna riga. Sviluppatori PHP, bentornati.

Bonus: registrazione in blocco (WordPress 6.8+)

Per plugin con più blocchi, da WordPress 6.8 non serve più registrare ogni blocco singolarmente. Si genera un file manifest con wp-scripts e si registrano tutti i blocchi con una sola chiamata:

wp_register_block_types_from_metadata_collection(
    __DIR__ . '/build',
    __DIR__ . '/build/blocks-manifest.php'
);

Per generare il manifest, basta modificare gli script nel package.json:

{
  "scripts": {
    "build": "wp-scripts build --blocks-manifest",
    "start": "wp-scripts start --blocks-manifest"
  }
}

Si aggiunge una nuova cartella blocco, si lancia il build, e il blocco viene riconosciuto automaticamente.

Checklist: il tuo primo blocco in 5 minuti

  1. npx @wordpress/create-block@latest my-block --variant=dynamic
  2. cd my-block && npm start
  3. Modificare src/edit.js per personalizzare l’UI dell’editor
  4. Modificare src/render.php per aggiungere l’output server-side
  5. Modificare block.json per impostare nome, attributi e supports
  6. npm run build per la produzione
  7. Comprimere la cartella del plugin e installare in WordPress

Scaffold. Customize. Build. Repeat.

Risorse

Autore: realloc