Blog de Juan Miguel Sosso | Drupal | PHP | Docker

React en Drupal 8 con Laravel Mix

React photo gallery

En esta ocasión vamos a ver como integrar un componente React en nuestro Drupal 8 utilizando Laravel Mix.

Lo podríamos hacer también configurando manualmente los preprocesadores JavaScript y CSS que vayamos a necesitar, pero con Laravel Mix nos vamos a ahorrar gran parte de ese trabajo ya que nos da una receta lista para utilizar.

Requerimientos

Antes de empezar debes tener instalados node y npm. Puedes encontrar muchos artículos en la red que explican como hacerlo, por lo que no voy a incluir esa parte aquí.

El módulo Drupal

Para este ejemplo vamos a crear una galería de imágenes basada en un componente ya existente.

Creamos un módulo nuevo en Drupal 8 con el típico archivo react_photo_gallery.info.yml:

name: 'Photo Gallery'
version: 8.x-0.1
description: 'React photo gallery for Drupal 8.'
type: module
core: 8.x

Y otro para definir las librerías JavaScript que vamos a utilizar, react_photo_gallery.libraries.yml:

photo_gallery:
  js:
    js/dist/index.js: { preprocess: false }

A continuación creamos el directorio js y dentro de él inicializamos un proyecto npm:

js$ npm init

Responde a todas las preguntas y al final tendrás el archivo js/package.json dentro del directorio de tu módulo.

Por último instalamos React y Laravel Mix:

js$ npm install react react-dom
js$ npm install laravel-mix cross-env --save-dev

Configurar Laravel Mix

Ahora tenemos que crear el archivo js/webpack.mix.js donde vamos a indicar el directorio de nuestro código fuente JavaScript y el directorio de destino del código traspilado:

const mix = require('laravel-mix');

mix.react('src/index.js', 'dist').sourceMaps();

Además le indicamos que queremos generar source maps para tener información más completa a la hora de debugear nuestro código en el navegador.

Añadimos todos los scripts necesarios a la sección de scripts de nuestro js/package.json:

  "scripts": {
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "npm run development -- --watch",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  },

Los dos más importantes son npm run watch para desarrollo y npm run production para producción.

Nuestro componente React

Llegados a este punto ya podemos empezar a trabajar en nuestro componente. Creamos el directorio src y dentro de él el archivo index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import ImageGallery from './components/PhotoGallery/PhotoGallery';

ReactDOM.render(<PhotoGallery />, document.getElementById('photo-gallery'));

La ruta completa a este archivo sería js/src/index.js. No te olvides que toda la parte React va dentro del directorio js de nuestro módulo.

A continuación creamos el directorio components y dentro PhotoGallery. Dentro de este último creamos el archivo PhotoGallery.js:

import React from 'react';
import Gallery from 'react-photo-gallery';

const photos = [
  {
    src: 'https://picsum.photos/300/200',
    width: 5,
    height: 3,
  },
  {
    src: 'https://picsum.photos/200',
    width: 1,
    height: 1,
  },
  {
    src: 'https://picsum.photos/350/250',
    width: 4,
    height: 3,
  },
  {
    src: 'https://picsum.photos/300',
    width: 1,
    height: 1,
  },
];

const PhotoGallery = () => <Gallery photos={photos} />;

export default PhotoGallery;

Nuestro componente simplemente llama al componente real que genera la galería de fotos utilizando 4 imágenes aleatorias generadas por el servicio picsum.photos. Este componente se llama React photo gallery y lo tenemos que instalar con:

js$ npm install react-photo-gallery

Ahora podemos construir nuestro componente React con npm run development o bien npm run watch para que la transpilación se realice de forma automática cada vez que guardemos un archivo de código fuente.

Mostrar el componente en Drupal

Por último tenemos que decidir donde queremos mostrar nuestro componente React, en este caso nuestra gallería de fotos.

En principio podemos mostrarlo en una página, utilizando una clase Controller, o en un bloque, utilizando una clase que extienda de BlockBase. Creo que para una galería de fotos lo mejor es mostrarla en una página, ya que puede ser grande si quereos mostrar muchas imágenes.

Vamos a crear, ya fuera del directorio js en la raíz de nuestro módulo, el directorio src y dentro el directorio Controller. Dentro de este último creamos el archivo de nuestra clase controller ImageGalleryController.php:

<?php

namespace Drupal\react_photo_gallery\Controller;

use Drupal\Core\Controller\ControllerBase;

/**
 * Photo gallery page.
 */
class PhotoGalleryController extends ControllerBase {

  /**
   * React component page.
   */
  public function page() {
    return [
      '#markup' => '<div id="photo-gallery"></div>',
      '#attached' => [
        'library' => 'react_photo_gallery/photo_gallery',
      ],
    ];
  }

}

Esta controller simplemente genera una página vacía con una etiqueta div que será donde el código JavaScript muestre nuestro componente. También le indica a Drupal que debe cargar la librería react_photo_gallery/photo_gallery que es precisamente donde se encuentra dicho código.

Y también necesitamos su correspondiente archivo react_photo_gallery.routing.yml para definir su ruta de acceso:

react_photo_gallery.photo_gallery:
  path: '/photo-gallery'
  defaults:
    _controller: '\Drupal\react_photo_gallery\Controller\PhotoGalleryController::page'
    _title: 'Photo Gallery'
  requirements:
    _permission: 'access content'

Ahora ya podemos habilitar el módulo y comprobar si todo funciona correctamente. Lo puedes hacer con drush o directamente desde la página de administración de módulos de Drupal.

Luego navega a la dirección local de tu sitio Drupal, por ejemplo http://localhost/photo-gallery, y debería aparecerte la galería de fotos con 4 fotografías. Para añadir más imagénes y cambiar su presentación consulta la documentación del componente original.

A la hora de desplegar solo es necesario el directorio js/dist y no js/node_modules. Por cierto, ambos deben estar excluídos de nuestro repositorio git. Para generar el directorio dist para producción ejecuta:

js$ npm run production

Puedes descargar el código fuente completo de este ejemplo en mi reposositorio de GitHub: react-photo-gallery.

Juan Miguel Sosso

Añadir nuevo comentario