Sono in molti a lamentarsi delle difficoltà che si incontrano quando si inizia a creare blocchi e app per Gutenberg. La curva di apprendimento è ripida, soprattutto a causa della difficoltà dell’installazione e della configurazione dell’ambiente di sviluppo. In più, solide conoscenze di JavaScript, Node.js, React e Redux sono ingredienti indispensabili per una ricetta decisamente complessa.

Il Block Editor Handbook ufficiale di WordPress fornisce agli sviluppatori un’enorme quantità di informazioni, ma in quel mare di informazioni ci si può smarrire rapidamente.

E vale la pena ricordare quanto ha affermato Matías Ventura, lead architect del progetto Gutenberg, in una intervista per WP Tavern:

Anche se ci sono persone che possono imparare velocemente, la barriera all’ingresso è ancora molto alta. Penso che ci siano diversi livelli in questo; la documentazione potrebbe essere migliorata di un ordine di grandezza sia nell’organizzazione che nella presentazione. Spero che riusciremo fare molto di più in questi ambiti.

Partendo da queste considerazioni, abbiamo deciso di offrire un tutorial passo passo volto ad aiutare i nostri lettori ad iniziare a sviluppare blocchi per Gutenberg.

Vi sembra interessante? Allora seguiteci!

Prerequisiti per lo Sviluppo dei Blocchi Gutenberg

Per questo tutorial, le uniche competenze richieste sono una buona conoscenza dello sviluppo di plugin WordPress e almeno una conoscenza di base di HTML, CSS, JavaScript e React.

È un progetto ambizioso? Ci potete scommettere!

Non è stato facile trovare il giusto compromesso tra completezza e semplicità e decidere quali argomenti includere e quali tralasciare.

Speriamo solo che i lettori intermedi e avanzati ci perdonino per non aver approfondito concetti come stati di React, store di Redux, high order component e così via. Questi argomenti richiedono maggiore spazio e attenzione e sono probabilmente troppo avanzati per chi inizia a sviluppare blocchi (a meno che non siate già sviluppatori React).

Per lo stesso motivo, non tratteremo alcuni degli argomenti più avanzati relativi allo sviluppo dei blocchi di Gutenberg, come i blocchi dinamici e i meta box.

Ma con le conoscenze che avrete acquisito alla fine di questo articolo, potrete iniziare ed essere produttivi e divertirvi da subito.

Una volta che avrete iniziato a costruire blocchi, potrete progressivamente migliorare le vostre abilità e creare da soli blocchi Gutenberg sempre più avanzati.

Cosa È un Blocco Gutenberg?

Da quando è stato rilasciato per la prima volta nel dicembre 2018, l’editor di blocchi è stato notevolmente migliorato sotto tutti gli aspetti: API più potenti, un’interfaccia utente più avanzata, una migliore usabilità, un sacco di nuovi blocchi, le prime implementazioni del Full Site Editing e molto altro.

In breve, anche se Gutenberg è ancora in fase di sviluppo, ha fatto molta strada e oggi l’editor di blocchi è un candidato a pieno titolo come costruttore affidabile e funzionale sia di pagine che di siti.

Dal punto di vista di uno sviluppatore, Gutenberg è una Single Page Application (SPA) basata su React che permette agli utenti di WordPress di creare, modificare e cancellare contenuti in modo semplice e veloce. Ma questo non deve far pensare a una versione migliorata del tradizionale editor di contenuti.

Vogliamo chiarire questo punto:

In Gutenberg, il contenuto è diviso in blocchi, che sono i “mattoni” che gli utenti possono utilizzare per creare articoli e pagine o i loro interi siti web.

Ma cos’è tecnicamente un blocco?

Ci piace la definizione di WordPress:

“Blocco” è il termine astratto utilizzato per descrivere unità di markup che, composte insieme, formano il contenuto o il layout di una pagina web. L’idea combina i concetti di ciò che in WordPress oggi otteniamo con shortcode, HTML personalizzato e embed discovery in un’unica API coerente e nell’esperienza dell’utente.

Titoli, paragrafi, colonne, immagini, gallerie e tutti gli elementi che compongono l’interfaccia dell’editor, dai pannelli della sidebar ai controlli della barra degli strumenti dei blocchi, sono tutti componenti React.

E quindi cosa sono i componenti React? W3Schools fornisce la seguente definizione:

I componenti sono blocchi di codice indipendenti e riutilizzabili. Hanno lo stesso scopo delle funzioni JavaScript, ma lavorano in modo isolato e restituiscono HTML tramite una funzione render().

Lavorare con i blocchi Gutenberg in WordPress 5.8.
Lavorare con i blocchi Gutenberg in WordPress 5.8.

Mentre l’esperienza di editing offerta da Gutenberg è nuova rispetto al classico editor di WordPress, il modo in cui WordPress memorizza i contenuti nel database non cambia affatto. Questo perché Gutenberg è un’applicazione che lavora all’interno di WordPress, ma non cambia il modo in cui il CMS funziona al suo core.

I post (e questo comprende post, pagine e tipi di post personalizzati) creati con Gutenberg sono sempre memorizzati nella tabella wp_posts, esattamente come nell’editor classico.

Ma in un post creato con Gutenberg, troverete nella tabella altre informazioni che fanno una differenza fondamentale tra i post creati tramite l’editor classico e i post creati con Gutenberg.

Queste informazioni assomigliano ai commenti HTML e hanno una funzione specifica: delimitare i blocchi:

Un post nella vista dell'editor di codice.
Un post nella vista dell’editor di codice.

I delimitatori di blocco dicono a WordPress quale blocco deve essere reso sullo schermo. Oltre a questo, forniscono i valori per le proprietà del blocco in un oggetto JSON. Queste proprietà stabiliscono il modo in cui il blocco deve essere reso sullo schermo:

Un post memorizzato nella tabella wp_posts.
Un post memorizzato nella tabella wp_posts.

Configurazione dell’Ambiente di Sviluppo di WordPress

La configurazione di un moderno ambiente di sviluppo JavaScript richiede una solida conoscenza di tecnologie avanzate come Webpack, React e JSX, Babel, ESLint, ecc.

Intimiditi? Non dovete esserlo! La comunità di WordPress ci viene in soccorso con potenti strumenti che permettono di evitare una complicata procedura di configurazione manuale.

Per mantenere le cose semplici, in questo articolo non tratteremo il transpiling (anche se consigliamo di approfondire l’argomento una volta che avrete acquisito le basi dello sviluppo dei blocchi). Invece, presenteremo due strumenti alternativi utili per configurare un moderno ambiente di sviluppo JavaScript in pochi minuti. Sta a voi scegliere lo strumento che troverete più conveniente e comodo per il vostro progetto.

La configurazione di un ambiente di sviluppo JavaScript per costruire i blocchi di Gutenberg si sviluppa in tre fasi:

  1. Installazione di Node.js e npm
  2. Installazione dell’Ambiente di Sviluppo
  3. Installazione del Plugin del Blocco

Cominciamo.

1. Installare Node.js e npm

Prima di installare l’ambiente di sviluppo e registrare il vostro primo blocco, dovrete installare Node.js e il gestore di pacchetti Node (npm).

Potete installare Node.js e npm in diversi modi. Ma prima dovreste controllare se il software è già installato sulla vostra macchina.

Per farlo, avviate il terminale ed eseguite il seguente comando:

node -v

Se il risultato è command not found, allora Node.js non è installato sul vostro computer e potete procedere con l’installazione.

Per questo articolo, abbiamo scelto l’opzione di installazione più semplice, che è il Node Installer. Tutto quello che dovete fare è scaricare la versione corrispondente al vostro sistema operativo e lanciare la procedura di installazione guidata:

Pagina di download di Node.js.
Pagina di download di Node.js.

Una volta che avete installato Node.js, eseguite nuovamente il comando node -v nel terminale. Potete anche eseguire il comando npm -v per avere la conferma di avere anche il pacchetto npm.

Ora siete equipaggiati con i seguenti strumenti:

  • Il package runner di Node.js npx (vedi la documentazione). Questo vi permette di eseguire un comando npm senza doverlo installare prima.
  • Il gestore di pacchetti di Node.js npm (vedi la documentazione). Questo viene utilizzato per installare le dipendenze ed eseguire gli script.

Il passaggio successivo è l’installazione dell’ambiente di sviluppo.

2. Installare l’Ambiente di Sviluppo

Una volta che avete le ultime versioni di Node.js e npm sulla vostra macchina locale, avrete bisogno di un ambiente di sviluppo per WordPress.

Potete utilizzare un ambiente di sviluppo locale come DevKinsta o utilizzare lo strumento ufficiale di WordPress. Diamo un’occhiata a entrambe le opzioni.

Opzione 1: Ambiente di Sviluppo Locale (DevKinsta)

