hand Inicio
hand JSBloqs
hand GutenBloqs
Qué?
nochedía

DESARROLLO WEB con
REACT y WORDPRESS

Apúntate a la newsletter (escribo algo de tanto en cuanto)
Wallpaper)

Desarrolla un theme en WordPress con React

1700 palabras
7 minutos
October 22, 2020
cursoswordpressreact

WordPress es React, en el frontend para el administrador de WordPress, pero también puede serlo en el frontend para el visitante

UPDATE 2020.10: Reescrito con un theme más sencillo

Prólogo

Para utilizar React en WordPress necesitamos trabajar con dos tecnologías, por un lado el backend con php, y por otro lado React con JavaScript moderno en el frontend

Y ese React y JavaScript moderno necesitamos compilarlo a JavaScript clásico para que los navegadores no tengan problemas, con lo que también necesitaremos correr un backend con NodeJS durante el desarrollo

Lo vemos en este curso

Qué haremos en este curso

Desarrollaremos un theme de WordPress que será una aplicación React integrada en WordPress y que nos permitirá, por ejemplo, utilizar @emotion para gestionar nuestros estilos

Lo mejor de este desarrollo es que no estamos hablando de desarrollar un theme separado de WordPress (como Gatsby) y que por lo tanto su contenido deberá alojarse en otro servidor (aunque no tiene por qué ser así, es lo más habitual)

Aquí estamos hablando de un theme al uso, hospedado con WordPress, con una página (en este caso será una única página) que podremos editar, y con acceso a todos los plugins que queramos

Y esto lo podremos hacer porque nada nos impide utilizar el React que WordPress ya incluye en el backend, también en el frontend

Y qué ventajas tiene esto?

  • Poder trabajar con React

  • Poder aprovechar todo el ecosistema de WordPress

Los themes y plugins que voy desarrollando los puedes ver en gutenbloqs.com con su código fuente

En este caso, el repositorio lo tienes en gutenbloqs-theme-base

  1. Prólogo
  2. Qué haremos en este curso
  3. Entorno de trabajo
  4. Preparar el bloque de Gutenberg y la aplicación React
  5. Los estilos generales
  6. Estructura del theme
  7. La aplicación React
  8. Generando el zip y probando el theme

Entorno de trabajo

Para la programación en React con vscode tienes la configuración del entorno de trabajo en este curso

Además, necesitarás tener una instalación WordPress, y si la quieres en local y en entorno Windows tienes este curso

Con esto, te faltaría añadir algunas extensiones en el editor vscode para trabajar con php y twig, algo que ya me gustaría que estuviera tan estandarizado como para JavaScript

Yo utilizo

  • Format HTML in PHP (rifi2k)

  • Twig Language 2 (mblode)

  • Phpfmt - PHP formatter (kokororin)

Y con esta última tengo añadir la localización de mi php.exe que está instalado via Laragon, esto lo hago en el archivo (que lo creo) en /.vscode/settings.json

json
{
"phpfmt.php_bin": "C:\\laragon\\bin\\php\\php-7.2.19-Win32-VC15-x64\\php.exe"
}

A partir de aquí, ya casi lo tienes todo, aunque faltaría comentar que el theme llevará de serie Timber

Qué es Timber?

Timber / Twig es un sistema que te moderniza WordPress en tanto a liberarte de las "antiguedades" de php, y que aquí utilizaremos para vehicular la transición entre WordPress y React

Es Timber absolutamente necesario?

En absoluto, podrías hacer exactamente lo mismo con php

Timber forma parte de una familia de entornos de desarrollo / starters que te permiten mejorar y mucho la experiencia de desarrollo en WordPress

Ejemplos de alternativas a Timber o soluciones que se basan o pueden basar en Timber serían estos

La mayoría de los listados arriba mejoran mucho el desarrollo en WordPress, pero al mismo tiempo generan una barrera inmensa para el usuario final que no es desarrollador, por lo que su adopción sólo parece razonable si se controla no sólo el desarrollo sino el mantenimiento del site

Ya que nuestro desarrollo se basa en Timber, para nuestro theme utilizaremos el starter de Timber, que lo clonaremos como es habitual (en el terminal de vscode)

bash
git clone https://github.com/timber/starter-theme

Ahora necesitaremos preparar el mismo entorno que pusimos para desarrollar un bloque Gutenberg (tienes el curso aquí)

Resumiendo se trata de un entorno React con NodeJS y Webpack para escribir en JavaScript moderno y generar una versión compatible con JavaScript no tan moderno que es la que WordPress consumirá

Necesitamos el paquete @wordpress/scripts para desarrollo y los paquetes de @emotion para producción, también añado un paquete que integra twig en prettier

Para instalarlo, primero creamos el package.json

