Mucha gente se queja de las dificultades para empezar a construir bloques y aplicaciones de Gutenberg. La curva de aprendizaje es empinada, principalmente debido a la dificultad de instalar y configurar el entorno de desarrollo. Además, un sólido conocimiento de JavaScript, Node.js, React y Redux son ingredientes imprescindibles para esta receta bastante compleja.

El manual oficial del editor de bloques de WordPress proporciona a los desarrolladores una enorme cantidad de información, pero puede que te encuentres perdido en ese mar de detalles.

Y vale la pena mencionar lo que Matías Ventura, arquitecto principal del proyecto Gutenberg, dijó en su entrevista en WP Tavern:

Aunque hay gente que puede aprenderlo rápidamente, sigue siendo una gran barrera para la gente. Creo que existen diversas claves; la documentación podría mejorar en gran medida, tanto en organización como en presentación. Espero que podamos hacer mucho más en este sentido.

Con esto en mente, hemos decidido crear un tutorial paso a paso destinado a ayudar a nuestros lectores a iniciarse en el desarrollo de bloques de Gutenberg.

¿Te parece interesante? Vamos a sumergirnos en el tema.

Requisitos previos para el desarrollo de bloques de Gutenberg

Para este tutorial, las únicas habilidades requeridas son un buen conocimiento del desarrollo de plugins de WordPress y al menos una comprensión básica de HTML, CSS, JavaScript y React.

¿Es un proyecto ambicioso? Por supuesto que sí.

No fue fácil encontrar el compromiso adecuado entre la exhaustividad y la sencillez, ni decidir qué temas incluir y cuáles dejar fuera.

Esperemos que los lectores intermedios y avanzados nos perdonen por no profundizar en ciertos conceptos como el estado de React, el almacén Redux, los high order components, etc. Estos temas requieren espacio y atención adicionales y son probablemente demasiado avanzados para el desarrollo de bloques principiante (a menos que seas un desarrollador de React).

Por la misma razón, no cubriremos algunos de los temas más avanzados relacionados con el desarrollo de bloques de Gutenberg, como los bloques dinámicos y los meta boxes.

Con los conocimientos que obtendrás al final de este artículo, podrás empezar a divertirte y ser productivo de inmediato.

Una vez que te pongas en marcha con la construcción de bloques, estarás preparado para mejorar tus habilidades y construir bloques Gutenberg aún más avanzados por tu cuenta.

 

¿Qué es un bloque Gutenberg?

Desde que se lanzó por primera vez en diciembre de 2018, el editor de bloques ha mejorado mucho en todos los aspectos: APIs más potentes, una interfaz de usuario más avanzada, una usabilidad mejorada, una tonelada de bloques nuevos, las primeras implementaciones de Full Site Editing y mucho más.

En resumen, aunque Gutenberg sigue en pleno desarrollo, ha recorrido un largo camino – y hoy, el editor de bloques es un candidato de pleno derecho como constructor de páginas y sitios fiables y funcionales.

Desde el punto de vista del desarrollador, Gutenberg es una single-page application (SPA) basada en React que permite a los usuarios de WordPress crear, editar y eliminar contenido en WordPress. Sin embargo, esto no debe hacer pensar en una versión mejorada del editor de contenidos tradicional.

Queremos dejar esto claro:

En Gutenberg, el contenido se divide en bloques, que son «ladrillos» que los usuarios pueden utilizar para crear entradas y páginas o sus sitios web completos.

Pero, ¿qué es técnicamente un bloque?

Nos gusta la definición de WordPress:

«Bloque» es el término abstracto utilizado para describir las unidades de marcado que, compuestas juntas, forman el contenido o el diseño de una página web. La idea combina conceptos de lo que en WordPress conseguimos hoy con los shortcodes, el HTML personalizado y el embed discovery en una única y consistente API y experiencia de usuario.

Los títulos, los párrafos, las columnas, las imágenes, las galerías y todos los elementos que componen la interfaz del editor, desde los paneles de la barra lateral hasta los controles de la barra de herramientas de los bloques, son componentes React.

Entonces, ¿qué son los componentes React? W3Schools ofrece la siguiente definición:

Los componentes son fragmentos de código independientes y reutilizables. Sirven para el mismo propósito que las funciones de JavaScript, pero funcionan de forma aislada y devuelven HTML a través de una función render().

Trabajar con bloques Gutenberg en WordPress 5.8.
Trabajar con bloques Gutenberg en WordPress 5.8.

Aunque la experiencia de edición que ofrece Gutenberg es nueva en comparación con el editor clásico de WordPress, la forma en que WordPress almacena sus piezas de contenido en la base de datos no cambia en absoluto. Esto se debe a que Gutenberg es una aplicación que funciona dentro de WordPress pero no cambia la forma en que el CMS funciona en su núcleo.

Las entradas (y esto incluye entradas, páginas y tipos de entradas personalizadas) creadas con Gutenberg siguen almacenándose en la tabla wp_posts, exactamente igual que con el editor clásico.

Pero en un post creado con Gutenberg, encontrarás trozos de información adicionales en la tabla que representan una diferencia fundamental entre los posts creados a través del Editor Clásico vs Gutenberg.

Estas piezas de información se parecen a los comentarios HTML, y tienen una función específica: delimitar bloques:

Una entrada del blog en la vista del editor de código.
Una entrada del blog en la vista del editor de código.

Los delimitadores de bloque le indican a WordPress qué bloque se va a mostrar en la pantalla. También proporcionan valores para las propiedades del bloque en un objeto JSON. Esas propiedades dictan la forma en que el bloque debe ser renderizado en la pantalla:

Una entrada de blog almacenada en la tabla wp_posts.
Una entrada de blog almacenada en la tabla wp_posts.

Configuración del entorno de desarrollo de WordPress

La configuración de un entorno de desarrollo JavaScript moderno requiere un sólido conocimiento de tecnologías avanzadas como Webpack, React y JSX, Babel, ESLint, etc.

¿Intimidado? No lo estés. La comunidad de WordPress ya ha acudido al rescate proporcionando potentes herramientas que te permiten evitar un engorroso proceso de configuración manual.

Para simplificar las cosas, no cubriremos la transpilación en este artículo (que, sin embargo, recomendamos que te familiarices con ella una vez que hayas aprendido los fundamentos del desarrollo en bloque). En su lugar, presentaremos dos herramientas alternativas que puedes utilizar para configurar rápida y fácilmente un entorno de desarrollo de JavaScript moderno en pocos minutos. Depende de ti elegir la que te resulte más conveniente para tu proyecto.

Configurar un entorno de desarrollo de JavaScript para construir bloques de Gutenberg es un proceso de tres pasos:

  1. Instalar Node.js y npm
  2. Configurar el entorno de desarrollo
  3. Configurar el plugin de bloques