Con pochi click, potete installare WordPress in locale utilizzando DevKinsta, il nostro moderno strumento di sviluppo locale di WordPress. In alternativa, potete optare per un altro strumento di sviluppo locale, come MAMP o XAMPP:

Creare un nuovo sito WordPress in DevKinsta.
Creare un nuovo sito WordPress in DevKinsta.

Opzione 2: wp-env

Potete anche optare per lo strumento ufficiale wp-env, che fornisce un ambiente di sviluppo locale di WordPress che può essere lanciato direttamente dalla riga di comando. Noah Alen lo definisce come segue:

Gli ambienti WordPress locali sono ora semplici come l’esecuzione di un singolo comando. wp-env è uno strumento a configurazione zero per ambienti WordPress locali privi di difficoltà. Fornisce decisioni sulle opzioni in modo che gli utenti possano far girare rapidamente WordPress senza perdere tempo. Infatti, l’obiettivo è quello di rendere questi ambienti facilmente accessibili a tutti – sviluppatori, designer, manager, o chiunque altro.

Se decidete di fare un tentativo, l’installazione di wp-env richiede uno sforzo minimo. Basta seguire questi passaggi:

Passo 1: Verificare l’Installazione di Docker e Node.js

Per soddisfare i requisiti tecnici, dovrete prima installare sul vostro computer sia Docker che Node.js. Questo perché wp-env crea un’istanza di Docker che esegue un sito WordPress. Qualsiasi modifica apportata al codice si riflette immediatamente nell’istanza di WordPress.

Passo 2: Installare @wordpress/env dalla Riga di Comando

Con Docker e Node.js in esecuzione, procedete e installate l’ambiente di sviluppo per WordPress.

Potete installare wp-env sia a livello globale che locale. Per installarlo a livello globale, avrete bisogno di eseguire il seguente comando dall’interno della directory dei plugin (maggiori informazioni su questo punto nel box di avviso “Importante” qui sotto):

npm install -g @wordpress/env

Scomponiamo il tutto:

Per verificare che wp-env è stato installato correttamente, eseguite questo comando:

wp-env --version

Dovreste vedere la versione corrente di wp-env, il che significa che ora potete lanciare l’ambiente con il seguente comando dalla cartella del vostro plugin:

wp-env start

È possibile accedere alla bacheca di WordPress utilizzando questo indirizzo:

  • http://localhost:8888/wp-admin/

Le credenziali predefinite sono le seguenti:

  • Nome utente: admin
  • Password: password

Installare il Plugin del Blocco

Ora avete bisogno di un plugin iniziale su cui costruire il blocco. Ma invece di creare manualmente un plugin di sviluppo con tutti i file e le cartelle necessarie, si può semplicemente utilizzare uno strumento di sviluppo che fornisce tutti i file e le configurazioni necessarie per iniziare a sviluppare blocchi.

Anche in questo caso, avete a disposizione un paio di soluzioni.

Opzione 1: Installare un Plugin di Blocco con @wordpress/create-block

@wordpress/create-block è lo strumento ufficiale a configurazione zero per creare blocchi Gutenberg:

Create Block è la soluzione ufficiale per la registrazione di un blocco con un plugin WordPress. Offre una moderna configurazione di build che non richiede alcuna configurazione. Genera codice PHP, JS, CSS e tutto quello di cui avete bisogno per avviare il progetto.

È in gran parte ispirato a create-react-app. Complimenti a @gaearon, a tutto il team di Facebook e alla comunità React.

Una volta che il vostro ambiente locale è attivo, potrete configurare un blocco iniziale semplicemente eseguendo il comando npx @wordpress/create-block e questo fornirà tutti i file e le cartelle di cui avete bisogno per creare l’impalcatura del plugin e registrare un nuovo blocco.

Facciamo un test per vedere come funziona.

Dalla linea di comando, spostatevi nella directory /wp-content/plugins/ ed eseguite questo comando:

npx @wordpress/create-block my-first-block

Quando vi viene chiesta conferma, inserite y:

Creare un blocco con @wordpress/create-block.
Creare un blocco con @wordpress/create-block.

Il processo impiega pochi istanti. Quando si sarà concluso, vedrete la seguente risposta:

Il plugin del blocco è stato creato.
Il plugin del blocco è stato creato.

E questo è tutto!

Ora lanciate il vostro ambiente di sviluppo WordPress e andate alla schermata dei plugin nella bacheca di WordPress. Dovrebbe essere stato aggiunto un nuovo plugin chiamato “My First Block” al vostro elenco di plugin:

Il plugin del blocco è stato installato con successo.
Il plugin del blocco è stato installato con successo.

Attivate il plugin se necessario, create un nuovo post, scorrete il pannello di inserimento dei blocchi fino alla sezione Widget e selezionate il vostro nuovo blocco:

Un blocco di esempio creato con @wordpress/create-block.

Ora tornate al terminale e cambiate la directory corrente in my-first-block:

cd my-first-block

Poi eseguite il comando:

npm start

Questo permette di eseguire il plugin in modalità di sviluppo. Per creare il codice di produzione, dovrete invece usare il comando:

npm run build

Opzione 2: Configurare un Plugin di Blocco con create-guten-block

create-guten-block è uno strumento di sviluppo di terze parti per la creazione di blocchi Gutenberg:

