Skip to research

Implementation de React dans un custom module Drupal 8 via Webpack

Image
Illustration for react to drupal
Temps de lecture
Environ 5 minutes

Nous allons implémenter ReactJs dans un module Drupal 8 en nous appuyant sur webpack pour la compilation du code.

Pré-requis

On vérifie que nous avons node.js, npm  et yarn d'installer sur notre machine. yarn permet une meilleur maitrise des dépendances, mais si vous préférez utiliser npm, vous pouvez.

 

PS C:\Users\mm\Documents\tdb\workspace\REACT\react_to_drupal> node -v
v8.11.1

PS C:\Users\mm\Documents\tdb\workspace\REACT\react_to_drupal> npm -v
5.6.0

PS C:\Users\mm\Documents\tdb\workspace\REACT\react_to_drupal> yarn -v
1.7.0

 

Le squelette du module drupal

Créons un dossier react_to_drupal au nom de notre custom module, puis à l'intérieur créons
 

  • le fichier /react_to_drupal/react_to_drupal.info.yml
name: React to Drupal
type: module
description: 'Implement ReactJs in a custom module Drupal 8 with Webpack.'
package: MM
core: 8.x
dependencies:
  - rest
  - system (>=8.2.0)

 

  • Le fichier /react_to_drupal/react_to_drupal.module, vide pour l'instant, le fichier .module est obligatoire pour activer un module Drupal.
<?php

 

  • et le fichier /react_to_drupal/react_to_drupal.libraries.yml
react:
  js:
    react/dist/app.bundle.js: {}
  css:
    component:
      'react/dist/app.bundle.css': {}

Le block pour recevoir notre App

  • le fichier /react_to_drupal/src/Plugin/Block/ReactBlock.php

    A la racine du module react_to_drupal créé les dossiers src/Plugin/Block, puis à l'intérieur du dossier Block, créer le fichier ReactBlock.php et sa class. Class plutôt simple, on place une div avec un id #app pour injecter notre application dans le markup du block et a laquelle nous allons attacher notre librairie react que nous avons déclarer dans le fichier react_to_drupal.libraries.yml.
<?php

/**
 * @file
 * Contains \Drupal\react_to_drupal\Plugin\Block\ReactBlock.
 */

namespace Drupal\react_to_drupal\Plugin\Block;

use Drupal\Core\Block\BlockBase;

/**
 * Provides a block for ReactJs.
 *
 * @Block(
 *   id = "react_to_drupal_block",
 *   admin_label = @Translation("React Block")
 * )
 */
class ReactBlock extends BlockBase {

  public function build() {
    return [
      'name' => [
        '#markup' => '<div id="app"></div>',
      ],
      '#attached' => [
        'library' => [
          'react_to_drupal/react',
        ],
      ],
    ];
  }
}

 

Installation de Webpack

Installons webpack, webpack-cli et webpack command avec yarn global add webpack webpack-cli webpack-command --d, sans numéros de version a webpack pour avoir la dernière.

yarn add webpack webpack-cli webpack-command -D

Installation de Babel

Pour installer babel et ses dépendances, dans un terminal, runner cette commande :

yarn add babel-core babel-loader babel-preset-react babel-preset-stage-0 -D


Installons également quelques dépendances de Babel en mode -D (dev) qui nous permettra de gerer la compilation des fichiers js, jsx, css, scss et les images.
 

yarn add style-loader css-loader file-loader image-webpack-loader node-sass sass-loader -D

 

Installation de React

Installons react et react-dom :

yarn add react react-dom

Le squelette du dossier react

  • Le fichier /react_to_drupal/react/package.json

Yarn Init

Dans un terminal, placons-nous à la racine du module puis créons le dossier react dans lequel nous nous plaçons avec un cd react.

Initialisons notre projet avec yarn init.
yarn init lance le processus de création du fichier package.json.
Suivre la procédure système et finaliser la configuration du fichier package.json.

PS C:\Users\mm\Documents\tdb\workspace\REACT\react_to_drupal> yarn init
yarn init v1.7.0
question name (react_to_drupal): react_to_drupal
question version (1.0.0):
question description: Implement ReactJs in a custom module Drupal 8 with Webpack
question entry point (index.js):
question repository url:
question author:
question license (MIT):
question private:
success Saved package.json
Done in 71.30s.

 

  • le fichier /react_to_drupal/react/.babelrc

Configuration du fichier .babelrc

A la racine du dossier react, créer un fichier avec l'extension .babelrc avec ces lignes.
 