Empecemos.

1. Instalar Node.js y npm

Antes de instalar tu entorno de desarrollo y registrar tu primer bloque, necesitarás instalar Node.js y el gestor de paquetes Node (npm).

Puedes instalar Node.js y npm de diferentes maneras. Pero primero, es posible que quieras comprobar si el software ya está instalado en tu máquina.

Para ello, inicia el terminal y ejecute el siguiente comando:

node -v

Si el resultado es command not found, entonces Node.js no está instalado en tu ordenador, y puedes proceder con la instalación.

Para este artículo, hemos elegido la opción de instalación más sencilla, que es el instalador de Node. Lo único que tienes que hacer es descargar la versión correspondiente a tu sistema operativo e iniciar el asistente de instalación:

Página de descargas de Node.js.
Página de descargas de Node.js.

Una vez que hayas instalado Node.js, ejecuta el comando node -v en tu terminal de nuevo. También puedes ejecutar el comando npm -v para confirmar que tienes el paquete.

Ahora estás equipado con las siguientes herramientas:

  • El corredor de paquetes npx Node.js (ver docs). Esto te permite ejecutar un comando npm sin instalarlo primero.
  • El gestor de paquetes npm Node.js (ver docs). Se utiliza para instalar dependencias y ejecutar scripts.

El siguiente paso es instalar el entorno de desarrollo.

2. Configurar el entorno de desarrollo

Una vez que tengas las últimas versiones de Node.js y npm en tu máquina local, necesitarás un entorno de desarrollo para WordPress.

Puedes utilizar un entorno de desarrollo local como DevKinsta o utilizar la herramienta oficial de WordPress. Vamos a echar un vistazo a ambas opciones.

Opción 1: Entorno de desarrollo local (DevKinsta)

Con solo unos pocos clics, puedes instalar WordPress localmente usando DevKinsta, nuestra moderna herramienta de desarrollo local de WordPress. O puedes optar por otra herramienta de desarrollo local, como MAMP o XAMPP:

Cree un nuevo sitio web de WordPress en DevKinsta.
Crea un nuevo sitio web de WordPress en DevKinsta.

Opción 2: wp-env

También puedes optar por la wp-envherramienta oficial, que proporciona un entorno de desarrollo local de WordPress que puedes lanzar directamente desde la línea de comandos. Noah Alen lo define así:

Los entornos locales de WordPress son ahora tan sencillos como ejecutar un único comando. wp-env es una herramienta de configuración cero para entornos locales de WordPress sin complicaciones. Proporciona decisiones sobre las opciones para que los usuarios puedan poner en marcha rápidamente WordPress sin perder tiempo. De hecho, el objetivo es hacer que estos entornos sean fácilmente accesibles para todos, ya seas un desarrollador, un diseñador, un gestor o cualquier otra persona.

Si decides probarlo, la instalación de wp-env requiere un esfuerzo mínimo. Solo tienes que seguir estos pasos:

Paso 1: Confirmar la instalación de Docker y Node.js

Para cumplir con los requisitos técnicos, primero tendrás que tener Docker y Node.js instalados en tu ordenador. Esto se debe a que wp-env crea una instancia Docker que ejecuta un sitio web de WordPress. Cualquier cambio realizado en el código se refleja inmediatamente en la instancia de WordPress.

 Paso 2: Instalar @wordpress/env desde la línea de comandos

Con Docker y Node.js funcionando en tu ordenador, puedes pasar a instalar el entorno de desarrollo de WordPress.

Puede instalar wp-env de forma global o local. Para hacerlo de forma global, tendrás que ejecutar el siguiente comando desde el directorio de plugins (más información sobre esto en el cuadro de aviso «Importante» más abajo):

npm install -g @wordpress/env

Vamos a desglosar eso:

Para confirmar que wp-env se ha instalado correctamente, ejecuta el siguiente comando:

wp-env --version

Deberías ver la versión actual de wp-env, lo que significa que ahora puedes lanzar el entorno utilizando el siguiente comando desde la carpeta de su plugin:

wp-env start

Puedes acceder al panel de control de WordPress utilizando la siguiente dirección:

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

Las credenciales por defecto son las siguientes:

  • Nombre de usuario: admin
  • Contraseña: password

Configurar el plugin de bloqueo

Ahora necesitas un plugin de bloques de inicio sobre el que construir. Pero en lugar de crear manualmente un plugin de desarrollo de bloques con todos los archivos y carpetas necesarios, puedes simplemente ejecutar una herramienta de desarrollo que te proporcione todos los archivos y configuraciones que necesitas para empezar a desarrollar bloques.

De nuevo, tienes un par de opciones para elegir. Veamos cada una de ellas.

Opción 1: Configurar un plugin de bloque con @wordpress/create-block

@wordpress/create-block es la herramienta oficial de configuración cero para crear bloques Gutenberg:

Create Block es una forma oficial de crear bloques para registrar un bloque para un plugin de WordPress. Ofrece una configuración de construcción moderna sin configuración. Genera código PHP, JS, CSS y todo lo que necesitas para iniciar el proyecto.

Se inspira en gran medida en create-react-app. Un gran reconocimiento a @gaearon, a todo el equipo de Facebook y a la comunidad React.

Una vez que tu entorno local esté en funcionamiento, puedes configurar un bloque inicial simplemente ejecutando el comando npx @wordpress/create-block, y te proporcionará todos los archivos y carpetas que necesita para crear el andamiaje del plugin y registrar un nuevo bloque.

Hagamos una prueba para ver cómo funciona.

Desde tu herramienta de línea de comandos, navega hasta el directorio /wp-content/plugins/ y ejecuta el siguiente comando:

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

Cuando te le pida que confirma, introduce y para continuar:

Creación de un bloque con @wordpress/create-block.
Creación de un bloque con @wordpress/create-block.

El proceso dura unos instantes. Cuando se haya completado, deberías obtener la siguiente respuesta:

Se ha creado el plugin de bloques.
Se ha creado el plugin de bloques.

¡Y ya está!

Ahora inicia tu entorno de desarrollo de WordPress y dirígete a la pantalla de plugins en el panel de control de WordPress. Un nuevo plugin llamado «My First Block» debería haber sido añadido a tu lista de plugins:

El plugin del bloque se ha instalado con éxito.
El plugin del bloque se ha instalado con éxito.

Activa el plugin si es necesario, crea una nueva entrada de blog, desplázate por el insertador de bloques hasta la sección de Widgets y selecciona tu nuevo bloque:

Un ejemplo de bloque creado con @wordpress/create-block.
Un ejemplo de bloque creado con @wordpress/create-block.

Ahora vuelve al terminal y cambia el directorio actual a mi-primer-bloque:

cd my-first-block