create-guten-block è uno strumento di sviluppo a configurazione zero (#0CJS) per sviluppare blocchi Gutenberg in WordPress in pochi minuti senza dover configurare React, webpack, ES6/7/8/Next, ESLint, Babel, ecc.

Esattamente come lo strumento ufficiale create-block, create-guten-block è basato su create-react-app e può aiutarvi a generare il vostro primo plugin di blocco senza problemi.

Il toolkit fornisce tutto il necessario per creare un moderno plugin per WordPress, compreso quanto segue:

  • Supporto della sintassi di React, JSX e ES6.
  • Processo di build webpack di sviluppo/produzione dietro le quinte.
  • Extra del linguaggio oltre ES6 come l’operatore di object spread.
  • CSS con prefisso automatico, quindi non avete bisogno di -webkit o altri prefissi.
  • Uno script di compilazione per impacchettare JS, CSS e immagini per la produzione con le mappe di origine.
  • Aggiornamenti senza problemi per gli strumenti di cui sopra con una sola dipendenza cgb-scripts.

Ma si noti il seguente avvertimento:

Il compromesso è che questi strumenti sono preconfigurati per lavorare in un modo specifico. Se il vostro progetto ha bisogno di maggiore personalizzazione, potete “espellerlo” e personalizzarlo, ma poi dovrete mantenere questa configurazione.

Una volta che avete un sito WordPress locale a portata di mano, lanciate il vostro strumento da linea di comando, spostatevi nella cartella /wp-content/plugins della vostra installazione ed eseguite questo comando:

npx create-guten-block my-first-block

Dovrete aspettare un minuto o due mentre viene creata la struttura del progetto e scaricate le dipendenze:

Creare un blocco Gutenberg con create-guten-block.
Creare un blocco Gutenberg con create-guten-block.

Quando il processo è terminato, dovreste vedere la seguente schermata:

Blocco Gutenberg creato con successo con create-guten-block.
Blocco Gutenberg creato con successo con create-guten-block.

L’immagine che segue mostra la struttura del progetto con il terminale in esecuzione in Visual Studio Code:

Il plugin di blocco in Visual Studio Code.
Il plugin di blocco in Visual Studio Code.

Ora tornate alla vostra bacheca di WordPress. Dovrebbe essere stato aggiunto un nuovo elemento nell’elenco della schermata dei plugin – è il plugin my-first-block:

La schermata dei plugin con un nuovo plugin creato con create-guten-block.
La schermata dei plugin con un nuovo plugin creato con create-guten-block.

Attivate il plugin e tornate al terminale. Cambiate la directory corrente in my-first-block, poi eseguite npm start:

cd my-first-block
npm start

Dovreste avere la seguente risposta:

npm start.
npm start.

Questo, come dicevamo, vi permette di eseguire il plugin in modalità di sviluppo. Per creare il codice di produzione, dovrete usare:

npm run build

Attivate il plugin e create un nuovo post o una nuova pagina, poi sfogliate i vostri blocchi e selezionate il vostro nuovo blocco Gutenberg:

Un nuovo blocco creato con create-guten-block.
Un nuovo blocco creato con create-guten-block.

Per una panoramica più approfondita o in caso di errori, fate riferimento alla documentazione fornita da Ahmad Awais.

Analisi dell’Impalcatura del Blocco di Avvio

Qualunque sia il dev-tool che scegliete, create-block o create-guten-block, ora avete un’impalcatura che potete usare come punto di partenza per costruire un plugin per il vostro blocco.

Ma cos’è esattamente un’impalcatura del blocco o “block scaffolding”?

Block scaffolding è un termine abbreviato che descrive la struttura delle directory di supporto necessaria a WordPress per riconoscere un blocco. Normalmente questa directory contiene file come index.php, index.js, style.css e altri – che a loro volta contengono chiamate come register_block_type.

Abbiamo optato per il dev-tool ufficiale Create Block, in quanto è utilizzato nel Block Editor Handbook. Ma, anche se decidete di usare uno strumento di terze parti come create-guten-block, la vostra esperienza non sarà troppo diversa.

Detto questo, analizziamo più dettagliatamente il tool create-block.

Uno Sguardo Più da Vicino allo Strumento di Sviluppo Create Block

Come abbiamo detto in precedenza, Create Block è lo strumento ufficiale a riga di comando per creare blocchi Gutenberg. L’esecuzione di @wordpress/create-block nel vostro terminale genera i file PHP, JS e SCSS e il codice necessario per registrare un nuovo tipo di blocco:

npx @wordpress/create-block [options] [slug]
  • [slug] (opzionale) — usato per assegnare lo slug del blocco e installare il plugin
  • [options] (opzionale) — opzioni disponibili

Di default viene assegnato un template ESNext. Questo significa che otterrete la prossima versione di JavaScript, con l’aggiunta della sintassi JSX.

Se si omette il nome del blocco, il comando viene eseguito in modalità interattiva, permettendovi di personalizzare diverse opzioni prima di generare i file:

npx @wordpress/create-block
Esecuzione di create-block in modalità interattiva.
Esecuzione di create-block in modalità interattiva.

L’immagine qui sotto mostra la struttura del file di un plugin di blocco creato con lo strumento ufficiale Create Block:

File e cartelle di un plugin di blocco creato con @wordpress/create-block.
File e cartelle di un plugin di blocco creato con @wordpress/create-block.

Detto questo, scorriamo i file e le cartelle principali del nostro nuovo plugin di blocco.

Il File del Plugin

Con il file principale del plugin si registra il blocco sul server:

<?php
/**
 * Plugin Name:       Kinsta Academy Block
 * Plugin URI:        https://kinsta.com/
 * Description:       An example block for Kinsta Academy students
 * Requires at least: 5.9
 * Requires PHP:      7.0
 * Version:           0.1.0
 * Author:            Kinsta Students
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       ka-example-block
 *
 * @package           ka-example-block
 */

/**
 * Registers the block using the metadata loaded from the `block.json` file.
 * Behind the scenes, it registers also all assets so they can be enqueued
 * through the block editor in the corresponding context.
 *
 * @see https://developer.wordpress.org/reference/functions/register_block_type/
 */
function ka_example_block_ka_example_block_block_init() {
	register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'ka_example_block_ka_example_block_block_init' );

La funzione register_block_type registra un tipo di blocco sul server usando i metadati memorizzati nel file block.json.

La funzione accetta due parametri:

  • Il nome del tipo di blocco, incluso il namespace, o il percorso della cartella dove si trova il file block.json, o un oggetto WP_Block_Type completo
  • Un array di argomenti del tipo di blocco

Nel codice qui sopra, la costante magica __DIR__ restituisce la cartella corrente. Ciò significa che il file block.json risiede nella cartella /build.

Il file package.json

Il file package.json definisce le proprietà e gli script JavaScript del vostro progetto. Qui è dove potete installare le dipendenze del vostro progetto.

Per capire meglio a cosa serve questo file, apritelo con il vostro editor di codice preferito:

{
	"name": "ka-example-block",
	"version": "0.1.0",
	"description": "An example block for Kinsta Academy students",
	"author": "Kinsta Students",
	"license": "GPL-2.0-or-later",
	"homepage": "https://kinsta.com/",
	"main": "build/index.js",
	"scripts": {
		"build": "wp-scripts build",
		"format": "wp-scripts format",
		"lint:css": "wp-scripts lint-style",
		"lint:js": "wp-scripts lint-js",
		"packages-update": "wp-scripts packages-update",
		"plugin-zip": "wp-scripts plugin-zip",
		"start": "wp-scripts start"
	},
	"devDependencies": {
		"@wordpress/scripts": "^24.1.0"
	},
	"dependencies": {
		"classnames": "^2.3.2"
	}
}

La proprietà scripts è un dizionario contenente i comandi che vengono eseguiti in vari momenti del ciclo di vita di un pacchetto con npm run [cmd].

In questo articolo, useremo i seguenti comandi:

  • npm run build — crea una build di produzione (compressa)
  • npm run start o npm start — crea una build di sviluppo (non compressa)

dependencies e devDependencies sono due oggetti che mappano il nome di un pacchetto a una versione. Le dependencies sono richieste in produzione, mentre le devDependences sono necessarie solo per lo sviluppo locale (leggi di più).

L’unica dipendenza di sviluppo predefinita è il pacchetto @wordpress/scripts, che è definito come “una raccolta di script riutilizzabili su misura per lo sviluppo di WordPress”.

Il file block.json

A partire da WordPress 5.8, il file dei metadati block.json è il modo canonico per registrare i tipi di blocco.

Un file block.json offre diversi vantaggi, tra cui prestazioni migliori e una migliore visibilità nella directory dei plugin di WordPress:

Dal punto di vista delle prestazioni, quando i temi supportano il lazy loading delle risorse, i blocchi registrati con block.json avranno l’enqueuing ottimizzato nativamente. Le risorse CSS e JavaScript del frontend elencate nelle proprietà style o script saranno messe in coda solo quando il blocco è presente nella pagina, con conseguente riduzione delle dimensioni della pagina.

L’esecuzione del comando @wordpress/create-block genera il seguente file block.json:

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 2,
	"name": "ka-example-block/ka-example-block",
	"version": "0.1.0",
	"title": "Kinsta Academy Block",
	"category": "widgets",
	"icon": "superhero-alt",
	"description": "An example block for Kinsta Academy students",
	"supports": {
		"html": false
	},
	"textdomain": "ka-example-block",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css"
}

Ecco l’elenco completo delle proprietà predefinite:

  • apiVersion — la versione dell’API usata dal blocco (la versione attuale è la 2)
  • name — un identificatore univoco per un blocco che include un namespace
  • version — la versione corrente di un blocco
  • title — il titolo del blocco
  • category — una categoria di blocco
  • icon — uno slug Dashicon o un’icona SVG personalizzata
  • description — una breve descrizione visibile nel block inspector
  • supports — un insieme di opzioni per controllare le funzionalità usate nell’editor
  • textdomain — il text-domain del plugin
  • editorScript — definizione dello script dell’editor
  • editorStyle — definizione dello stile dell’editor
  • style — fornisce stili alternativi per un blocco

Oltre alle proprietà elencate qui sopra, potete (e probabilmente lo farete) definire un oggetto attributes che fornisce informazioni sui dati memorizzati dal vostro blocco. Nel vostro block.json potete impostare un numero arbitrario di attributi in coppie chiave/valore, dove la chiave è il nome dell’attributo e il valore è la definizione dell’attributo.

Ecco un esempio di definizione di attributi:

"attributes": {
	"content": {
		"type": "array",
		"source": "children",
		"selector": "p"
	},
	"align": {
		"type": "string",
		"default": "none"
	},
	"link": { 
		"type": "string", 
		"default": "https://kinsta.com" 
	}
},

Analizzeremo più a fondo il file block.json più avanti nell’articolo, ma potreste anche dare un’occhiata al Block Editor Handbook per informazioni più dettagliate sui metadati e sugli attributi del file block.json.

La Cartella src

La cartella src è il posto avviene lo sviluppo. In questa cartella troverete i seguenti file:

  • index.js
  • edit.js
  • save.js
  • editor.scss
  • style.scss

index.js

Il file index.js è il vostro punto di partenza. Qui importerete le dipendenze e registrerete il tipo di blocco sul client:

import { registerBlockType } from '@wordpress/blocks';

import './style.scss';

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

registerBlockType( metadata.name, {
	/**
	 * @see ./edit.js
	 */
	edit: Edit,

	/**
	 * @see ./save.js
	 */
	save,
} );

La prima dichiarazione importa la funzione registerBlockType dal pacchetto @wordpress/blocks. Le successive dichiarazioni importano il foglio di stile e le funzioni Edit e save.

La funzione registerBlockType registra il componente sul client. La funzione accetta due parametri: un nome namespace/block-name (lo stesso registrato sul server) e un oggetto di configurazione del blocco.

La funzione Edit fornisce l’interfaccia del blocco come viene resa nell’editor di blocchi, mentre la funzione save fornisce la struttura che sarà serializzata e salvata nel database (leggi di più).

edit.js

edit.js è il file dove costruirete l’interfaccia di amministrazione del blocco:

import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';

