Contenido
- Primeros Pasos
- Creando un Plugin de WordPress
- Instalando las dependencias.
- Agregando webpack
- Archivos para crear el primer Bloque
- Creando el Primer Bloque
- Los 7 Pasos para utilizar los Componentes de Gutenberg.
- Paso 1: Importar el Componente o los Componentes que utilizarás.
- Paso 2: Coloca el Componente donde deseas utilizarlo.
- Paso 3: Crea una función que lea los contenidos del Componente
- Paso 4: Registrar un Atributo
- Paso 5: Extraer el Atributo desde Props.
- Paso 6: Guarda el Contenido con setAttributes
- Paso 7: Trabajar con save()
- Código completo hasta aquí
El Desarrollo en WordPress está evolucionando en la dirección correcta. PHP aún juega un papel importante pero con Gutenberg ya es posible utilizar tecnologías modernas como React, webpack, npm para crear bloques.
Actualmente Gutenberg solo reside en el Editor de WordPress, pero en los próximos años temas completas serán realizados con Gutenberg.
Primeros Pasos
Para comenzar a trabajar con nuestro Primer Bloque es necesario instalar un ambiente de desarrollo y algunas herramientas, debido a que estaremos utilizando una herramienta llamada WP-Scripts que simplifica el desarrollo de Bloques de Gutenberg y la forma de agregarla en nuestro proyecto es con NPM es necesario instalar Node.js y NPM. En el sitio web de Node.js puedes descargarlo, una vez que sigues el wizard de instalación puedes comprobar la instalación en una terminal o command promp con los comandos:
node -v
npm -v
Si tienes un resultado con alguna versión, ya tienes instalado Node.js y npm.
Creando un Plugin de WordPress
El código de bloques personalizados de Gutenberg puede residir en un tema o en un Plugin por lo tanto en una instalación de WordPress en la carpeta wp-content/plugins/ creamos una carpeta llamada bloques-gutenberg y dentro de esta carpeta el archivo bloques-gutenberg.php, tenemos que agregar información para decirle a WordPress que este es un nuevo Plugin.
<?php
/*
Plugin Name: Gutenberg Blocks para WordPress
Plugin URI:
Description: Plugin para crear bloques de Gutenberg
Version: 1.0.0
Author: Juan De la torre
Author URI: @JuanDevWP en Twitter
Text Domain: guten
*/
Una vez agregado este código y guardado el archivo accedemos a Plugins y activamos nuestro nuevo Plugin.
Después, copia el siguiente código (para más explicación de lo que hace este código puedes revisar los comentarios que he colocado en el)
<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Prevenir que el plugin sea ejecutado directamente
/** Registra Bloques Personalizados */
add_action( 'init', 'ccj_bloques');
function ccj_bloques() {
// Si gutenberg no esta activado
if ( !function_exists( 'register_block_type' ) ) {
return;
}
// Registrar el archivo script.js para gutenberg
wp_register_script(
'ccj-editor-script', // nombre
plugins_url( 'build/index.js', __FILE__ ), // archivo script
array( 'wp-blocks', 'wp-i18n', 'wp-element', 'wp-editor' ), // dependencias
filemtime( plugin_dir_path( __FILE__ ) . 'build/index.js' ) // version
);
// Registrar CSS para el editor (unicamente)
wp_register_style(
'ccj-editor-styles', // nombre
plugins_url( 'build/editor.css', __FILE__ ), // archivo
array( 'wp-edit-blocks' ), // dependencias
filemtime( plugin_dir_path( __FILE__ ) . 'build/editor.css' ) //version
);
// Registrar CSS para el frontend y editor
wp_register_style(
'ccj-frontend-styles', // nombre
plugins_url( 'build/style.css', __FILE__ ), // CSS
array(), // dependencias
filemtime( plugin_dir_path( __FILE__ ) . 'build/style.css' ) // version
);
// Arreglo de Bloques (Conforme vayas creando bloques aqui deberás registrarlos)
$blocks = [];
// Recorrer $blocks y agregar cada uno
foreach( $blocks as $block ) {
register_block_type( $block, array(
'editor_script' => 'ccj-editor-script', // agregar script de editor
'editor_style' => 'ccj-editor-styles', // agregar estilos de editor
'style' => 'ccj-frontend-styles', // agregar estilos frontend
) );
}
}
El código anterior puedes notar que carga un archivo llamado index.js en la carpeta build/ así como una hoja de estilos CSS para el frontend y una para el editor, en Gutenberg tendrás 2 hojas de estilos, en algunos casos una para ajustes o CSS en el editor, mientras que la otra para la presentación de tus bloques en el FrontEnd.
Instalando las dependencias.
El siguiente paso es crear un archivo package.json para manejar las dependencias de nuestro proyecto, en este caso WP-Scripts. por lo tanto puedes abrir tu terminal y navega hasta la carpeta del plugin o si utilizas VS Code puedes hacer lo siguiente:
Al escribir npm init, te aparecerán una serie de opciones, solo presiona enter o coloca la información como autor, nombre de paquete según creas conveniente.
Esto creará un archivo package.json donde se guardarán las dependencias ( o nombres de los paquetes que utilizaremos, así como sus versiones).
Vamos a instalar unas dependencias, en la misma terminal que esta abierto puedes colocar lo siguiente:
npm install @wordpress/scripts svgr/webpack url-loader --save-dev
Este paso toma alrededor de 5 o 10 minutos dependiendo tu conexión así que esperamos un poco. Una vez listo abrimos el package.json y busca una sección que dice “scripts” y reemplaza su contenido por el siguiente:
"scripts": {
"start": "wp-scripts start",
"build": "wp-scripts build"
},
WP-Scripts ya cuenta con una serie de scripts y funciones para simplificar el desarrollo de bloques de Gutenberg, es una excelente herramienta desarrollada por los creadores de Gutenberg.
Agregando webpack
Webpack nos permitirá crear un bundle optimizado para producción tomando todas las ventajas de Webpack como Code Splitting y mucho más, crea un archivo llamado webpack.config.js y agrega lo siguiente:
const defaultConfig = require("@wordpress/scripts/config/webpack.config");
module.exports = {
...defaultConfig,
module: {
...defaultConfig.module,
rules: [
...defaultConfig.module.rules,
{
test: /\.svg$/,
use: ["@svgr/webpack", "url-loader"]
}
]
}
};
Archivos para crear el primer Bloque
En el plugin que hemos creado vamos a agregar una carpeta llamada src/ por lo tanto la estructura de nuestro proyecto será asi:
bloques-gutenberg/
- node_modules/
- src/
- bloques-gutenberg.php
- package.json
- webpack.config.js
Dentro de esta carpeta llamada src/ colocaremos un archivo llamado index.js ya que WP-Scripts buscará este archivo en esta ubicación para comenzar a compilar los bloques de Gutenberg.
Después crearemos una carpeta para nuestro primer bloque, es buena práctica tener una carpeta por bloque que generes, por lo tanto en src/ crearemos la carpeta integrante y dentro un archivo llamado index.js, nuestra estructura será asi:
bloques-gutenberg/
- node_modules/
- src/
- integrante/
index.js
- index.js
- bloques-gutenberg.php
- package.json
- webpack.config.js
El siguiente paso es utilizar una de las nuevas caracteristicas de JavaScript e importar los contenidos de integrante/index.js, para ello abrimos el index.js que se encuentra en src/ y agregamos ell siguiente código
import "./integrante";
Es importante nombrar el archivo dentro de la carpeta integrante/ como index.js ya que de esta forma JavaScript buscará ese archivo automaticamente y no necesitas colocar el nombre del archivo en ese import. Escribe el siguiente comando en tu terminal:
npm start
Este comando ejecutará las tareas de WP-Scripts y te va a crear la carpeta build/ – que registramos en el plugin – así como el archivo index.js
A estas alturas es buena idea crear en build/ los archivos editor.css y style.css, lo puedes hacer manualmente en VS Code, más delante volveremos hacia esos archivos.
Creando el Primer Bloque
Cada bloque estará en una carpeta, por lo tanto estaremso trabajando en el archivo index.js de la carpeta integrante/ agrega el siguiente código en el archivo:
import { registerBlockType } from '@wordpress/blocks'; // importar función principal
registerBlockType('ccj/integrante', { // El nombre va sin espacios y en minusculas
title: 'Integrante Equipo', // Nombre del bloque
icon: 'admin-users', // Cualquier dashicon
category: 'layout', // Valores posibles: common, formatting, layout, widgets, embed
edit: () => {
return (
<p>Todo lo que coloques en edit() se ve en Gutenberg</p>
)
},
save: () => {
return (
<p>Todo lo que coloques en save() se ve en el front end/p>
)
}
});
Asegúrate de tener corriendo el comando npm start en tu terminal, una vez que guardes cambios y abras Gutenberg, en la categoría de Layout Elements encontrarás nuestro bloque.
Dependiendo de la categoría seleccionada es donde el bloque se mostrará, en nuestro caso nuestro código le dice a este bloque que deberá estar en ‘category: ‘layout’, otras opciones para la categoría son: common, formatting, layout, widgets, embed. Importante también mencionar que puedes crear tus propias categorías.
Los 7 Pasos para utilizar los Componentes de Gutenberg.
En Gutenberg la mayoría de componentes ya están desarrollados, existen componentes para subir fotos, videos, texto, columnas, etc. Para utilizarlos se siguen una serie de pasos que es lo que yo llamo: Los 7 Pasos para utilizar los Componentes de Gutenberg.
Paso 1: Importar el Componente o los Componentes que utilizarás.
Vamos a importar un componente que nos permite escribir, ya que de momento nuestro bloque no hace mucho, coloca el siguiente código en la parte superior de integrante/index.js
import { RichText } from '@wordpress/editor';
En este caso importamos el componente RichText, de wordpress/editor, en el editor de Gutenberg puedes abrir la consola de tu navegador y escribir wp.editor para acceder a todos los componentes.
Paso 2: Coloca el Componente donde deseas utilizarlo.
Nuestro componente permite que el usuario escriba texto, por lo tanto lo colocaremos en el edit() para que el usuario pueda escribir en el mientras estamos en Gutenberg, también le pasaremos un placeholder para darle indicaciones al usuario, atributos como placeholder son valores que le puedes pasar a cada componente y pueden variar de acuerdo a los diferentes Componentes.
return (
<RichText
placeholder="Agrega el titulo de esta sección"
/>
)
Paso 3: Crea una función que lea los contenidos del Componente
Tener un RichText nos permitirá escribir en el Componente, pero debemos escribir una función que lea sus contenidos, para ello utilizaremos un evento de React llamado onChange que detectará y ejecutará una función cada que un usuario este escribiendo, ya con la función nuestro edit() debe verse así:
edit: () => {
// Funciones para leer los contenidos de nuestros componentes
const onChangeNombre = (nuevoNombre) => {
console.log(nuevoNombre)
}
return (
<p className="nombre">
<RichText
placeholder="Agrega el nombre del Integrante"
onChange={onChangeNombre}
/>
</p>
)
}
De esta forma conforme el usuario escriba o utilice el componente, se estará enviando a la consola el contenido.
Paso 4: Registrar un Atributo
Los atributos son los que guardan la información, la cantidad y tipo de atributos que tengas serán la forma que deberá tener tu bloque, si creas un bloque para mostrar un testimonial, tus atributos serán un texto, imagen y nombre de la persona que escribe ese testimonial, por lo tanto serán únicos en cada componente, antes de la función edit() agregamos:
attributes: {
nombreIntegrante: {
type: 'string',
source: 'html',
selector: '.nombre'
}
},
edit: () => // Código previo...
El atributo anterior, debido a que será utilizado para el RichText debemos decirle que guardará HTML y además será utilizado por el selector (similar a CSS) que tenga una clase llamado nombre, casi todos tus atributos deberán tener un selector que sea una clase y un selector tipo CSS.
Paso 5: Extraer el Atributo desde Props.
En Gutenberg también hay props al igual que en React, contienen funciones y los diferentes atributos, para extraerlos lo hacemos dentro de la función edit: (props) => – Siempre puedes enviar a la consola console.log(props) para poder ver el contenido de los props, aplicando destructuring de JavaScript podemos extraer el atributo desde props:
const { attributes: { nombreIntegrante } } = props;
Paso 6: Guarda el Contenido con setAttributes
setAttributes será la función que se encargue de guardar lo que lee nuestra función en el evento del Componente en el atributo, es como el conector entre atributo y Componente, setAttributes se encuentra disponible en los props, por lo tanto primero hay que extraerlo, del código anterior agregamos setAttributes por fuera del destructuring de attributes:
const { attributes: { nombreIntegrante } setAttributes } = props;
Nuestra función que actualmente esta escrita asi:
const onChangeNombre = (nuevoNombre) => {
console.log(nuevoNombre)
}
Deberá quedar así:
const onChangeNombre = nuevoNombre => {
setAttributes({ nombreIntegrante: nuevoNombre})
}
También es buena idea que el atributo que hemos extraido anteriormente sea pasado como value del componente:
<RichText
placeholder="Agrega el nombre del Integrante"
onChange={onChangeNombre}
value={nombreIntegrante}
/>
Paso 7: Trabajar con save()
save() será similar a edit() en muchas cosas, pero en lugar de permitirle al usuario editar el contenido, va a mostrarlo, tenemos que extraer los props y también utilizar el componente aunque con una sintaxis diferente:
save: (props) => {
// Extraer Contenido de Props
const { attributes: { nombreIntegrante } } = props;
return (
<p className="nombre">
<RichText.Content value={nombreIntegrante} />
</p>
)
}
A diferencia del RichText de edit, en el save() mostraremos el contenido guardado en ese atributo, por lo tanto no requerimos un evento, si no más bien mostrar el contenido con .Content
De esta forma podremos Guardar cambios, abrir Gutenberg y probar nuestro Componente.
Código completo hasta aquí
import {registerBlockType } from '@wordpress/blocks';
import { PlainText, RichText } from '@wordpress/editor';
registerBlockType('wcgdl/equipo', {
title: 'Integrante Equipo',
icon: 'admin-users',
category: 'layout', // common, formatting, layout, widgets, embed
attributes: {
nombreIntegrante: {
type: 'string',
source: 'html',
selector : '.nombre'
}
},
edit: (props) => {
// Extraer Contenido de Props
const { attributes: { nombreIntegrante }, setAttributes } = props;
// Funciones para leer los contenidos de nuestros componentes
const onChangeNombre = nuevoNombre => {
setAttributes({ nombreIntegrante: nuevoNombre });
}
return (
<p className="nombre">
<RichText
placeholder="Nombre Integrante"
onChange={ onChangeNombre }
value={nombreIntegrante}
/>
</p>
)
},
save: (props) => {
// Extraer Contenido de Props
const { attributes: { nombreIntegrante } } = props;
return (
<p className="nombre"><RichText.Content value={nombreIntegrante} /></p>
)
}
});
Los pasos vistos en este Bloque se repiten a lo largo de la mayoria de los bloques, para no hacer una entrada más larga he decidido crear un repositorio que puedes ver y estudiar, si tienes alguna duda puedes hacermela saber por Twitter en @JuanDevWP