A continuación, ejecuta el siguiente comando:

npm start

Esto te permite ejecutar el plugin en modo de desarrollo. Para crear el código de producción, debes utilizar el siguiente comando:

npm run build

Opción 2: Configurar un plugin de bloque con create-guten-block

create-guten-block es una herramienta de desarrollo de terceros para construir bloques Gutenberg:

create-guten-block es un dev-toolkit de configuración cero (#0CJS) para desarrollar bloques de WordPress Gutenberg en cuestión de minutos sin configurar React, webpack, ES6/7/8/Next, ESLint, Babel, etc.

Al igual que la herramienta oficial de create-block, create-guten-block se basa en create-react-app y puede ayudarte a generar tu primer plugin de bloques sin problemas.

El kit de herramientas proporciona todo lo necesario para crear un moderno plugin de WordPress, incluyendo lo siguiente:

 

  • Soporte de sintaxis React, JSX y ES6.
  • proceso de construcción de webpack para desarrollo/producción detrás de la escena.
  • Extras del lenguaje más allá de ES6 como el operador de propagación de objetos.
  • CSS autoprefijado, por lo que no se necesita -webkit u otros prefijos.
  • Un script de construcción para empaquetar JS, CSS e imágenes para la producción con mapas de origen.
  • Actualizaciones sin problemas para las herramientas anteriores con una sola dependencia cgb-scripts.

 

Ten en cuenta la siguiente advertencia:

La contrapartida es que estas herramientas están preconfiguradas para funcionar de una manera específica. Si tu proyecto necesita más personalización, puedes «expulsar» y personalizarlo, pero entonces tendrás que mantener esta configuración.

Una vez que tengas a mano un sitio web local de WordPress, inicie tu herramienta de línea de comandos, navega hasta la carpeta /wp-content/plugins de su instalación y ejecuta el siguiente comando:

npx create-guten-block my-first-block

Tendrás que esperar uno o dos minutos mientras se crea la estructura del proyecto y se descargan las dependencias:

 Creación de un bloque Gutenberg con create-guten-block.
Creación de un bloque Gutenberg con create-guten-block.

Cuando el proceso se haya completado, deberías ver la siguiente pantalla:

Bloque Gutenberg creado con éxito con create-guten-block.
Bloque Gutenberg creado con éxito con create-guten-block.

La siguiente imagen muestra la estructura del proyecto con el terminal ejecutado en Visual Studio Code:

El plugin de bloques en Visual Studio Code.
El plugin de bloques en Visual Studio Code.

Ahora vuelve a tu panel de control de WordPress. Debería aparecer un nuevo elemento en la pantalla de plugins: es el plugin my-first-block:

La pantalla de Plugins con un nuevo plugin creado con create-guten-block.
La pantalla de Plugins con un nuevo plugin creado con create-guten-block.

Activa el plugin y vuelve a la terminal. Cambia el directorio actual a mi-primer-bloque, luego ejecuta npm start:

cd my-first-block
npm start

Deberías obtener la siguiente respuesta:

npm comenzó.
npm comenzó.

De nuevo, esto te permite ejecutar el plugin en modo de desarrollo. Para crear el código de producción, debes utilizar:

npm run build

Activa el plugin y crea un nuevo post o página, luego explora tus bloques y selecciona tu flamante bloque Gutenberg:

Un nuevo bloque creado con create-guten-block.
Un nuevo bloque creado con create-guten-block.

Para una visión más profunda o en caso de errores, consulta la documentación proporcionada por Ahmad Awais.

Un recorrido por el andamiaje del bloque inicial

Cualquiera de las dos herramientas de desarrollo create-block o create-guten-block que elijas, ahora tendrás un andamiaje de bloques que puedes usar como punto de partida para construir un plugin de bloques.

Pero, ¿qué es exactamente un andamio de bloques?

El andamio de bloques es un término abreviado que describe la estructura de directorios de soporte que necesita WordPress para reconocer un bloque. Normalmente ese directorio incluye archivos como index.php, index.js, style.css y otros, que a su vez contienen llamadas como register_block_type.

Hemos optado por la herramienta oficial de creación de bloques, ya que se utiliza en el manual del editor de bloques. Pero incluso si te decides por una herramienta de terceros como create-guten-block, tu experiencia no será muy diferente.

Dicho esto, vamos a profundizar en la create-block herramienta.

Una mirada más cercana a la herramienta de creación de bloques

Como hemos mencionado anteriormente, Create Block es la herramienta oficial de línea de comandos para crear bloques de Gutenberg. Ejecutar @wordpress/create-block en tu terminal genera los archivos PHP, JS y SCSS y el código necesario para registrar un nuevo tipo de bloque:

npx @wordpress/create-block [options] [slug]
  • [slug] (opcional) – se utiliza para asignar el slug del bloque e instalar el plugin
  • [options] (opcional) – opciones disponibles

Por defecto, se asigna una plantilla ESNext. Esto significa que obtendrás la siguiente versión de JavaScript, con la adición de la sintaxis JSX.

Si omites el nombre del bloque, el comando se ejecuta en modo interactivo, lo que te permite personalizar varias opciones antes de generar los archivos:

npx @wordpress/create-block
Ejecutando Crear Bloque en modo interactivo
Ejecutando Crear Bloque en modo interactivo

La imagen siguiente muestra la estructura de archivos de un plugin de bloque creado con la herramienta oficial Create Block:

Archivos y carpetas de un plugin de bloque creado con @wordpress/create-block.
Archivos y carpetas de un plugin de bloque creado con @wordpress/create-block.

Dicho esto, vamos a repasar los principales archivos y carpetas de nuestro nuevo plugin de bloques.

El archivo del plugin

Con el archivo principal del plugin se registra el bloque en el servidor:

<?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 función register_block_type registra un tipo de bloque en el servidor utilizando los metadatos almacenados en el archivo block.json.

La función toma dos parámetros:

  • El nombre del tipo de bloque incluyendo el espacio de nombres, o una ruta a la carpeta donde se encuentra el archivo block.json, o un objeto WP_Block_Type completo
  • Una matriz de argumentos de tipo de bloque

En el código anterior, la constante mágica __DIR__ devuelve la carpeta actual. Eso significa que el archivo block.json reside en la subcarpeta /build.

El archivo package.json

El archivo package.json define las propiedades y scripts de JavaScript para tu proyecto. Aquí es donde puedes instalar las dependencias de tu proyecto.

Para entender mejor para qué sirve este archivo, ábrelo con tu editor de código favorito:

{
	"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 propiedad scripts es un diccionario que contiene comandos que se ejecutan en varios momentos del ciclo de vida de un paquete utilizando npm run [cmd].

En este artículo vamos a utilizar los siguientes comandos:

  • npm run build — crea una compilación de producción (comprimida)
  • npm run start o npm start — crea una compilación de desarrollo (sin comprimir)

Las dependencies y las devDependencies son dos objetos que asignan un nombre de paquete a una versión. Las dependencies son necesarias en producción, mientras que las devDependences solo son necesarias para el desarrollo local (leer más).

La única dependencia de desarrollo por defecto es el paquete @wordpress/scripts que se define como «una colección de scripts reutilizables adaptados al desarrollo de WordPress».

El archivo block.json

A partir de WordPress 5.8, el archivo de metadatos block.json es la forma canónica de registrar los tipos de bloque.

Tener un archivo block.json proporciona varios beneficios, incluyendo un mejor rendimiento y una mejor visibilidad en el directorio de plugins de WordPress:

Desde el punto de vista del rendimiento, cuando los temas admiten activos de carga lenta, los bloques registrados con block.json tendrán una cola de espera de activos optimizada de forma inmediata. Los activos CSS y JavaScript del frontend que aparecen en las propiedades de style o de script solo se pondrán en cola cuando el bloque esté presente en la página, lo que reducirá el tamaño de la misma.

La ejecución del comando @wordpress/create-block genera el siguiente archivo 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"
}

Aquí está la lista completa de propiedades por defecto:

  • apiVersion —la versión de la API utilizada por el bloque (la versión actual es la 2)
  • name — un identificador único para un bloque que incluye un espacio de nombres
  • version – la versión actual de un bloque
  • title – un título para mostrar un bloque
  • category —una categoría de bloque
  • icon – un slug de Dashicon o un icono SVG personalizado
  • description – una breve descripción visible en el inspector de bloques
  • supports – un conjunto de opciones para controlar las características utilizadas en el editor
  • textdomain – el plugin text-domain
  • editorScript — definición de script del editor
  • editorStyle — definición del estilo del editor
  • style — proporciona estilos alternativos para un bloque

Además de las propiedades enumeradas anteriormente, puedes (y probablemente lo harás) definir un objeto de attributes que proporcione información sobre los datos almacenados por tu bloque. En tu block.json puedes establecer cualquier número de atributos en pares clave/valor, donde la clave es el nombre del atributo y el valor es la definición del mismo.

Observa el siguiente ejemplo de definición de atributos:

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

Más adelante profundizaremos en el archivo block.json, pero también puedes consultar el Manual del Editor de Bloques para obtener información más detallada sobre los metadatos y atributos de block.json.

La carpeta src

La carpeta src es donde ocurre el desarrollo. En esa carpeta, encontrarás los siguientes archivos:

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

index.js

El archivo index.js es tu punto de partida. Aquí importarás las dependencias y registrarás el tipo de bloque en el servidor:

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 primera sentencia importa la función registerBlockType del paquete @wordpress/blocks. Las siguientes declaraciones de importación importan la hoja de estilos junto con las funciones Edit y save, y un objeto de metadatos del archivo block.json.

La función registerBlockType registra el componente en el cliente. La función toma dos parámetros: un nombre de bloque y un objeto de configuración de bloque.

La función Edit proporciona la interfaz del bloque tal y como se muestra en el editor de bloques, mientras que la función save proporciona la estructura que se serializará y guardará en la base de datos (leer más).

edit.js

edit.js es donde construirás la interfaz de administración del bloque:

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>
	);
}