export default function Edit() {
	return (
		<p {...useBlockProps()}>
			{__('My First Block – hello from the editor!', 'my-first-block')}
		</p>
	);
}

Per prima cosa, questo importa la funzione __ dal pacchetto @wordpress/i18n (questo pacchetto contiene una versione JavaScript delle funzioni di traduzione), l’hook React useBlockProps e il file editor.scss.

Quindi esporta il componente React (si legga di più sulle dichiarazioni di importazione ed esportazione).

save.js

Il file save.js è dove costruiamo la struttura del blocco da salvare nel database:

import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';

export default function save() {
	return (
		<p {...useBlockProps.save()}>
			{__(
				'My First Block – hello from the saved content!',
				'my-first-block'
			)}
		</p>
	);
}

editor.scss e style.scss

Oltre agli script, due file SASS risiedono nelle cartelle src. Il file editor.scss contiene gli stili applicati al blocco nel contesto dell’editor, mentre il file style.scss contiene gli stili del blocco per la visualizzazione sia nel frontend che nell’editor. Approfondiremo questi file nella seconda parte di questa guida.

Le Cartelle node_modules e build

La cartella node_modules contiene i moduli di node e le rispettive dipendenze. Non analizzeremo nel dettaglio i pacchetti di node perché è al di là dello scopo di questo articolo, ma potrete approfondire il discorso in questo articolo che spiega dove vengono installati i pacchetti con npm.

La cartella build contiene i file JS e CSS risultanti dal processo di build. Potete approfondire il processo di build nelle guide ESNext syntax e JavaScript Build Setup.

Il Progetto: il Nostro Primo Blocco Gutenberg

È ora di sporcarsi le mani. In questa sezione spieghiamo come creare un plugin che fornisce un blocco CTA chiamato Kinsta Academy Block.

Il blocco sarà composto da due colonne, con un’immagine a sinistra e un paragrafo di testo a destra. Un pulsante con un link personalizzabile sarà posizionato sotto il testo:

Il tipo di blocco che creiamo in questa guida.
Il tipo di blocco che creiamo in questa guida.

È solo un semplice esempio, ma ci permetterà di acquisire le basi dello sviluppo dei blocchi di Gutenberg. Una volta che avrete una chiara comprensione dei concetti di base, potrete proseguire in autonomia e creare blocchi Gutenberg sempre più complessi, con l’aiuto del Block Editor Handbook e tutte le altre numerose risorse disponibili in rete.

Supponendo che abbiate l’ultima versione di WordPress in esecuzione sul vostro ambiente di sviluppo locale, ecco cosa imparerete da qui in avanti:

Pronti… via!

Come Installare il Plugin del Blocco di Avvio

Lanciate il vostro tool a riga di comando e spostatevi nella cartella /wp-content/plugins:

New terminal at folder in Mac OS.
New terminal at folder in Mac OS.

Ora eseguite il seguente comando:

npx @wordpress/create-block

Questo comando genera i file PHP, SCSS e JS per la registrazione di un blocco in modalità interattiva, permettendovi di aggiungere facilmente i dati necessari al vostro blocco. Per il nostro esempio useremo i seguenti dati:

  • Template variant: static
  • Block slug: ka-example-block
  • Internal namespace: ka-example-block
  • Block display title: Kinsta Academy Block
  • Short block description: An example block for Kinsta Academy students
  • Dashicon: superhero-alt
  • Category name: widgets
  • Do you want to customize the WordPress plugin?: yes
  • The home page of the plugin: https://kinsta.com/
  • Current plugin version: 0.1.0
  • Plugin author: your name
  • License: –
  • Link to the license text: –
  • Custom domain path for translations: –

L’installazione del plugin e di tutte le dipendenze richiede un paio di minuti. Quando il processo sarà terminato, vedrete la seguente risposta:

Il blocco è stato installato e registrato per lo sviluppo.
Il blocco è stato installato e registrato per lo sviluppo.

Ora eseguite questo comando dalla cartella /wp-content/plugins:

cd ka-example-block
Esecuzione di comandi dal terminale di Visual Studio Code.
Esecuzione di comandi dal terminale di Visual Studio Code.

Infine, dalla cartella del vostro plugin (ka-example-block nel nostro esempio), potete avviare lo sviluppo con:

npm start

Ora aprite la schermata dei plugin e attivate il plugin Kinsta Academy Block:

Attivazione del blocco di esempio
Attivazione del blocco di esempio

Create un nuovo post, aprite il block inserter e scorrete fino alla categoria Design. Quindi fate clic per aggiungere il blocco:

Un blocco di avvio creato con @wordpress/create-block.
Un blocco di avvio creato con @wordpress/create-block.

Il File block.json al Lavoro

Come abbiamo detto in precedenza, la registrazione del blocco lato server avviene nel file .php principale. Tuttavia, non definiremo le impostazioni nel file .php, ma useremo il file block.json.

Quindi aprite di nuovo block.json e diamo un’occhiata più da vicino alle impostazioni predefinite:

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 2,
	"name": "ka-example-block/ka-example-block",
	"version": "0.1.0",
	"title": "Kinsta Academy Block",
	"category": "widgets",
	"icon": "superhero-alt",
	"description": "An example block for Kinsta Academy students",
	"supports": {
		"html": false
	},
	"textdomain": "ka-example-block",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css"
}

Script e Stili

Le proprietà editorScript, editorStyle e style forniscono i percorsi relativi agli script e agli stili del frontend e del backend.

Non è necessario registrare manualmente gli script e gli stili definiti qui perché questi sono automaticamente registrati e accodati da WordPress. Per provarlo, lanciate l’inspector del browser e aprite la scheda Network:

Ispezione delle risorse in Chrome DevTools.
Ispezione delle risorse in Chrome DevTools.

Come si vede dall’immagine qui sopra, il nostro script index.js che risiede nella cartella build è stato regolarmente accodato senza dover aggiungere alcun codice PHP.

Etichette di UI

Le proprietà title e description forniscono le etichette necessarie per identificare il blocco nell’editor:

Nome del blocco e descrizione nella sidebar del blocco.
Nome del blocco e descrizione nella sidebar del blocco.

Keyword

Come abbiamo detto, è possibile configurare dettagliatamente le impostazioni del blocco usando proprietà e attributi. Ad esempio, è possibile aggiungere una o più keywords per aiutare gli utenti a cercare i blocchi:

"keywords": [ 
		"kinsta", 
		"academy", 
		"superhero" 
	],

Se ora inserite “kinsta”, “academy” o “superhero” nel pannello di inserimento rapido dei blocchi, l’editor vi suggerirà il blocco custom:

Ricerca di un blocco con una parola chiave nel pannello di inserimento rapido.
Ricerca di un blocco con una parola chiave nel pannello di inserimento rapido.

Localizzazione

Se vi state chiedendo come avviene la localizzazione delle stringhe nel file JSON, ecco la risposta:

In JavaScript, ora si può usare il metodo registerBlockTypeFromMetadata dal pacchetto @wordpress/blocks per registrare un tipo di blocco usando i metadati caricati dal file block.json. Tutte le proprietà localizzate vengono automaticamente avvolte in chiamate di funzione _x (dal pacchetto @wordpress/i18n) come avviene in PHP con register_block_type_from_metadata. L’unico requisito è la proprietà textdomain nel file block.json.

Qui utilizziamo la funzione registerBlockType invece di registerBlockTypeFromMetadata, dato che quest’ultima è stata deprecata a partire da Gutenberg 10.7, ma il meccanismo è lo stesso.

Usare i Componenti Incorporati: Il Componente RichText

Gli elementi che compongono un blocco Gutenberg sono componenti React e si può accedere a questi componenti tramite la variabile globale wp. Ad esempio, provate a digitare wp.editor nella console del vostro browser. Questo vi darà l’elenco completo dei componenti inclusi nel modulo wp.editor.

Scorrete la lista e provate a indovinare a cosa servono i componenti dai rispettivi nomi.

Allo stesso modo, potete scorrere la lista dei componenti inclusi nel modulo wp.components:

WP components
WP components

Ora torniamo al file edit.js e diamo un’occhiata più da vicino allo script:

import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';

export default function Edit() {
	return (
		<p { ...useBlockProps() }>
			{ __(
				'Kinsta Academy Block – hello from the editor!',
				'ka-example-block'
			) }
		</p>
	);
}

Questo codice genera un blocco statico con un testo semplice e non modificabile. Ma possiamo cambiare le cose facilmente:

Il blocco iniziale nell'editor di codice.
Il blocco iniziale nell’editor di codice.

Per rendere il testo modificabile dovrete sostituire l’attuale tag <p> con un componente che renda modificabile il contenuto dell’input. Per questo, Gutenberg fornisce il componente integrato RichText.