{
  "presets" : ["babel-preset-env", "react", "stage-0"]
}

 

  • le fichier /react_to_drupal/react/webpack.config.js

Configuration Webpack

Lançons la commande webpack pour nous apercevoir que la commande renvoie un message d'erreur, webpack demande le fichier webpack.config.js pour s'initialiser.
Créons ce fichier avec ces quelques lignes.


// Pour appeler la function __dirname qui renvoie la racine du dossier en cour
// Nous avons besoin de la class path fourni par nodeJs
var webpack = require('webpack');
var path = require('path');
// Créon des variables de nos chemins de nos dossiers
var BUILD_DIR = path.join(__dirname, 'dist');
var APP_DIR = path.join(__dirname, 'src');

var config = {
  // Le mode de compilation  "production" | "development" | "none"
  // Selon le mode, on active ou pas, les optimisation de production ou
  // les outils ou aide au développement
  mode: 'development',
  // L'entrée en string | object | array pour indiquer a webpack ou il doit commencer a travailler
  // ou où se situe les fichiers de notre application.
  // Les bonnes pratiques nous recommande de situer 
  // ces fichiers toujours a partir d'un dossier /src à la racine de notre projet. 
  entry: APP_DIR + '/app.js',
  // les options relatifs au dossier ou webpack va compiler les fichiers
  // pour un soucies des bonnes pratiques
  // considérons des a présent que ce dossier dist 
  // représente le dossier js d'un module drupal.
  output: {
    path: BUILD_DIR,
    filename: 'app.bundle.js'
  },
  // La logique des loader se deroule dans l'objet module
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: 'babel-loader'
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        use: 'file-loader'
      }
    ]
  }
}

 

Le dossier src de react

A la racine du dossier react créons un dossier src dans lequel nous plaçons deux fichiers,

 

  • le fichier /react_to_drupal/react/src/app.js
import React, { Component } from 'react';
import {render} from 'react-dom';

import './app.scss';

class App extends Component {
  render() {
    return (
      <div>
        <h2>hello Tribute to React, Yeah!</h2>
      </div>
    )
  }
}

render(<App/>, document.getElementById('app'));

 

  • et le fichier /react_to_drupal/react/src/app.scss
#app {
  color: blue;
}

 

et le fichier yarn.lock générer par yarn.

  • /react_to_drupal/react/yarn.lock

 

Résumé de nos fichiers

/ react_to_drupal
/ - react_to_drupal.info.yml
/ - react_to_drupal.librarie.yml
/ - react_to_drupal.module
/ - / src
/ - / - / Plugin
/ - / - / - / Block
/ - / - / - / - ReactBlock.php
/ - / react
/ - / - .babelrc
/ - / - package.json
/ - / - webpack.config.js
/ - / - yarn.lock
/ - / - node_modules
/ - / - / src
/ - / - / - app.js
/ - / - / - css.scss


Lançons webpack dans le terminal.
 

C:\Users\mm\Documents\tdb\workspace\drupal-react\drupal\web\modules\custom\react_to_drupal\react  (react_to_drupal@1.0.0)
λ webpack
Hash: 95116524067e238842f1
Version: webpack 4.16.0
Time: 1137ms
Built at: 2018-07-11 23:39:49
        Asset     Size  Chunks             Chunk Names
app.bundle.js  734 KiB    main  [emitted]  main
[./node_modules/css-loader/index.js!./node_modules/sass-loader/lib/loader.js!./src/app.scss] ./node_modules/css-loader!./node_modules/sass-loader/lib/loader.js!./src/app.scss 184 bytes {main} [built]
[./src/app.js] 2.32 KiB {main} [built]
[./src/app.scss] 1.17 KiB {main} [built]
    + 24 hidden modules


Si, comme moi, vous obtenez ce retour, c'est que webpack a compiler vos fichiers.
Dans le dossier react, un nouveau dossier dist à été créé avec le fichier app.bundle.js

/ react_to_drupal
/ - react_to_drupal.info.yml
/ - react_to_drupal.librarie.yml
/ - react_to_drupal.module
/ - / src
/ - / - / Plugin
/ - / - / - / Block
/ - / - / - / - ReactBlock.php
/ - / react
/ - / - .babelrc
/ - / - package.json
/ - / - webpack.config.js
/ - / - yarn.lock
/ - / - node_modules
/ - / - / src
/ - / - / - app.js
/ - / - / - css.scss
/ - / - dist
/ - / - / - app.bundle.js


Activons maintenant le module drupal, plaçons le block et contemplons le résultat.