En primer lugar, importa la función __ del paquete @wordpress/i18n (este paquete contiene una versión JavaScript de las funciones de traducción), el hook useBlockProps React y el archivo editor.scss.

A continuación, exporta el componente React (lee más sobre las declaraciones de importación y exportación).

save.js

El archivo save.js es donde construimos la estructura de bloques que se guardará en la base de datos:

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 y style.scss

Además de los scripts, en las carpetas src residen dos archivos SASS. El archivo editor.scss contiene los estilos aplicados al bloque en el contexto del editor, mientras que el archivo style.scss contiene los estilos del bloque para su visualización en el frontend así como en el editor. Profundizaremos en estos archivos en la segunda parte de esta guía.

Las carpetas node_modules y build

La carpeta node_modules contiene los módulos de node y sus dependencias. No vamos a profundizar en los paquetes de node ya que está fuera del alcance de este artículo, pero puedes leer más en este artículo sobre dónde instala npm los paquetes.

La carpeta de build contiene los archivos JS y CSS resultantes del proceso de construcción. Puedes profundizar en el proceso de compilación en las guías de sintaxis de ESNext y de configuración de la compilación de JavaScript.

El proyecto: Construir tu primer bloque Gutenberg

Es hora de ensuciarse las manos. Esta sección te enseñará cómo crear un plugin que proporcione un bloque de CTA llamado Kinsta Academy Block.

El bloque constará de dos columnas, con una imagen a la izquierda y un párrafo de texto a la derecha. Debajo del texto se colocará un botón con un enlace personalizable:

El tipo de bloque que aprenderás a construir en esta guía.
El tipo de bloque que aprenderás a construir en esta guía.

Este es solo un ejemplo sencillo, pero nos permite cubrir los fundamentos del desarrollo de bloques Gutenberg. Una vez que tengas claro lo básico, puedes seguir adelante y crear bloques de Gutenberg más y más complejos con la ayuda del Manual del Editor de Bloques y cualquier otro de los vastos recursos disponibles por ahí.

Asumiendo que tienes la última versión de WordPress corriendo en tu entorno de desarrollo local, esto es lo que vas a aprender de aquí en adelante:

Preparados… listos… ¡ya!

Cómo configurar el plugin Starter Block

Inicia tu herramienta de línea de comandos y navega hasta la carpeta /wp-content/plugins:

Nuevo terminal en la carpeta en Mac OS.
Nuevo terminal en la carpeta en Mac OS.

Ahora, ejecuta el siguiente comando:

npx @wordpress/create-block

Este comando genera los archivos PHP, SCSS y JS para registrar un bloque en modo interactivo, permitiéndole añadir los datos necesarios para su bloque fácilmente. Para nuestro ejemplo utilizaremos los siguientes datos:

  • Variante de la Plantilla: static
  • Slug del bloque: ka-example-block
  • Nombre del espacio interno: ka-example-block
  • Título de visualización del bloque: Kinsta Academy Block
  • Descripción breve del bloque: Un bloque de ejemplo para los estudiantes de la Academia Kinsta
  • Dashicon: superhero-alt
  • Nombre de la categoría: widgets
  • ¿Quieres personalizar el plugin de WordPress?: sí
  • La página de inicio del plugin: https://kinsta.com/
  • Versión actual del plugin: 0.1.0
  • Autor del plugin: tu nombre
  • Licencia: –
  • Enlace al texto de la licencia: –
  • Ruta de dominio personalizada para las traducciones: –