Aggiungere un componente integrato ad un blocco richiede 5 passaggi:

  1. Importazione dei Componenti Necessari da un Pacchetto WordPress
  2. Inserimento degli Elementi Corrispondenti nel Codice JSX
  3. Definizione degli Attributi Necessari nel File block.json
  4. Definizione degli Event Handler
  5. Salvataggio dei Dati

Passo 1: Importazione dei Componenti Necessari da un Pacchetto WordPress

Ora aprite il file edit.js e cambiate la seguente dichiarazione import:

import { useBlockProps } from '@wordpress/block-editor';

nella seguente:

import { useBlockProps, RichText } from '@wordpress/block-editor';

In questo modo, importiamo la funzione useBlockProps e il componente RichText dal pacchetto @wordpress/block-editor.

useBlockProps

L’hook React useBlockProps contrassegna l’elemento wrapper del blocco:

Quando si utilizzano le API versione 2, è necessario utilizzare il nuovo hook useBlockProps nella funzione edit per contrassegnare l’elemento wrapper del blocco. L’hook inserirà gli attributi e gli event handler necessari per abilitare il comportamento del blocco. Qualsiasi attributo che vuoi passare all’elemento del blocco deve essere passato attraverso useBlockProps e il valore restituito deve essere distribuito sull’elemento.

Per spiegare le cose in modo semplice, useBlockProps assegna automaticamente attributi e classi all’elemento wrapper (l’elemento p nel nostro esempio):

Elementi e classi generati da useBlockProps.
Elementi e classi generati da useBlockProps.

Se si rimuove useBlockProps dall’elemento wrapper, si avrà una semplice stringa di testo senza accesso alle funzionalità e allo stile del blocco:

Lo stesso blocco senza useBlockProps.
Lo stesso blocco senza useBlockProps.

Come spiegheremo più avanti, potete anche passare a useBlockProps un oggetto di proprietà per personalizzare l’output.

RichText

Il componente RichText fornisce un input contenteditable, permettendo agli utenti di modificare e formattare il contenuto.

Il componente è documentato su GitHub all’indirizzo gutenberg/packages/block-editor/src/components/rich-text/README.md.

Passo 2: Inserimento degli Elementi Corrispondenti nel Codice JSX

...

const blockProps = useBlockProps();

return (
	<RichText 
		{ ...blockProps }
		tagName="p"
		onChange={ onChangeContent }
		allowedFormats={ [ 'core/bold', 'core/italic' ] }
		value={ attributes.content }
		placeholder={ __( 'Write your text...' ) }
	/>
);

Commentiamo il codice riga per riga:

  • tagName — il nome del tag dell’elemento HTML modificabile
  • onChange — funzione invocata quando cambia il contenuto dell’elemento
  • allowedFormats — un array di formati consentiti. Per impostazione predefinita, tutti i formati sono consentiti
  • value — la stringa HTML da rendere modificabile
  • placeholder — testo segnaposto da mostrare quando l’elemento è vuoto

Passo 3: Definizione degli Attributi Necessari nel File block.json

Gli attributi forniscono informazioni sui dati memorizzati da un blocco, come il rich content, il colore di sfondo, gli URL, ecc.

È possibile impostare un numero arbitrario di attributi all’interno di un oggetto attributes in coppie chiave/valore, dove la chiave è il nome dell’attributo e il valore è la definizione dell’attributo.

Ora aprite il file block.json e aggiungete la seguente proprietà attributes:

"attributes": {
	"content": {
		"type": "string",
		"source": "html",
		"selector": "p"
	}
},

L’attributo content permette di memorizzare il testo digitato dall’utente nel campo editabile:

  • type indica il tipo di dati memorizzati dall’attributo. Il tipo è richiesto a meno che non si definisca una proprietà enum.
  • source definisce il modo in cui il valore dell’attributo viene estratto dal contenuto del post. Nel nostro esempio, si tratta del contenuto HTML. Si noti che, se non viene fornita una proprietà source, i dati saranno memorizzati nel delimitatore di blocco (leggi tutto).
  • selector è un tag HTML o qualsiasi altro selettore, come il nome di una classe o un attributo id.

Passeremo alla funzione Edit un oggetto di proprietà. Quindi tornate al file edit.js e fate la seguente modifica:

export default function Edit( { attributes, setAttributes } ) { ... }

Passo 4: Definizione degli Event Handler

L’elemento RichText ha un attributo onChange, che fornisce una funzione da invocare quando il contenuto dell’elemento cambia.

Definiamo questa funzione e vediamo l’intero script edit.js:

import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';
import './editor.scss';

export default function Edit( { attributes, setAttributes } ) {
	const blockProps = useBlockProps();

	const onChangeContent = ( newContent ) => {
		setAttributes( { content: newContent } )
	}

	return (
		<RichText 
			{ ...blockProps }
			tagName="p"
			onChange={ onChangeContent }
			allowedFormats={ [ 'core/bold', 'core/italic' ] }
			value={ attributes.content }
			placeholder={ __( 'Write your text...' ) }
		/>
	);
}

Ora salvate il file ed eseguite npm run start nella finestra di terminale. Poi tornate alla bacheca di WordPress, create un nuovo articolo o pagina e aggiungete il vostro blocco:

L'output del componente RichText nel Block Editor.
L’output del componente RichText nel Block Editor.

Aggiungete del testo e passate alla vista Codice. Ecco come dovrebbe apparire il vostro codice:

<!-- wp:ka-example-block/ka-example-block -->
<p class="wp-block-ka-example-block-ka-example-block">Kinsta Academy Block – hello from the saved content!</p>
<!-- /wp:ka-example-block/ka-example-block -->

Se ora salvate la pagina e controllate il risultato nel frontend, potreste rimanere un po’ delusi perché le vostre modifiche non avranno avuto effetto sul sito. Questo perché dobbiamo ancora modificare il file save.js per memorizzare l’input dell’utente nel database quando il post viene salvato.

Passo 5: Salvataggio dei Dati

Ora aprite il file save.js e cambiate lo script come segue:

import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';

export default function save( { attributes } ) {
	const blockProps = useBlockProps.save();
	return (
		<RichText.Content 
			{ ...blockProps } 
			tagName="p" 
			value={ attributes.content } 
		/>
	);
}

Questo è quello che stiamo facendo qui:

  • Importiamo il componente RichText dal pacchetto block-editor.
  • Passiamo diverse proprietà attraverso un argomento oggetto alla funzione save (in questo esempio, stiamo passando solo la proprietà attributes)
  • Viene restituito il contenuto del componente RichText
Il contenuto del blocco è stato salvato nel database.
Il contenuto del blocco è stato salvato nel database.

Per altre info sul componente RichText, potrete fare riferimento al Block Editor Handbook e all’elenco completo delle proprietà su Github.

Ora facciamo un passo avanti. Nella prossima sezione, scopriremo come aggiungere controlli alla barra degli strumenti del blocco.

Aggiungere Controlli alla Barra degli Strumenti del Blocco

La barra degli strumenti dei blocchi contiene un insieme di controlli che permettono agli utenti di manipolare porzioni di contenuto del blocco. Troverete un componente per ogni controllo della barra degli strumenti:

La barra degli strumenti del blocco core paragrafo.
La barra degli strumenti del blocco core paragrafo.

Ad esempio, potreste aggiungere un controllo di allineamento del testo per il vostro blocco. Tutto quello che dovete fare è importare due componenti dal pacchetto @wordpress/block-editor.

Seguiremo gli stessi passi dell’esempio precedente:

  1. Importazione dei Componenti Necessari da un Pacchetto WordPress
  2. Inserimento degli Elementi Corrispondenti nel Codice JSX
  3. Definizione degli Attributi Necessari nel File block.json
  4. Definizione degli Event Handler
  5. Salvataggio dei Dati

Passo 1: Importazione dei componenti BlockControls e AlignmentControl da @wordpress/block-editor

Per aggiungere un controllo di allineamento alla barra degli strumenti del blocco, avete bisogno di due componenti:

  • BlockControls genera una barra degli strumenti dinamica di controlli (non documentato).
  • AlignmentControl genera un menu a discesa che visualizza le opzioni di allineamento per il blocco selezionato (leggi di più)

Aprite il file edit.js e modificate la dichiarazione import come mostrato di seguito:

import { 
	useBlockProps, 
	RichText, 
	AlignmentControl, 
	BlockControls 
} from '@wordpress/block-editor';

Passo 2: Aggiungere gli Elementi BlockControls e AlignmentControl al Codice JSX

Andate alla funzione Edit e inserite l’elemento <BlockControls /> allo stesso livello di <RichText />. Poi aggiungete <AlignmentControl /> all’interno di <BlockControls />:

export default function Edit( { attributes, setAttributes } ) {
	const blockProps = useBlockProps();
	return (
		<>
			<BlockControls>
				<AlignmentControl
					value={ attributes.align }
					onChange={ onChangeAlign }
				/>
			</BlockControls>
			<RichText 
				{ ...blockProps }
				tagName="p"
				onChange={ onChangeContent }
				allowedFormats={ [ 'core/bold', 'core/italic' ] }
				value={ attributes.content }
				placeholder={ __( 'Write your text...' ) }
				style={ { textAlign: attributes.align } }
			/>
		</>
	);
}

Nel codice qui sopra, <> e </> sono la sintassi breve per dichiarare i frammenti React, che sono il modo in cui vengono restituti elementi multipli in React.

In questo esempio, AlignmentControl ha due attributi:

  • value fornisce il valore corrente dell’elemento
  • onChange fornisce un event handler da eseguire quando il valore cambia

Abbiamo anche definito altri attributi per l’elemento RichText (si veda la lista completa degli attributi con esempi)

Passo 3: Definizione dell’Attributo align in block.json

Ora tornate al file block.json e aggiungete l’attributo align:

"align": {
	"type": "string",
	"default": "none"
}

Tornate all’editor di blocchi, aggiornate la pagina e selezionate il blocco. Dovrebbe essere visualizzato un messaggio di errore all’interno del blocco.

Il blocco mostra un messaggio di errore.
Il blocco mostra un messaggio di errore.

Il motivo è che non abbiamo ancora definito il nostro event handler.

Passo 4: Definizione degli Event Handler

Ora definite onChangeAlign:

const onChangeAlign = ( newAlign ) => {
	setAttributes( { 
		align: newAlign === undefined ? 'none' : newAlign, 
	} )
}

Se newAlign è undefined, allora impostiamo newAlign su none. Altrimenti, usiamo newAlign.

Il nostro script edit.js dovrebbe essere completo (per ora):

export default function Edit( { attributes, setAttributes } ) {
	const blockProps = useBlockProps();
	const onChangeContent = ( newContent ) => {
		setAttributes( { content: newContent } )
	}
	const onChangeAlign = ( newAlign ) => {
		setAttributes( { 
			align: newAlign === undefined ? 'none' : newAlign, 
		} )
	}
	return (
		<>
			<BlockControls>
				<AlignmentControl
					value={ attributes.align }
					onChange={ onChangeAlign }
				/>
			</BlockControls>
			<RichText 
				{ ...blockProps }
				tagName="p"
				onChange={ onChangeContent }
				allowedFormats={ [ 'core/bold', 'core/italic' ] }
				value={ attributes.content }
				placeholder={ __( 'Write your text...' ) }
				style={ { textAlign: attributes.align } }
			/>
		</>
	);
}

Ora Potete tornare all’editor e allineare il contenuto del blocco. Il blocco dovrebbe ora mostrare fieramente una barra di allineamento.

Il nostro blocco ora ha una barra di allineamento.
Il nostro blocco ora ha una barra di allineamento.

Ma se salvate il post, vedrete che il contenuto del blocco non è allineato sul front-end come nell’editor dei blocchi. Questo perché dobbiamo ancora modificare la funzione save per memorizzare il contenuto e gli attributi dei blocchi nel database.

Passo 5: Salvataggio dei Dati

Aprite save.js e cambiate la funzione save come segue:

export default function save( { attributes } ) {
	const blockProps = useBlockProps.save();
	return (
		<RichText.Content 
			{ ...blockProps } 
			tagName="p" 
			value={ attributes.content } 
			style={ { textAlign: attributes.align } }
		/>
	);
}

Infine, per rendere il codice più leggibile, potete estrarre le singole proprietà dall’oggetto attribute usando la sintassi dell’assegnazione di destrutturazione:

export default function save( { attributes } ) {
	const blockProps = useBlockProps.save();
	const { content, align } = attributes;
	return (
		<RichText.Content 
			{ ...blockProps } 
			tagName="p" 
			value={ content } 
			style={ { textAlign: align } }
		/>
	);
}

Potete fare lo stesso nel file edit.js.

Salvate il file e tornate all’editor in modalità Codice. Il codice dovrebbe assomigliare a questo:

<!-- wp:ka-example-block/ka-example-block {"align":"right"} -->
<p class="wp-block-ka-example-block-ka-example-block" style="text-align:right">This is my first editable <strong>Gutenberg</strong> <em>block</em> 😎</p>
<!-- /wp:ka-example-block/ka-example-block -->
I controlli della barra degli strumenti del blocco.
I controlli della barra degli strumenti del blocco.

E questo è tutto! avete appena aggiunto un controllo di allineamento alla barra degli strumenti del blocco 🤓

Potete leggere di più sui controlli della barra degli strumenti dei blocchi nel Block Editor Handbook.

Personalizzare la Sidebar delle Impostazioni del Blocco

Potete anche aggiungere dei controlli alla sidebar delle impostazioni del blocco (o anche creare una nuova sidebar per la vostra applicazione).

L’API fornisce un componente InspectorControls per questo.

Il Block Editor Handbook spiega come usare la sidebar delle impostazioni:

La sidebar delle impostazioni viene utilizzata per visualizzare le impostazioni meno utilizzate o quelle che richiedono più spazio sullo schermo. La sidebar delle impostazioni dovrebbe essere utilizzata solo per le impostazioni a livello di blocco.

Se avete delle impostazioni che influenzano solo il contenuto selezionato all’interno di un blocco (ad esempio l’impostazione “grassetto” per il testo selezionato all’interno di un paragrafo): non mettetela all’interno della sidebar delle impostazioni. La sidebar delle impostazioni viene visualizzata anche quando si modifica un blocco in modalità HTML, quindi dovrebbe contenere solo impostazioni a livello di blocco.

Di nuovo:

  1. Importazione dei Componenti Necessari da un Pacchetto WordPress
  2. Inserimento degli Elementi Corrispondenti nel Codice JSX
  3. Definizione degli Attributi Necessari nel File block.json
  4. Definizione degli Event Handler
  5. Salvataggio dei Dati

Passo 1. Importare i componenti InspectorControls e PanelColorSettings da @wordpress/block-editor

Potete aggiungere diversi controlli per permettere agli utenti di personalizzare aspetti specifici del blocco. Ad esempio, potete fornire un pannello di controllo dei colori. Per farlo, dovrete importare i componenti InspectorControls e PanelColorSettings dal modulo block-editor:

import { 
	useBlockProps, 
	RichText, 
	AlignmentControl, 
	BlockControls,
	InspectorControls,
	PanelColorSettings
} from '@wordpress/block-editor';

Passo 2: Inserire gli Elementi Corrispondenti nel Codice JSX

Ora potete aggiungere gli elementi corrispondenti al codice JSX restituito dalla funzione Edit:

export default function Edit( { attributes, setAttributes } ) {
	const blockProps = useBlockProps();

	const { content, align, backgroundColor, textColor } = attributes;

	const onChangeContent = ( newContent ) => {
		setAttributes( { content: newContent } )
	}
	const onChangeAlign = ( newAlign ) => {
		setAttributes( { 
			align: newAlign === undefined ? 'none' : newAlign, 
		} )
	}
	return (
		<>
			<InspectorControls>
				<PanelColorSettings 
					title={ __( 'Color settings', 'ka-example-block' ) }
					initialOpen={ false }
					colorSettings={ [
						{
						  value: textColor,
						  onChange: onChangeTextColor,
						  label: __( 'Text color', 'ka-example-block' )
						},
						{
						  value: backgroundColor,
						  onChange: onChangeBackgroundColor,
						  label: __( 'Background color', 'ka-example-block' )
						}
					] }
				/>
			</InspectorControls>
			<BlockControls>
				<AlignmentControl
					value={ align }
					onChange={ onChangeAlign }
				/>
			</BlockControls>
			<RichText 
				{ ...blockProps }
				tagName="p"
				onChange={ onChangeContent }
				allowedFormats={ [ 'core/bold', 'core/italic' ] }
				value={ content }
				placeholder={ __( 'Write your text...' ) }
				style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
			/>
		</>
	);
}

Notate che abbiamo anche aggiornato l’attributo style dell’elemento RichText:

<RichText 
	 { ...blockProps }
	 tagName="p"
	 onChange={ onChangeContent }
	 allowedFormats={ [ 'core/bold', 'core/italic' ] }
	 value={ content }
	 placeholder={ __( 'Write your text...' ) }
	 style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
/>

Passo 3: Definizione degli Attributi Necessari in block.json

Ora definite gli attributi backgroundColor e textColor nel file block.json:

"attributes": {
	"content": {
		"type": "string",
		"source": "html",
		"selector": "p"
	},
	"align": {
		"type": "string",
		"default": "none"
	},
	"backgroundColor": {
		"type": "string"
	},	 
	"textColor": {
		"type": "string"
	}
},

Passo 4: Definizione degli Event Handler