json
{
"name": "mi-theme",
"version": "0.0.1",
"description": "mi-theme",
"main": "index.js",
"author": "kuworking.com",
"license": "ISC",
"scripts": {
"start": "wp-scripts start",
"build": "wp-scripts build"
}
}

Y luego instalamos las dependencias desde el terminal que es más cómodo (con yarn o npm, esto va a gustos)

bash
yarn add --dev --exact @wordpress/scripts
yarn add --exact @emotion/core @emotion/styled
yarn add --dev --exact @babel/core @babel/plugin-proposal-class-properties @wordpress/babel-preset-default @wordpress/scripts babel-eslint babel-plugin-emotion eslint eslint-config-prettier eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-prettier eslint-plugin-promise eslint-plugin-react eslint-plugin-standard prettier prettier-plugin-twig-melody

Sólo nos falta asegurarnos que la carpeta que hemos clonado arriba esté en la carpeta de WordPress /wp-content/themes

O bien la clonamos el theme directamente allí, o simplemente movemos la carpeta a ese directorio y después abrimos la carpeta otra vez con vscode

Ahora nos falta instalar Composer, que viene a ser lo que es NPM para librerías de JavaScript, pero para php

Es decir, un gestor de librerías para php

Si has instalado WordPress localmente, ya tendrás php instalado y ya puedes instalar Composer siguiendo la documentación oficial

Una vez instalado, tenemos el archivo composer.json donde le diremos que necesitamos instalarnos la librería de Timber

json
{
"name": "kuworking/mi-theme",
"description": "mi-theme",
"type": "wordpress-theme",
"minimum-stability": "stable",
"repositories": [
{
"type": "composer",
"url": "https://wpackagist.org"
}
],
"require": {
"timber/timber": "1.*"
}
}

Ahora ejecutamos composer en el terminal con composer install y nos instalará Timber, nos lo instalará en la carpeta con lo que luego nosotros podremos incluirlo en el .zip final de nuestro theme

Y ahora ya sí, ya lo tenemos todo preparado para continuar

Preparar el bloque de Gutenberg y la aplicación React

Antes de desarrollar los bloques, hay que tener claro que necesitaremos generar dos archivos

  • El correspondiente al bloque de Gutenberg

  • El correspondiente a la aplicación React del frontend

Los dos archivos compartiran el grueso del código (esto es, el componente), pero luego cada uno ira a lo que le toca

Dicho así sería tan sencillo como crear estos dos archivos, pero puesto que queremos compilarlo (con webpack), tenemos que decirle a webpack que nos genere estos dos archivos

Lo hacemos "extendiendo" la configuración que WordPress utiliza para él mismo (que tienes aquí), simplemente añadiendo un par de cosas:

  • Que genere 2 archivos finales a partir de 2 archivos de inicio

  • Que genere enlaces "simbólicos" que nos vinculen el React de WordPress con el React verdadero, que tienen nombres distintos (y nos servirá para cuando utilicemos librerías que esperan importar React como habitualmente)

js
// webpack.config.js
const path = require('path')
const defaults = require('@wordpress/scripts/config/webpack.config')
module.exports = {
...defaults,
entry: {
index: path.resolve(process.cwd(), 'src', 'index.js'),
card: path.resolve(process.cwd(), 'src', 'gutenberg/card.js'),
},
externals: {
react: 'React',
'react-dom': 'ReactDOM',
},
}

Con esto estamos diciendo que nuestros dos archivos raiz serán el /src/index.js y el /src/gutenberg/card.js

Pronto los crearemos

Antes, terminamos la configuración de webpack con babel, creando el archivo .babelrc y allí volcamos lo siguiente

js
{
"presets": ["@wordpress/babel-preset-default"],
"plugins": ["emotion", "@babel/plugin-proposal-class-properties"]
}

Webpack seguirá lo que babel le diga ya que en la configuración de webpack (la de WordPress) utiliza el babel-loader, y aquí en babel introducimos el plugin para babel de @emotion (aquí, y para WordPress aquí)

Ahora ya tenemos webpack y babel preparados, podemos seguir

Los estilos generales

Nuestro theme necesita por convenio un archivo style.css

Pero si vamos a utilizar @emotion debería estar vacío, no?

Podría, pero también podemos aprovecharlo para añadir estilos específicos y generales, y por ejemplo para cargar las fuentes que queramos

Además, lo necesitamos para dar nombre al theme, claro

css
/*
* Theme Name: mi-theme
* Description: mi-theme
* Author: Kuworking
*/
@import url('https://fonts.googleapis.com/css2?family=Open+Sans&family=Handlee&display=swap');
body {
margin: 0;
}

Estructura del theme

No necesitamos todos los archivos que nos vienen en el starter de Timber (o en cualquier starter de WordPress puro)