La instalación del plugin y de todas las dependencias lleva un par de minutos. Cuando el proceso se complete, verás la siguiente respuesta:

El bloque de afiliados ha sido instalado y registrado para su desarrollo.
El bloque de afiliados ha sido instalado y registrado para su desarrollo.

Ahora, ejecuta el siguiente comando desde la carpeta /wp-content/plugins:

cd ka-example-block
Ejecución de comandos desde el terminal de código de Visual Studio.
Ejecución de comandos desde el terminal de código de Visual Studio.

Finalmente, desde la carpeta de tu plugin (ka-example-block en nuestro ejemplo), puedes comenzar el desarrollo con:

npm start

Ahora abre la pantalla de plugins para encontrar y activar el plugin Kinsta Academy Block:

Activar el bloque de ejemplo
Activar el bloque de ejemplo

Crea una nueva publicación, abre el insertador de bloques y desplázate hasta la categoría de Diseño. Haz clic para añadir el bloque de la Academia Kinsta:

Un bloque inicial construido con @wordpress/create-block.
Un bloque inicial construido con @wordpress/create-block.

block.json a trabajar

Como mencionamos anteriormente, el registro del bloque del lado del servidor tiene lugar en el archivo principal .php. Sin embargo, no vamos a definir la configuración en el archivo .php. En su lugar, utilizaremos el archivo block.json.

Por lo tanto, abre de nuevo block.json y echa un vistazo a la configuración por defecto:

{
	"$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"
}

Guiones y estilos

Las propiedades editorScript, editorStyle, y style proporcionan las rutas relativas a los scripts y estilos del frontend y del backend.

No tienes que registrar manualmente los scripts y estilos definidos aquí porque éstos son registrados y puestos en cola automáticamente por WordPress. Para comprobarlo, inicia el inspector del navegador y abra la pestaña Red:

Inspección de recursos en Chrome DevTools.
Inspección de recursos en Chrome DevTools.

Como puedes ver en la imagen de arriba, nuestro script index.js que reside en la carpeta de construcción se ha puesto en cola regularmente sin tener que añadir ningún código PHP.

Etiquetas UI

Las propiedades title y description proporcionan las etiquetas necesarias para identificar el bloque en el editor:

Nombre del bloque y descripción en la barra lateral del bloque.
Nombre del bloque y descripción en la barra lateral del bloque.

Palabras clave

Como hemos mencionado anteriormente, puedes configurar con precisión los ajustes de los bloques mediante propiedades y atributos. Por ejemplo, puedes añadir una o más keywords para ayudar a los usuarios a buscar bloques:

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

Si ahora introduces «kinsta», «academy» o «superhero» en el insertador rápido, el editor te sugerirá el bloque de la Academia Kinsta:

Búsqueda de un bloque mediante una palabra clave en el insertador rápido.
Búsqueda de un bloque mediante una palabra clave en el insertador rápido.

Localización

Si te preguntas cómo se produce la localización de las cadenas en el archivo JSON, aquí tienes la respuesta:

En JavaScript, puede utilizar el método registerBlockTypeFromMetadata del paquete @wordpress/blocks para registrar un tipo de bloque utilizando los metadatos cargados desde el archivo block.json. Todas las propiedades localizadas se envuelven automáticamente en llamadas a la función _x(del paquete @wordpress/i18n), de forma similar a como funciona en PHP con register_block_type_from_metadata. El único requisito es establecer la propiedad textdomainen el archivo block.json.

Aquí estamos utilizando la función registerBlockType en lugar de registerBlockTypeFromMetadata, ya que esta última ha quedado obsoleta desde Gutenberg 10.7, pero el mecanismo es el mismo.

Uso de los componentes incorporados: El componente RichText

Los elementos que conforman un bloque de Gutenberg son componentes de React, y puedes acceder a estos componentes a través de la variable global wp. Por ejemplo, intenta escribir wp.editor en la consola de tu navegador. Esto te dará la lista completa de los componentes incluidos en el módulo wp.editor.

Desplázate por la lista y adivina para qué sirven los componentes por sus nombres.

Del mismo modo, puede comprobar la lista de componentes incluidos en el módulo wp.components:

Componentes de WP Editor.
Componentes de WP Editor.

Ahora vuelve al archivo edit.js y echa un vistazo al 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>
	);
}

Este código genera un bloque estático con un texto simple y no editable. Pero podemos cambiar las cosas fácilmente:

El bloque de inicio en el editor de código.
El bloque de inicio en el editor de código.

Para hacer que el texto sea editable tendrás que sustituir la etiqueta <p> actual por un componente que haga que el contenido de entrada sea editable. Para ello, Gutenberg proporciona el componente integrado RichText.

Añadir un componente incorporado a tu bloque es un proceso de 5 pasos:

  1. Importar los componentes necesarios de un paquete de WordPress
  2. Incluir los elementos correspondientes en tu código JSX
  3. Definir los atributos necesarios en el archivo block.json
  4. Definir los manejadores de eventos
  5. Guardar datos

Paso 1: Importar los componentes necesarios de un paquete de WordPress

Ahora abre el archivo edit.js y cambia la siguiente declaración de import:

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

…a:

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

De esta manera, estás importando la función useBlockProps y el componente RichText del paquete @wordpress/block-editor.

useBlockProps

El hook useBlockProps de React marca el elemento envolvente del bloque:

Cuando se utiliza la versión 2 de la API, se debe utilizar el nuevo gancho useBlockProps en la función de edit para marcar el elemento envolvente del bloque. El gancho insertará los atributos y manejadores de eventos necesarios para habilitar el comportamiento del bloque. Cualquier atributo que desee pasar al elemento del bloque debe pasarse a través de useBlockProps y el valor devuelto debe extenderse al elemento.

Para simplificar, useBlockProps asigna automáticamente atributos y clases al elemento envolvente (el elemento p en nuestro ejemplo):

Elementos y clases generados por useBlockProps.
Elementos y clases generados por useBlockProps.

Si se elimina useBlockProps del elemento envolvente, se tendría una simple cadena de texto sin acceso a la funcionalidad y el estilo del bloque:

El mismo bloque sin useBlockProps.
El mismo bloque sin useBlockProps.

Como explicaremos más adelante, también puedes pasar useBlockProps un objeto de propiedades para personalizar la salida.

RichText

El componente RichText proporciona una entrada con contenido editable, permitiendo a los usuarios editar y formatear el contenido.

Encontrarás el componente documentado en GitHub en gutenberg/packages/block-editor/src/components/rich-text/README.md.

Paso 2: Incluir los elementos correspondientes en tu código JSX

...

const blockProps = useBlockProps();

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