Ora è necessario definire due funzioni che aggiornino backgroundColor e textColor su input dell’utente:

const onChangeBackgroundColor = ( newBackgroundColor ) => {
	setAttributes( { backgroundColor: newBackgroundColor } )
}

const onChangeTextColor = ( newTextColor ) => {
	setAttributes( { textColor: newTextColor } )
}

Passo 5: Salvataggio dei Dati

Un ultimo passaggio: aprite il file save.js e cambiate lo script come segue:

export default function save( { attributes } ) {
	const blockProps = useBlockProps.save();
	const { content, align, backgroundColor, textColor } = attributes;
	return (
		<RichText.Content 
			{ ...blockProps } 
			tagName="p" 
			value={ content } 
			style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
		/>
	);
}

Salvate il file e controllate il blocco nell’editor. Dovreste trovarvi di fronte ad una sgradita sorpresa: un messaggio di errore che dice che il blocco contiene contenuti inattesi o non validi.

Il messaggio di errore Unexpected or invalid content.
Il messaggio di errore “Unexpected or invalid content”.

Questo avviene perché è cambiato il contenuto del file save.js e il codice salvato nel database non corrisponde a quello utilizzato nell’editor.

Per risolvere il problema, aggiornate la pagina, cancellate qualsiasi istanza del blocco e aggiungetelo nuovamente al post:

Il pannello delle impostazioni del colore nella barra delle impostazioni del blocco.
Il pannello delle impostazioni del colore nella barra delle impostazioni del blocco.

Fate le vostre modifiche, salvate il post e visualizzatelo sul front-end. A questo punto, le modifiche apportate nell’editor di blocchi dovrebbero riflettersi sulla pagina frontale.

Il blocco personalizzato ora funziona correttamente sul front-end.
Il blocco personalizzato ora funziona correttamente sul front-end.

In questa sezione aggiungeremo nuovi componenti al tipo di blocco:

  • Un componente ExternalLink che permette agli utenti di aggiungere un link personalizzabile al blocco
  • Diversi controlli della sidebar che permettono agli utenti di personalizzare le impostazioni dei link

Passo 1. Importazione dei Componenti da @wordpress/components

Ora avete bisogno di importare diversi componenti da @wordpress/components. Aprite il vostro file edit.js e aggiungete la seguente dichiarazione import:

import {
	TextControl,
	PanelBody,
	PanelRow,
	ToggleControl,
	ExternalLink
} from '@wordpress/components';
  • PanelBody aggiunge un container a scomparsa alla sidebar delle impostazioni.
  • PaneRow produce un container generico per i controlli della sidebar.
  • TextControl fornisce un input di testo.
  • ToggleControl fornisce un interruttore che permette agli utenti di abilitare/disabilitare una specifica opzione
  • ExternalLink è un semplice componente per aggiungere un link esterno.

Passo 2. Inserimento degli Elementi Corrispondenti nel Codice JSX

Aggiungerete prima l’elemento ExternalLink allo stesso livello di RichText in un container div:

<div { ...blockProps }>
	<RichText 
		...
	/>
	<ExternalLink 
		href={ kaLink }
		className="ka-button"
		rel={ hasLinkNofollow ? "nofollow" : "" }
	>
			{ linkLabel }
	</ExternalLink>

</div>

Il componente ExternalLink non è documentato, quindi abbiamo fatto riferimento al componente stesso per ottenere l’elenco degli attributi disponibili. Qui utilizziamo gli attributi href, className e rel.

Di default, il valore dell’attributo rel è impostato su noopener noreferrer. Il nostro codice aggiungerà la keyword nofollow all’attributo rel del tag a risultante, quando il controllo toggle è attivo.

Ora possiamo aggiungere le impostazioni dei link alla sidebar del blocco.

Per prima cosa, aggiungerete un elemento PanelBody dentro InspectorControls allo stesso livello di PanelColorSettings:

<InspectorControls>
	<PanelColorSettings 
	...
	/>
	<PanelBody 
		title={ __( 'Link Settings' )}
		initialOpen={true}
	>
	...
	</PanelBody>
</InspectorControls>

Ecco cosa stiamo facendo:

  1. L’attributo title fornisce il titolo del pannello.
  2. initialOpen stabilisce se il pannello è inizialmente aperto o meno.

Poi aggiungeremo due elementi PanelRow dentro PanelBody, e un elemento TextControl dentro ogni PanelRow:

<PanelBody 
	title={ __( 'Link Settings', 'ka-example-block' )}
	initialOpen={true}
>
	<PanelRow>
		<fieldset>
			<TextControl
				label={__( 'KA link', 'ka-example-block' )}
				value={ kaLink }
				onChange={ onChangeKaLink }
				help={ __( 'Add your Academy link', 'ka-example-block' )}
			/>
		</fieldset>
	</PanelRow>
	<PanelRow>
		<fieldset>
			<TextControl
				label={__( 'Link label', 'ka-example-block' )}
				value={ linkLabel }
				onChange={ onChangeLinkLabel }
				help={ __( 'Add link label', 'ka-example-block' )}
			/>
		</fieldset>
	</PanelRow>
</PanelBody>

Il codice sopra dovrebbe ora essere abbastanza comprensibile. I due controlli di testo permettono agli utenti di impostare l’etichetta del link e l’URL.

Aggiungeremo anche un ulteriore PanelRow con un ToggleControl per attivare/disattivare un’opzione specifica, come ad esempio se includere o meno un attributo:

<PanelRow>
	<fieldset>
		<ToggleControl
			label="Add rel = nofollow"
			help={
				hasLinkNofollow
					? 'Has rel nofollow.'
					: 'No rel nofollow.'
			}
			checked={ hasLinkNofollow }
			onChange={ toggleNofollow }
		/>
	</fieldset>
</PanelRow>

Passo 3: Definizione degli Attributi Necessari in block.json

Ora definiamo gli attributi kaLink, linkLabel e hasLinkNofollow nel file block.json:

"kaLink": {
	"type": "string",
	"default": ""
},
"linkLabel": {
	"type": "string",
	"default": "Check it out!"
},
"hasLinkNofollow": {
	"type": "boolean",
	"default": false
}

Non c’è altro da aggiungere qui! Passiamo alla definizione delle funzioni di gestione degli eventi.

Passo 4: Definizione degli Event Handler

Tornate al file edit.js e aggiungete le seguenti funzioni:

const { content, align, backgroundColor, textColor, kaLink, linkLabel, hasLinkNofollow } = attributes;

const onChangeKaLink = ( newKaLink ) => {
	setAttributes( { kaLink: newKaLink === undefined ? '' : newKaLink } )
}

const onChangeLinkLabel = ( newLinkLabel ) => {
	setAttributes( { linkLabel: newLinkLabel === undefined ? '' : newLinkLabel } )
}

const toggleNofollow = () => {
	setAttributes( { hasLinkNofollow: ! hasLinkNofollow } )
}

Queste funzioni aggiornano i valori degli attributi corrispondenti su input dell’utente.

Passo 5: Salvataggio dei Dati

Per ultimo, dobbiamo aggiornare la funzione save in save.js:

export default function save( { attributes } ) {
	
	const { content, align, backgroundColor, textColor, kaLink, linkLabel, hasLinkNofollow } = attributes;

	const blockProps = useBlockProps.save( {
		className: `has-text-align-${ align }`
	} );
	
	return (
		<div 
			{ ...blockProps }
			style={ { backgroundColor: backgroundColor } }
		>
			<RichText.Content 
				tagName="p" 
				value={ content } 
				style={ { color: textColor } }
			/>
			<p>
				<a 
					href={ kaLink }
					className="ka-button"
					rel={ hasLinkNofollow ? "nofollow" : "noopener noreferrer" }
				>
					{ linkLabel }
				</a>
			</p>
		</div>
	);
}

Si noti che qui abbiamo usato un normale elemento a invece di ExternalLink:

Il pannello delle impostazioni dei link nella barra delle impostazioni del blocco.
Il pannello delle impostazioni dei link nella barra delle impostazioni del blocco.

Aggiungere Stili di Blocco Multipli

In una sezione precedente, abbiamo mostrato come aggiungere un controllo alla toolbar di blocco che permette di allineare l’input dell’utente. Possiamo aggiungere altri controlli di stile alla barra degli strumenti dei blocchi, ma possiamo anche fornire un insieme di stili di blocco predefiniti che l’utente può selezionare con un solo clic.

A questo scopo, useremo un’utile funzionalità dell’API dei blocchi: gli Stili di blocco.

Tutto quello che dovete fare è definire la proprietà styles nel file block.json e dichiarare gli stili corrispondenti nei vostri fogli di stile.

Ad esempio, potete aggiungere il seguente array di stili:

"styles": [
	{
		"name": "default",
		"label": "Default",
		"isDefault": true
	},
	{
		"name": "border",
		"label": "Border"
	}
],

