DEV Community

Cover image for React dans Symfony avec Vite
Guillaume
Guillaume

Posted on

React dans Symfony avec Vite

Problème du jour : je veux me mettre à React, mais avec un backend Symfony.

Alors OK, vous allez me dire d'utiliser Webpack Encore et vous avez raison.... sauf que webpack est lent, surtout dans la phase de dev.

Donc l'idée est de trouver comment intégrer Vite à notre projet et comment configurer Vite pour faire marcher React.

Créons notre projet Symfony (6)

Rien de bien compliqué ici avec la CLI Symfony:

symfony new --webapp reactSymfonyProject

Intégrer Vite à mon projet Symfony

Heureusement, quelqu'un s'est penché sur le problème pour nous (même si le faire à la main n'aurait pas non plus été infaisable). Il y a donc un bundle pour ça !

Entrez dans le répertoire du projet et installez le bundle:

composer require pentatrion/vite-bundle

Voici le résultat de l'installation :

resultat installation du bundle

On va donc faire comme indiqué, en sautant la première étape - en bref on laisse les paramètres par défaut.
Si la deuxième vaut quand même le coup d'oeil (allez jeter un oeil au fichier vite.config.js comme indiqué), le fichier ne requiert aucune modification.

Suivez l'étape 3 et installez les dépendances Javascripts

yarn install (ou npm install)

Enfin, on va aller modifier notre template Twig de base pour aller chercher le résultat de la compilation de Vite.

Dans le fichier templates/base.html.twig, remplacez la ligne :
{{ encore_entry_link_tags('app') }}
par
{{ vite_entry_link_tags('app') }}

puis la ligne:
{{ encore_entry_script_tags('app') }}
par
{{ vite_entry_script_tags('app', { dependency: 'react' }) }}

 Création d'un contrôleur de test

A la racine du projet :

symfony console make:controller Test

On a maintenant une URL /test de disponible

 Premier test

On va démarrer tout ça et voir le résultat

D'abord on va démarrer le serveur PHP interne:
symfony serve -d

Puis on va compiler nos assets:
yarn dev

Rendez-vous maintenant dans votre navigateur à l'adresse :
https://127.0.0.1:8000/test

Note : le port 8000 peut différer sur votre installation. L'adresse est indiquée quand vous démarrez le serveur PHP.

Maintenant constatez le résultat en ouvrant la console Javascript (F12):

visualisation du résultat dans le navigateur

On voit ici qu'on retrouve bien le résultat de notre script assets/app.js et que Vite est bien démarré en mode dev.

Vous pouvez faire un test pour voir la puissance de Vite au regard de Webpack.

Ajouter à la fin du fichier assets/app.js n'importe quel console.log('plop'), et regardez le résultat apparaître dans la console instantanément, sans recharger la page du navigateur !

 OK pour Vite, mais pour React ?

Pour l'instant on est d'accord, Vite marche mais pas de React en vue (notez la blague React - Vue).

Il nous manque 2 choses : du code certes, mais aussi des dépendances.

Installons-les:

yarn add -D @vitejs/plugin-react @types/react @types/react-dom
yarn add react react-dom

Enter fullscreen mode Exit fullscreen mode

On va maintenant transformer notre Javascript et faire un peu de React.

Ouvrez le fichier assets/app.js et transformez-le comme suit:

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'

import "./app.css";

ReactDOM.createRoot(document.getElementById('root')).render(
    <React.StrictMode>
        <App />
    </React.StrictMode>,
)

Enter fullscreen mode Exit fullscreen mode

Comme vous le voyez, on va "rendre" notre application dans un element avec un ID "root".

On ne l'a pas pour le moment. Pour cela, on va modifier notre page de test (fichier templates/test/index.html.twig) comme suit:

{% extends 'base.html.twig' %}

{% block title %}Hello TestController!{% endblock %}

{% block body %}
<div id="root"></div>
{% endblock %}
Enter fullscreen mode Exit fullscreen mode

On va relancer Vite, et voir ce que ça donne....
A la racine du projet, relancez Vite;
yarn dev

Ouch, une grosse erreur apparaît et c'est bien normal :

Erreur de compilation

On a mis du JSX dans un fichier avec l'extension ".js".
Pour des raisons pratiques, on va renommer notre app.js en main.jsx

N'oublions pas non plus de modifier notre vite.config.js en pointant aussi vers le fichier main.jsx au lieu de app.js. On va aussi en profiter pour dire à Vite qu'on utilise son plugin React. Votre fichier vite.config.js doit donc ressembler à ça:

import { defineConfig } from "vite";
import symfonyPlugin from "vite-plugin-symfony";
import react from '@vitejs/plugin-react'


export default defineConfig({
    plugins: [
        react(),
        symfonyPlugin(),
    ],
    build: {
        rollupOptions: {
            input: {
                app: "./assets/main.jsx"
            },
        }
    },
});

Enter fullscreen mode Exit fullscreen mode

Relancez Vite, et constatez que vous avez une nouvelle erreur....normal, on a pas fini notre code ;)
On dit dans notre fichier main.jsx de rendre le composant "App" mais on ne l'a pas créé ! C'est aussi pour des raisons de conflit qu'on a renommé notre app.js en main.jsx et non en app.jsx.

Créez maintenant au même niveau que main.jsx un fichier App.jsx avec ce contenu :

import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from './images/vite.svg'

function App() {
  const [count, setCount] = useState(0)

  return (
    <div className="App">
      <div>
        <a href="https://vitejs.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://reactjs.org" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
        <p>
          Edit <code>assets/App.jsx</code> and save to test HMR
        </p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
    </div>
  )
}

export default App

Enter fullscreen mode Exit fullscreen mode

Note: vous trouverez les logos de React et Vite en SVG sur Internet ;)

Modifiez aussi le CSS de l'application (fichier assets/app.css) comme suit:

#root {
  max-width: 1280px;
  margin: 0 auto;
  padding: 2rem;
  text-align: center;
}

.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
  transition: filter 300ms;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
  filter: drop-shadow(0 0 2em #61dafbaa);
}

@keyframes logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: no-preference) {
  a:nth-of-type(2) .logo {
    animation: logo-spin infinite 20s linear;
  }
}

.card {
  padding: 2em;
}

.read-the-docs {
  color: #888;
}

Enter fullscreen mode Exit fullscreen mode

Et voilà, normalement, vous devriez avoir cette page qui apparait dans votre navigateur :

Capture résultat final

Top comments (0)