Comentemos el código línea por línea:

  • tagName — función llamada cuando el contenido del elemento cambia
  • onChange — función llamada cuando el contenido del elemento cambia
  • allowedFormats — una matriz de formatos permitidos. Por defecto, se permiten todos los formatos
  • value — la cadena HTML para hacerla editable
  • placeholder — texto que se mostrará cuando el elemento esté vacío

Paso 3: Definir los atributos necesarios en el archivo block.json

Los atributos proporcionan información sobre los datos almacenados por un bloque, como el contenido enriquecido, el color de fondo, las URL, etc.

Puede establecer un número arbitrario de atributos dentro de un objeto de attributes en pares clave/valor, donde la clave es el nombre del atributo y el valor es la definición del atributo.

Ahora abre el archivo block.json y añade los siguientes attributes prop:

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

El atributo de content permite almacenar el texto escrito por el usuario en el campo editable:

  • type indica el tipo de datos almacenados por el atributo. El tipo es obligatorio a menos que se defina una propiedad enum.
  • source define cómo se extrae el valor del atributo del contenido de la entrada. En nuestro ejemplo, es el contenido HTML. Ten en cuenta que si no proporciona una propiedad de fuente, los datos se almacenan en el delimitador de bloque (leer más).
  • selector es una etiqueta HTML o cualquier otro selector, como un nombre de clase o un atributo id.

Pasaremos a la función Edit un objeto de propiedades. Así que, vuelve al archivo edit.js y haz el siguiente cambio:

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

Paso 4: Definir los manejadores de eventos

El elemento RichText tiene un atributo onChange, que proporciona una función para llamar cuando el contenido del elemento cambia.

Definamos esa función y veamos todo el 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...' ) }
		/>
	);
}

Ahora guarda el archivo y vuelve a tu panel de control de WordPress, crea una nueva entrada o página y añade tu bloque personalizado:

La salida del componente RichText en el Editor de bloques.
La salida del componente RichText en el Editor de bloques.

Añade algo de texto y cambia a la vista de código. Este es el aspecto que debería tener su código:

<!-- 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 -->

Como puedes ver, si cambias al Editor de Código, el contenido de tu bloque ha cambiado. Eso es porque tienes que modificar el archivo save.js para almacenar la entrada del usuario en la base de datos cuando se guarda la entrada.

Paso 5: Guardar los datos

Ahora abre el archivo save.js y cambia el script como sigue:

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 } 
		/>
	);
}

Eso es lo que estamos haciendo aquí:

  • Importa el componente RichText paquete block-editor.
  • Pasa varias propiedades a través de un argumento de objeto a la función de save (en este ejemplo, solo estamos pasando la attributes propiedad)
  • Devuelve el contenido del componente RichText
El contenido del bloque se ha guardado en la base de datos
El contenido del bloque se ha guardado en la base de datos

Puedes leer más sobre el componente RichText en el Manual del Editor de Bloques y encontrar la lista completa de accesorios en Github

Ahora vamos a dar un paso más. En la siguiente sección, aprenderás a añadir controles a la barra de herramientas del bloque.

Añadir controles a la barra de herramientas del bloque

La barra de herramientas del bloque contiene un conjunto de controles que permiten a los usuarios manipular partes del contenido del bloque. Para cada control de la barra de herramientas, encontrará un componente:

La barra de herramientas del bloque de párrafo principal.
La barra de herramientas del bloque de párrafo principal.

Por ejemplo, puedes añadir un control de alineación de texto para tu bloque. Todo lo que necesitas hacer es importar dos componentes del paquete @wordpress/block-editor.

Seguiremos los mismos pasos que en el ejemplo anterior:

  1. Importar los componentes necesarios de los paquetes de WordPress
  2. Incluir los elementos correspondientes en tu código JSX
  3. Definir los atributos necesarios en el archivo block.json
  4. Definir manejadores de eventos
  5. Guardar datos

Paso 1: Importar los componentes BlockControls y AlignmentControl de @wordpress/block-editor

Para añadir un control de alineación a la barra de herramientas del bloque, necesitas dos componentes:

  • BlockControls muestra una barra de herramientas dinámica de controles (no documentada).
  • AlignmentControl presenta un menú desplegable que muestra las opciones de alineación del bloque seleccionado (más información)

Abre el archivo edit.js y edite la declaración de import como se muestra a continuación:

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

Paso 2: Añadir elementos BlockControls y AlignmentControl

Dirígete a la función Edit e inserta el elemento <BlockControls />; al mismo nivel que <RichText />;. A continuación, añade y <AlignmentControl />; dentro de <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 } }
			/>
		</>
	);
}

En el código anterior, <> y </> son la sintaxis corta para declarar fragmentos de React, que es como devolvemos múltiples elementos en React.

En este ejemplo, AlignmentControl tiene dos atributos:

  • value proporciona el valor actual del elemento
  • onChange proporciona un controlador de eventos que se ejecuta cuando el valor cambia

También hemos definido atributos adicionales para el elemento RichText (consulta la lista completa de atributos con ejemplos)

Paso 3: Definir el atributo align en block.json

Ahora ve al archivo block.json y añade el atributo align:

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

Cuando termines, vuelve al editor de bloques, actualiza la página y selecciona el bloque. Deberías ver un mensaje de error dentro de tu bloque.

El bloque muestra un mensaje de error
El bloque muestra un mensaje de error

El motivo es que aún no hemos definido nuestro controlador de eventos.

Paso 4: Definir los manejadores de eventos

Ahora define onChangeAlign:

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

Si newAlign está undefined, entonces establecemos newAlign como none. En caso contrario, utilizamos newAlign.

Nuestro script edit.js debería estar completo (por ahora):

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 } }
			/>
		</>
	);
}

Ahora puedes volver al editor y alinear el contenido del bloque. Tu bloque debería mostrar con orgullo una Barra de Herramientas de Alineación.

Nuestro bloque tiene ahora una Barra de Herramientas de Alineación
Nuestro bloque tiene ahora una Barra de Herramientas de Alineación

Pero si guardas la entrada, verás que el contenido de tu bloque no está alineado en el front end como lo está en el editor de bloques. Eso es porque tenemos que modificar la función de save para almacenar el contenido y los atributos del bloque en la base de datos.

Paso 5: Guardar los datos

Abre save.js y cambia la función de  save como sigue:

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

Por último, para hacer el código más legible, puede extraer las propiedades individuales del objeto attribute utilizando la sintaxis de asignación de desestructuración:

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

Puedes hacer lo mismo en el archivo edit.js.

Ahora guarda el archivo y cambia al Editor de Código. El código del bloque debería tener el siguiente aspecto:

<!-- 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 -->
Comprobación de los controles de la barra de herramientas del bloque
Comprobación de los controles de la barra de herramientas del bloque

¡Y eso es todo! Acabas de añadir un control de alineación a la barra de herramientas del bloque 🤓