Con questo, avete appena aggiunto uno stile predefinito e uno stile aggiuntivo chiamato border. Ora tornate all’editor di blocchi:

Due stili di blocco predefiniti.
Due stili di blocco predefiniti.

Gli stili saranno disponibili all’utente cliccando sul block switcher e poi cercando il pannello Stili nella sidebar delle impostazioni del blocco.

Selezionate uno stile e controllate le classi applicate all’elemento p. Cliccate con il tasto destro del mouse sul blocco e poi Inspect. È stata aggiunta una nuova classe con un nome strutturato come segue:

is-style-{style-name}

Se avete selezionato lo stile “Border”, allora sarà aggiunta all’elemento p la classe is-style-border. Se avete selezionato lo stile “Default”, verrà invece aggiunta la classe is-style-default.

Ora dovete solo dichiarare le proprietà CSS. Aprite il file editor.scss e sostituite gli stili correnti con i seguenti:

.wp-block-ka-example-block-ka-example-block {
    padding: 4px;
}

Ora potete fare lo stesso in style.scss. Come abbiamo detto in precedenza, gli stili definiti in style.scss sono applicati sia sul front-end che nell’editor:

.wp-block-ka-example-block-ka-example-block {
	&.is-style-default{
		border: 0;
        background-color: #FFE2C7;
	}
	&.is-style-border{
		border: 2px solid #000;
        border-radius: 16px;
        background-color: #F6F6F6;
	}
}

E questo è tutto! Aggiornate la pagina e divertitevi con i vostri nuovi stili di blocco:

Stili di blocco a confronto.
Stili di blocco a confronto.

Annidare i Blocchi Gutenberg con il Componente InnerBlocks

Anche se già interamente funzionale, il nostro blocco non è ancora molto attraente. Per renderlo più accattivante per il pubblico, potremmo aggiungere un’immagine.

Questo potrebbe aggiungere un livello di complessità al nostro blocco, ma per fortuna non c’è bisogno di reinventare la ruota perché Gutenberg fornisce un componente specifico che è possibile utilizzare per creare una struttura di blocchi annidati.

Il componente InnerBlocks è definito come segue:

InnerBlocks esporta una coppia di componenti che possono essere utilizzati nelle implementazioni dei blocchi per abilitare il contenuto dei blocchi annidati.

Per prima cosa, è necessario creare un nuovo file .js nella cartella src. Nel nostro esempio, chiameremo questo file container.js.

Ora è necessario importare la nuova risorsa nel file index.js:

import './container';

Go back to container.js and import the necessary components:

import { registerBlockType } from "@wordpress/blocks";
import { __ } from "@wordpress/i18n";
import {
	useBlockProps, 
	InnerBlocks 
} from "@wordpress/block-editor";

Il passo successivo è la definizione di un template che fornisce la struttura all’interno della quale saranno collocati i blocchi. Nell’esempio che segue, definiamo un template composto da due colonne che contengono un blocco principale Immagine e il nostro blocco personalizzato:

const TEMPLATE = [ [ 'core/columns', { backgroundColor: 'yellow', verticalAlignment: 'center' }, [
	[ 'core/column', { templateLock: 'all' }, [
		[ 'core/image' ],
	] ],
	[ 'core/column', { templateLock: 'all' }, [
		[ 'ka-example-block/ka-example-block', { placeholder: 'Enter side content...' } ],
	] ],
] ] ];

Il template è strutturato come un array di blockTypes (nome del blocco e attributi opzionali).

Nel codice qui sopra, abbiamo utilizzato diversi attributi per configurare i blocchi Columns e Column. In particolare, l’attributo templateLock: 'all' blocca i blocchi Column in modo che l’utente non possa aggiungere, riordinare o cancellare i blocchi esistenti. templateLock può assumere uno dei seguenti valori:

  • allInnerBlocks è bloccato, e nessun blocco può essere aggiunto, riordinato o rimosso.
  • insert — I blocchi possono essere solo riordinati o rimossi.
  • false — Il template non è bloccato.

Il template viene poi assegnato all’elemento InnerBlocks:

<InnerBlocks
	template={ TEMPLATE }
	templateLock="all"
/>

Per evitare qualsiasi problema di compatibilità, abbiamo anche aggiunto un attributo templateLock al componente InnerBlocks (si veda anche la issue #17262 e il pull #26128).

Ecco il nostro file container.js finale:

registerBlockType('ka-example-block/ka-example-container-block', {
	title: __( 'KA Container block', 'ka-example-block' ),
	category: 'design',

	edit( { className } ) {
		
		return(
			<div className={ className }>
				<InnerBlocks
					template={ TEMPLATE }
					templateLock="all"
				/>
			</div>
		)
	},

	save() {
		const blockProps = useBlockProps.save();
		return(
			<div { ...blockProps }>
				<InnerBlocks.Content />
			</div>
		)
	},
});
Il blocco finale nell'editor di blocchi.
Il blocco finale nell’editor di blocchi.

Altri Miglioramenti

Il nostro blocco è completo, ma potremmo migliorarlo un po’ con alcune piccole modifiche.

Abbiamo assegnato l’attributo backgroundColor al paragrafo generato dal componente RichText. Tuttavia, potremmo preferire assegnare il colore di sfondo alla div contenitore:

Quindi modificate le div dei file edit.js e save.js come segue:

<div 
	{ ...blockProps }
	style={ { backgroundColor: backgroundColor } }
>
...
</div>

Questo permetterà all’utente di cambiare lo sfondo dell’intero blocco.

Una modifica più rilevante riguarda il metodo useBlockProps. Nel codice iniziale, abbiamo definito la costante blockProps come segue:

const blockProps = useBlockProps();

Ma possiamo usare useBlockProps in modo più efficiente passando un insieme di proprietà. Ad esempio, possiamo importare classnames dal modulo classnames e impostare il nome della classe wrapper di conseguenza.

Nell’esempio che segue, assegniamo un nome di classe basato sul valore dell’attributo align (edit.js):

import classnames from 'classnames';

...

export default function Edit( { attributes, setAttributes } ) {
	...
	
	const onChangeAlign = ( newAlign ) => {
		setAttributes( { 
			align: newAlign === undefined ? 'none' : newAlign, 
		} )
	}

	const blockProps = useBlockProps( {
		className: `has-text-align-${ align }`
	} );
	...
}

Faremo la stessa modifica nel file save.js:

import classnames from 'classnames';

...

export default function save( { attributes } ) {
	...
	const { content, align, backgroundColor, textColor, kaLink, linkLabel, hasLinkNofollow } = attributes;

	const blockProps = useBlockProps.save( {
		className: `has-text-align-${ align }`
	} );
	...
}

E questa è la conclusione! Ora è possibile eseguire la build per la produzione:

npm run build

Riepilogo

Ed eccoci qui, alla fine di questo incredibile viaggio! Abbiamo iniziato con la configurazione dell’ambiente di sviluppo e abbiamo finito per creare un tipo di blocco completo.

Come abbiamo detto nell’introduzione, una solida conoscenza di Node.js, Webpack, Babel e React è essenziale per creare blocchi Gutenberg avanzati e posizionarsi sul mercato come sviluppatori Gutenberg professionisti.

Ma non è necessario avere un’esperienza consolidata di React per iniziare a divertirsi con lo sviluppo dei blocchi. Sviluppare blocchi potrebbe darvi le motivazioni e gli obiettivi per acquisire competenze sempre più ampie nelle tecnologie che stanno dietro i blocchi di Gutenberg.

Questa guida, quindi, è ben lungi dall’essere completa. È semplicemente un’introduzione a un’ampia varietà di argomenti che vi aiuterà ad iniziare a costruire i vostri primi blocchi Gutenberg.

Per questo motivo, consigliamo di approfondire la conoscenza della materia leggendo attentamente la documentazione e le guide online. Tra le molte risorse disponibili in giro, raccomandiamo le seguenti:

Se avete appena iniziato a sviluppare su WordPress, potreste voler comprendere meglio i concetti di base dello sviluppo frontend. Ecco un breve elenco di risorse che possono aiutarvi ad iniziare:

E ricordate che il codice completo degli esempi di questa guida è disponibile su Gist.

Ora è il vostro turno: Avete sviluppato qualche blocco Gutenberg? Quali sono le principali difficoltà che avete incontrato finora? Descriveteci la vostra esperienza nei commenti!

Carlo Daniele Kinsta

Carlo è cultore appassionato di webdesign e front-end development. Gioca con WordPress da oltre 20 anni, anche in collaborazione con università ed enti educativi italiani ed europei. Su WordPress ha scritto centinaia di articoli e guide, pubblicati sia in siti web italiani e internazionali, che su riviste a stampa. Lo trovate su LinkedIn.