O sí los necesitamos, al final depende de lo que queramos hacer, pero en este ejemplo haré lo mínimo para que el theme funcione

index.php

Aquí Timber se inicializa implementando un context, nos redirige a la template de twig, y lo renderiza

php
$context = Timber::context();
$templates = array('index.twig');
Timber::render($templates, $context);

index.twig

Originalmente este archivo extiende el archivo troncal base.twig, pero aquí podemos redefinirlo para reducirlo todo a la mínima expresión

php
<!doctype html>
<!--[if lt IE 9]><html class="no-js no-svg ie lt-ie9 lt-ie8 lt-ie7" {{ site.language_attributes }}> <![endif]-->
<!--[if IE 9]><html class="no-js no-svg ie ie9 lt-ie9 lt-ie8" {{ site.language_attributes }}> <![endif]-->
<!--[if gt IE 9]><!-->
<html class="no-js no-svg" {{ site.language_attributes }}>
<!--<![endif]-->
<head>
<meta charset="{{ site.charset }}" />
<meta name="description" content="{{ site.description }}">
<link rel="stylesheet" href="{{ site.theme.link }}/style.css" type="text/css" media="screen" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="author" href="{{ site.theme.link }}/humans.txt" />
<link rel="pingback" href="{{ site.pingback_url }}" />
<link rel="profile" href="http://gmpg.org/xfn/11">
{{function('wp_head')}}
<!-- REACT script -->
{{ add_react() }}
<!-- REACT script END -->
</head>
<body>
<!-- REACT anchor -->
<div id="gutenbloqs-theme-base"></div>
<!-- REACT anchor END -->
{% block content %}
{# prettier-ignore-start #}
<script>
window.gutenbloqs_theme_base = {{ expose_data()|json_encode }}
</script>
{# prettier-ignore-end #}
{% endblock %}
{{ function('wp_footer') }}
</body>
</html>

Básicamente definimos el documento html con lo habitual, pero con tres añadidos

php
{{ add_react() }}

Aquí añadimos React, lo vemos en un momento

php
<div id="gutenbloqs-theme-base"></div>

Aquí añadimos un <div> donde renderizaremos nuestra aplicación React

php
<script>
window.gutenbloqs_theme_base = {{ expose_data()|json_encode }}
</script>

Y aquí es donde ocurre todo, puesto que la manera que tenemos de comunicar la aplicación React con el backend de WordPress es así, volcando la información en una variable global de JavaScript

Es decir, lo que WordPress nos da (con la función expose_data() que ahora veremos) lo almacenamos en una variable, y luego desde React accederemos a esa variable y utilizaremos esa información

Puede parecer poco eficiente, pero sistemas como Gatsby hacen exactamente lo mismo, pasan la información con JavaScript que luego React tiene que interpretar

La alternativa es que React pida la información a WordPress mediante la REST API, un enfoque que muchos utilizan, pero que en mi opinión es menos eficiente al requerir peticiones http (puedes buscar en google para ver si el tema ha mejorado, y explorar un hack aquí)

functions.php

Este es el archivo madre de todos los archivos, el que gestiona nuestro website, y el que presenta una estructura caótica y que va muy bien separar en archivos individuales

Comparado con Gatsby, sería el gatsby-node.js de allí

Aquí dejamos el grueso tal y como nos viene en el starter de Timber, excepto 3 detalles

php
if (!is_admin()) {
add_action("wp_enqueue_scripts", function () {
wp_deregister_script('jquery');
}, 11);
}

Este código nos quita JQuery, que no lo queremos para nada

Y dentro de la clase de Timber

php
class StarterSite extends Timber\Site
{
/** ............. */
public function add_to_twig($twig)
{
$twig->addFunction(new Timber\Twig_Function('add_react', function () {
wp_register_script(
'kw-react',
get_template_directory_uri() . '/build/index.js',
['wp-element'],
'0.01'
);
wp_enqueue_script('kw-react');
}));
$twig->addFunction(new Timber\Twig_Function('expose_data', function () {
return [
'theme_link' => get_stylesheet_directory_uri(),
];
}));
return $twig;
}
}

Aquí definimos las dos funciones que hemos visto (y llamado) antes

  • add_react

Aquí añadimos el script que webpack nos habrá compilado, en /build/index.js, y con la dependencia wp-element que incluye React

  • expose_data

Aquí devolvemos un objeto que en este caso solo contiene un dato que es la dirección del directorio (que nos puede ser útil para utilizar imágenes, por ejemplo)

Aquí es donde configuraríamos el exportar datos de las entradas, de los bloques, de lo que sea que queramos exponer para luego consumir con React

Con esto ya lo tenemos todo para empezar el desarrollo con React

La aplicación React

La aplicación será testimonial, porque se trata de ver cómo integrar y comunicar React con WordPress

Entonces, qué nos falta?

Con webpack hemos apuntado a /src/index.js, con lo que tenemos que crear el archivo

js
const { render } = wp.element
import { Layout } from './components/layout'
const onload = () => render(<Layout />, document.getElementById(`gutenbloqs-theme-base`))
window.addEventListener
? window.addEventListener('load', onload, false)
: window.attachEvent && window.attachEvent('onload', onload)

Aquí básicamente lo que hacemos es esperar a que el documento se cargue, y cuando se haya cargado ejecutamos la aplicación React en el <div> que hemos introducido antes y que para entonces ya se habrá renderizado en el documento

Y nuestra aplicación será el componente <Layout> que importaremos del archivo correspondiente

Ese archivo ya será la aplicación en sí, y en este caso no puede ser más sencilla

js
const { useEffect, useState } = wp.element
import { Global, css } from '@emotion/core'
import styled from '@emotion/styled'
const GlobalStyles = () => (
<Global
styles={css`
html {
background-size: cover;
box-sizing: border-box;
height: 100%;
min-height: 100%;
font-size: 62.5%;
}
body {
font-family: 'Open Sans';
font-family: 'Source Sans Pro', sans-serif;
text-rendering: optimizeLegibility;
margin: 0;
font-size: 16px; /* fallback for rem */
font-size: 1.6rem;
}
`}
/>
)
export const Layout = () => {
const [gb, setGb] = useState()
useEffect(() => {
setGb(window.gutenbloqs_theme_base)
}, [])
return (
<Div>
<GlobalStyles />
<div className="layout">
<h1>[ GUTENBLOQS THEME BASE ]</h1>
<div>{JSON.stringify(gb)}</div>
</div>
</Div>
)
}
const Div = styled.main`
display: flex;
flex-direction: column;
flex-wrap: nowrap;
align-items: center;
transition: 0.2s all ease-in;
& .layout {
max-width: 800px;
width: 100%;
}
`

Que sin entretenerme, utilizo el Global de @emotion, algo que no hace falta si no queremos ya que podemos utilizar el style.css que hemos comentado antes, aunque así lo tenemos todo más centralizado y encapsulado

Y luego muestro el contenido de la variable que antes he expuesto window.gutenbloqs_theme_base

Lo único que vale la pena destacar es que en lugar de utilizar la variable tal cual, voy sobre seguro y la almaceno en una variable de estado, y así me aseguro de que si no está disponible al principio no pasa nada

js
const [gb, setGb] = useState()
useEffect(() => setGb(window.gutenbloqs_theme_base), [])

Queda comentar el hecho de cómo estoy importando useState y useEffect, es decir directamente de WordPress y no de React

Y ahora ya sí, ya lo tenemos casi todo

Que nos faltaría?

encapsularlo todo en un archivo .zip

Generando el zip y probando el theme

Para encapsularlo basta con añadir todos los archivos relevantes en un archivo .zip, y luego subir el tema en WordPress como es habitual

Ese archivo contendrá Timber que lo tenemos en la carpeta /vendor, el JavaScript compilado en la carpeta /build, todos los archivos de base y también las /templates

Esto lo tengo automatizado con el script zip.js que si exploras verás lo que hace

El repositorio lo tienes en gutenbloqs-theme-base, y para replicarlo tendrías que hacer lo siguiente

bash
git clone https://minhaskamal.github.io/DownGit/#/home?url=https://github.com/kuworking/gutenbloqs/tree/main/themes/gutenbloqs-theme-base
yarn
composer install
yarn start
yarn build
npm run zip

Donde yarn start o yarn build lo utilizaremos para desarrollo o para compilar, y el npm run zip para generar el archivo zip

Para el git clone deberías utilizar todo el repositorio, si quieres clonar una carpeta puedes utilizar (es lo que he hecho arriba) la herramienta DownGit (github)

Y ya lo tendrías

Listos!

🙋‍♂️

Qué tal el curso?

👌 Bien 🙌🙌
👍 Bien, pero algunas cosas podrían explicarse mejor 😬
🤷‍♂️ Da por sentadas demasiadas cosas 😒
🤷‍♂️ A ver, hay poca chicha 😬
🤷‍♂️ Los ejemplos no son muy claros 🙇‍♂️
🤷‍♂️ No se entiende, está mal escrito 👎
✍️ Hay errores, revísalo en cuanto puedas 🙏
Enviar Feedback ✍️
El texto está en blanco!
Gracias por enviarme tu opinión
👍

Si quieres explorar más cursos y más entradas en el blog, los tienes todos en la página principal, y si el contenido te ha ayudado dame las gracias por ejemplo por twitter con este enlace 👍

Privacidad
by kuworking.com
[ 2020 >> kuworking ]