Puede leer más sobre los controles de la barra de herramientas del bloque en el Manual del Editor de Bloques.

Personalización de la barra lateral de configuración del bloque

También puedes añadir controles a la barra lateral de configuración del bloque (o incluso crear una nueva barra lateral para su aplicación).

La API proporciona un InspectorControls componente para ello.

El manual del editor de bloques explica cómo utilizar la barra lateral de configuración:

La barra lateral de ajustes se utiliza para mostrar los ajustes menos utilizados o los que requieren más espacio en la pantalla. La barra lateral de configuración debe utilizarse únicamente para los ajustes a nivel de bloque.

Si tiene ajustes que solo afectan al contenido seleccionado dentro de un bloque (por ejemplo, el ajuste de «negrita» para el texto seleccionado dentro de un párrafo): no lo coloques dentro de la barra lateral de ajustes. La barra lateral de configuración se muestra incluso cuando se edita un bloque en modo HTML, por lo que solo debería contener ajustes a nivel de bloque.

Otra vez:

  1. Importar los componentes necesarios de los paquetes de WordPress
  2. Incluir los elementos correspondientes en tu código JSX
  3. Definir los atributos necesarios en el archivo block.json
  4. Definir manejadores de eventos
  5. Guardar datos

Paso 1. Importar los componentes InspectorControls y PanelColorSettings de @wordpress/block-editor

Puedes añadir varios controles para que los usuarios puedan personalizar aspectos concretos del bloque. Por ejemplo, puedes proporcionar un panel de control del color. Para ello, tendrás que importar los componentes InspectorControls y PanelColorSettings módulo block-editor:

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

Paso 2: Incluir los elementos correspondientes en tu código JSX

Ahora puede añadir los elementos correspondientes al JSX devuelto por la función 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 } }
			/>
		</>
	);
}

Observa que también hemos actualizado el atributo de style del elemento RichText:

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

Paso 3: Definir los atributos necesarios en block.json

Ahora define los atributos backgroundColor y textColor en el archivo block.json:

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

Paso 4: Definir los manejadores de eventos

Ahora necesitas definir dos funciones para actualizar backgroundColor y textColor en la entrada del usuario:

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

Paso 5: Guardar los datos

Un último paso: Abre el archivo save.js y cambia el script de la siguiente manera:

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 } }
		/>
	);
}

Guarda el archivo y comprueba el bloque en el editor. Es posible que te encuentres con una sorpresa no deseada: un mensaje de error que te avisa de que el bloque tiene un contenido inesperado o no válido.

Mensaje de error de contenido inesperado o no válido
Mensaje de error de contenido inesperado o no válido

Esto ocurre porque el archivo save.js se ha modificado y el código guardado en la base de datos no coincide con el código utilizado en el editor.

Para solucionarlo, actualiza la página, elimina cualquier instancia de tu bloque y añádelo de nuevo a tu entrada:

El panel de configuración del Color en la Barra Lateral de Configuración del bloque
El panel de configuración del Color en la Barra Lateral de Configuración del bloque

Realiza los cambios, guarda la entrada y visualízala en el front end. Ahora los cambios que hiciste en el editor de bloques deberían reflejarse en el front site.

El bloque personalizado ahora funciona correctamente en el front end
El bloque personalizado ahora funciona correctamente en el front end

En esta sección, añadirás nuevos componentes a tu tipo de bloque:

  • Un componente ExternalLink permite a los usuarios añadir un enlace personalizable a tu bloque personalizado
  • Varios controles en la barra lateral que permiten a los usuarios personalizar la configuración de los enlaces

Paso 1. Importar componentes desde @wordpress/componentes

Ahora necesitas importar varios componentes de @wordpress/components. Abre tu archivo edit.js y añade la siguiente declaración de import:

import {
	TextControl,
	PanelBody,
	PanelRow,
	ToggleControl,
	ExternalLink
} from '@wordpress/components';
  • PanelBody añade un contenedor plegable a la barra lateral de configuración.
  • PaneRow produce un contenedor genérico para los controles de la barra lateral.
  • TextControl proporciona un control de entrada de texto.
  • ToggleControl proporciona una palanca que permite a los usuarios activar/desactivar una opción específica
  • ExternalLink es un componente sencillo para añadir un enlace externo.

Paso 2. Incluir los elementos correspondientes en su código JSX

En primer lugar, añadirás el elemento ExternalLink al mismo nivel que RichText en un contenedor div:

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

</div>

 

El componente ExternalLink no está documentado, así que nos remitimos al propio componente para obtener la lista de atributos disponibles. Aquí estamos usando los atributos href, className y rel.

Por defecto, el valor del atributo rel está establecido en noopener noreferrer. Nuestro código añadirá la nofollow palabra clave al atributo rel de la etiqueta a resultante cuando el control de alternancia esté activado.

Ahora puedes añadir la configuración de los enlaces a la barra lateral del bloque.

En primer lugar, añadirás un elemento PanelBody dentro de InspectorControls al mismo nivel que PanelColorSettings:

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

Esto es lo que estamos haciendo con esto:

  1. El atributo title proporciona el título del panel.
  2. initialOpen establece si el panel está abierto inicialmente o no.

A continuación, añadiremos dos elementos PanelRow dentro de PanelBody, y un elemento TextControl dentro de cada 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>

El código anterior debería ser bastante sencillo. Los dos controles de texto permiten a los usuarios establecer la etiqueta del enlace y la URL.

También añadiremos un PanelRow adicional con un ToggleControl para activar/desactivar una opción específica, como por ejemplo, incluir o no un atributo:

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

Paso 3: Definir los atributos necesarios en block.json

Ahora define los atributos kaLink, linkLabel y hasLinkNofollow en el archivo block.json:

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

No hay nada más que añadir aquí. Pasemos a definir las funciones de manejo de eventos.

Paso 4: Definir los manejadores de eventos

Get back to the edit.js file, add the new attributes to the attributes object, and add the following functions:

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 } )
}

Estas funciones actualizan los valores de los atributos correspondientes a la entrada del usuario.

Paso 5: Guardar los datos

Por último, tenemos que actualizar la función de save en 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>
	);
}

Ten en cuenta que aquí hemos utilizado un elemento a normal en lugar de ExternalLink.

Puedes ver el resultado en la imagen de abajo.

El panel de Configuración de enlaces en la Barra lateral de Configuración del bloque
El panel de Configuración de enlaces en la Barra lateral de Configuración del bloque

Ahora guarda los datos y reinicia tu entorno.

Añadir varios estilos de bloque

En una sección anterior, aprendiste a añadir un control de barra de herramientas de bloque que permite a los usuarios alinear la entrada del usuario. Podemos añadir más controles de estilo a la barra de herramientas de bloque, pero también podemos proporcionar un conjunto de estilos de bloque predefinidos que el usuario puede elegir con un solo clic.

Para ello, vamos a utilizar una útil función de la API de bloques: Estilos de bloque.

Todo lo que tienes que hacer es definir la propiedad de styles block.json y declarar los estilos correspondientes en tus hojas de estilo.

Por ejemplo, puedes añadir la siguiente serie de estilos:

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

Con esto, acabas de añadir un estilo por defecto y un estilo adicional llamado border. Ahora vuelve al editor de bloques:

Dos estilos de bloque preconstruidos.
Dos estilos de bloque preconstruidos.

Los estilos estarán disponibles para el usuario haciendo clic en el conmutador de bloques y buscando el panel de Estilos en la barra lateral de configuración de bloques.

Selecciona un estilo y compruebe las clases aplicadas al elemento p. Haz clic con el botón derecho del ratón en el bloque e inspecciona. Se ha añadido una nueva clase con un nombre estructurado de la siguiente manera:

is-style-{style-name}

Si ha marcado el estilo «Borde», se añadirá una clase is-style-border al elemento p. Si ha marcado el estilo «Predeterminado», se añadirá una clase is-style-default en su lugar.

Ahora solo tienes que declarar las propiedades CSS. Abre el archivo editor.scss y sustituye los estilos actuales por los siguientes:

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

Ahora puedes hacer lo mismo con style.scss. Como mencionamos anteriormente, los estilos definidos en style.scss se aplican tanto en el front end como en el 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;
	}
}

Y ya está. Actualiza la página y diviértete con tus nuevos estilos de bloques:

Estilos de bloque comparados
Estilos de bloque comparados

Anidación de bloques Gutenberg con el componente InnerBlocks

Although fully functional, our custom block is still not very appealing. Para hacerlo más atractivo para el público, podríamos añadir una imagen.

Esto puede añadir una capa de complejidad a nuestro bloque, pero, afortunadamente, no es necesario reinventar el mundo porque Gutenberg proporciona un componente específico que puedes utilizar para crear una estructura de bloques anidados.

El componente InnerBlocks se define como sigue:

InnerBlocks exporta un par de componentes que pueden utilizarse en las implementaciones de bloques para permitir el contenido de bloques anidados.

En primer lugar, tendrás que crear un nuevo archivo .js en la carpeta src. En nuestro ejemplo, llamaremos a este archivo container.js.

Ahora tendrás que importar el nuevo recurso en el archivo index.js:

import './container';

Vuelve a container.js e importa los componentes necesarios:

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

El siguiente paso es definir una plantilla que proporcione la estructura dentro de la cual se colocarán los bloques. En el siguiente ejemplo, definimos una plantilla que consta de dos columnas que contienen un bloque de imagen principal y nuestro bloque personalizado:

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...' } ],
	] ],
] ] ];

La plantilla está estructurada como una matriz de blockTypes (nombre del bloque y atributos opcionales).

En el código anterior, hemos utilizado varios atributos para configurar los bloques Columnas y Columnas. En concreto, el atributo templateLock: 'all' bloquea los bloques Column para que el usuario no pueda añadir, reordenar o eliminar los bloques existentes. templateLock puede tomar uno de los siguientes valores:

  • allInnerBlocks está bloqueado, y no se pueden añadir, reordenar o eliminar bloques.
  • insert — Los bloques sólo pueden ser reordenados o eliminados.
  • false — – La plantilla no está bloqueada.

La plantilla se asigna entonces al elemento InnerBlocks:

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

Para evitar cualquier problema de compatibilidad, también hemos añadido un atributo templateLock al componente InnerBlocks (véanse también el problema #17262 y el pull #26128).

Aquí está nuestro archivo container.js final:

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>
		)
	},
});
El bloque final en el editor de bloques
El bloque final en el editor de bloques

Mejoras adicionales

Nuestro bloque es totalmente funcional, pero podríamos mejorarlo un poco con algunos pequeños cambios.

Hemos asignado el atributo backgroundColor al párrafo generado por el componente RichText. Sin embargo, podemos preferir asignar el color de fondo al div contenedor:

Por lo tanto, cambie el archivo edit.js y los divs save.js como sigue:

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

Esto permitirá al usuario cambiar el fondo de todo el bloque.

Por otro lado, un cambio más relevante tiene que ver con el método useBlockProps. En el código original, definimos la constante blockProps como sigue:

const blockProps = useBlockProps();

Pero podemos utilizar el useBlockProps de forma más efectiva pasando un conjunto de propiedades. Por ejemplo, podemos importar classnames del módulo classnames y establecer el nombre de la clase envolvente en consecuencia.

En el siguiente ejemplo, asignamos un nombre de clase basado en el valor del atributo 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 }`
	} );
	...
}

Haremos el mismo cambio en el archivo 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 }`
	} );
	...
}

Y eso es todo. Ahora puede ejecutar la construcción para la producción:

npm run build

Resumen

Y aquí estamos, ¡al final de este increíble viaje! Empezamos con la configuración del entorno de desarrollo y terminamos creando un tipo de bloque completo.

Como mencionamos en la introducción, un conocimiento sólido de Node.js, Webpack, Babel y React son esenciales para crear bloques avanzados de Gutenberg y posicionarse en el mercado como desarrollador profesional de Gutenberg.

Sin embargo, no es necesario tener una experiencia establecida en React para empezar a divertirse con el desarrollo de bloques. El desarrollo de bloques podría darte motivación y objetivos para adquirir habilidades cada vez más amplias en las tecnologías que hay detrás de los bloques de Gutenberg.

Esta guía, por lo tanto, está lejos de ser completa. Es simplemente una introducción a una amplia variedad de temas que te ayudarán a empezar a construir tus primeros bloques de Gutenberg.

Por ello, te recomendamos que profundices tus conocimientos leyendo detenidamente la documentación y las guías en línea. Entre los muchos recursos disponibles ahí fuera, te recomendamos los siguientes:

Si estás empezando con el desarrollo de WordPress, es posible que quieras entender los conceptos básicos del desarrollo del frontend. Aquí hay una lista rápida de recursos que pueden ayudarte a empezar:

Y recuerda que el código completo de los ejemplos de esta guía está disponible en Gist.

Ahora es tu turno: ¿Has desarrollado algún bloque de Gutenberg? ¿Cuáles son las principales dificultades que has experimentado hasta ahora? Cuéntanos tu experiencia en los comentarios!

Carlo Daniele Kinsta

Carlo es un diseñador y desarrollador de front-end freelance. Cuando escribe artículos y tutoriales, Carlo se ocupa principalmente de los estándares web, pero cuando juega con sitios web, su mejor compañero de trabajo es WordPress.