Symfony Reprise : Webpack Encore prépare doucement sa retraite
Pendant des années, dès qu’un projet Symfony avait besoin d’un frontend un peu sérieux, la réponse était presque automatique : Webpack Encore. Quelques lignes dans webpack.config.js, un petit yarn encore dev et, après avoir téléchargé approximativement la moitié d’Internet dans node_modules, nous pouvions enfin afficher notre fichier CSS.
Mais l’écosystème JavaScript a beaucoup changé. Webpack n’a évidemment pas disparu, mais des outils comme Vite ou Rsbuild proposent aujourd’hui une expérience de développement beaucoup plus moderne, avec des configurations souvent plus simples et surtout des serveurs de développement extrêmement rapides.
Symfony devait donc choisir : continuer à faire évoluer Encore autour de Webpack ou changer complètement d’approche.
La réponse s’appelle Symfony Reprise.
Encore était surtout là pour dompter Webpack
Pour comprendre Reprise, il faut revenir quelques années en arrière. Webpack est extrêmement puissant, mais sa configuration n’a jamais vraiment eu la réputation d’être une activité relaxante du dimanche après-midi.
Compiler du Sass, gérer Babel, TypeScript, les fichiers statiques, les versions de production ou encore les source maps nécessitait rapidement une configuration conséquente.
Encore avait donc une excellente raison d’exister : fournir une abstraction plus agréable au-dessus de Webpack.
Encore
.setOutputPath('public/build/')
.setPublicPath('/build')
.addEntry('app', './assets/app.js')
.enableSassLoader()
.enableSourceMaps(!Encore.isProduction())
.enableVersioning(Encore.isProduction())
;
Pour un développeur Symfony, c’était infiniment plus sympathique que d’aller discuter directement avec les loaders et plugins de Webpack.
Le problème, c’est que les bundlers modernes ont justement supprimé une bonne partie de cette complexité. Vite sait déjà gérer énormément de choses avec très peu de configuration. Créer une énorme abstraction Symfony au-dessus de Vite reviendrait donc à inventer une télécommande pour contrôler une autre télécommande.
Symfony a choisi une approche beaucoup plus raisonnable.
Reprise n’est pas un bundler
C’est probablement le point le plus important : Symfony Reprise ne compile pas votre JavaScript.
Il ne cherche pas à remplacer Vite, Rsbuild ou Webpack. Son objectif est uniquement de créer une couche d’intégration standard entre Symfony et les bundlers modernes.
Schématiquement, avec Encore nous avions :
Symfony
↓
Webpack Encore
↓
Webpack
↓
CSS / JavaScript / assets
Avec Reprise, l’architecture devient plutôt :
Symfony
↓
Reprise
↓
Vite / Rsbuild
↓
CSS / JavaScript / assets
La différence peut sembler subtile, mais elle est importante. Reprise ne cherche pas à masquer le bundler. Il lui fournit simplement les conventions nécessaires pour communiquer correctement avec Symfony.
Alors, Reprise fait quoi exactement ?
Le bundler reste responsable de ce qu’il sait faire : compiler, transformer, optimiser et découper les assets.
Reprise s’occupe de la partie Symfony et notamment de :
- la génération de
entrypoints.json; - la génération de
manifest.json; - la gestion des fichiers avec hash pour le cache navigateur ;
- l’intégration avec Twig ;
- la connexion au serveur de développement du bundler ;
- le support du Hot Module Replacement ;
- l’intégration avec Symfony UX et Stimulus ;
- la copie et la gestion des images et des polices ;
- la gestion des CDN ;
- le support du Subresource Integrity (SRI).
En clair : Vite fait du Vite, Symfony fait du Symfony et Reprise s’assure que les deux se comprennent.
Conceptuellement, c’est beaucoup plus propre qu’une surcouche essayant de piloter entièrement l’outil frontend.
Côté Twig, pas besoin de réapprendre à marcher
Bonne nouvelle pour ceux qui utilisent Encore depuis des années : Symfony n’a pas décidé de profiter de l’occasion pour transformer deux fonctions Twig en une architecture hexagonale distribuée.
Avec Webpack Encore, nous avions généralement :
{{ encore_entry_link_tags('app') }}
{{ encore_entry_script_tags('app') }}
Avec Reprise :
{{ reprise_entry_link_tags('app') }}
{{ reprise_entry_script_tags('app') }}
Le fonctionnement reste donc extrêmement familier. On déclare un point d’entrée, le bundler produit les fichiers correspondants et Reprise fournit à Symfony les informations nécessaires pour retrouver les bons fichiers.
C’est notamment pour cela que Reprise conserve le principe des fichiers entrypoints.json et manifest.json déjà bien connu dans l’écosystème Encore.
Et le développement avec Vite ?
C’est probablement là que la nouvelle architecture devient la plus intéressante.
Avec un bundler moderne, le serveur de développement reste actif pendant que l’on travaille :
npm run dev
Vite peut alors servir directement les assets et utiliser le Hot Module Replacement. Une modification CSS ou JavaScript peut être répercutée immédiatement dans le navigateur sans reconstruire l’intégralité du projet.
Ce genre de fonctionnement existe évidemment depuis longtemps dans l’écosystème frontend, mais Reprise permet désormais à Symfony de l’intégrer proprement sans imposer Webpack comme intermédiaire.
Et quand vient le moment de préparer la production :
npm run build
Le bundler génère les fichiers optimisés, versionnés et prêts à être servis par le serveur web.
Simple. Presque suspect pour du JavaScript.
Webpack Encore est-il mort ?
Non. Et supprimer immédiatement tous les fichiers webpack.config.js de vos projets en production serait une manière particulièrement créative de commencer la journée.
Symfony place cependant désormais Webpack Encore en mode maintenance. Cela signifie que les bugs pourront continuer à être corrigés et les dépendances mises à jour, mais qu’il ne faut plus s’attendre à de grandes évolutions fonctionnelles.
Encore devient donc progressivement une technologie historique de l’écosystème Symfony : toujours utilisable, toujours maintenue, mais qui n’est plus vraiment la direction choisie pour l’avenir.
Pour un projet existant qui fonctionne correctement avec Encore, il n’existe aucune raison urgente de migrer. Un build stable qui tourne depuis plusieurs années possède une qualité extrêmement rare dans le monde JavaScript : il fonctionne déjà.
Et AssetMapper dans tout ça ?
L’arrivée de Reprise pourrait donner l’impression que Symfony revient vers Node.js après avoir beaucoup communiqué autour d’AssetMapper. En réalité, les deux outils ne répondent simplement pas au même besoin.
AssetMapper reste probablement le meilleur choix pour beaucoup d’applications Symfony classiques.
Avec AssetMapper, pas besoin de bundler JavaScript traditionnel ni nécessairement de Node.js. Symfony peut gérer directement les assets et utiliser les standards modernes du navigateur, notamment les modules ES et les import maps.
Pour une application composée principalement de Twig, Stimulus et quelques composants Symfony UX, c’est particulièrement séduisant.
Mais imaginons maintenant un frontend utilisant :
- TypeScript ;
- Sass avec une chaîne de compilation spécifique ;
- React ;
- Vue ;
- Svelte ;
- des transformations complexes ;
- un gros volume de JavaScript ;
- du code splitting avancé.
Dans ce cas, utiliser un véritable bundler reste parfaitement pertinent.
Le choix devient donc beaucoup plus lisible :
Frontend Symfony classique
↓
AssetMapper
Frontend nécessitant un bundler
↓
Reprise
↓
Vite / Rsbuild
Ce n’est donc pas vraiment AssetMapper contre Reprise. Ce sont deux solutions destinées à deux catégories de projets différentes.
Pourquoi Vite et Rsbuild ?
Reprise arrive initialement avec des intégrations pour Vite et Rsbuild, deux représentants de la génération actuelle d’outils frontend.
Vite est devenu extrêmement populaire grâce à son serveur de développement rapide et à sa configuration relativement légère. Rsbuild poursuit une philosophie comparable en s’appuyant sur l’écosystème Rspack.
Le point intéressant est surtout que Reprise n’est conceptuellement pas attaché à un bundler unique comme Encore pouvait l’être avec Webpack.
Symfony définit la couche d’intégration. Le monde JavaScript peut ensuite continuer sa grande tradition consistant à changer d’outil préféré tous les dix-huit mois sans obliger Symfony à reconstruire toute son architecture autour.
Un exemple d’architecture moderne
Sur un projet Symfony nécessitant réellement une chaîne frontend complète, on pourrait donc retrouver quelque chose comme :
Application Symfony
│
├── Controllers
├── Twig
├── Symfony UX
├── Stimulus
│
└── Reprise
│
└── Vite
├── TypeScript
├── Sass
├── React / Vue / Svelte
├── HMR
└── build production
Symfony n’essaie plus de contrôler toute la chaîne. Il définit simplement une frontière propre entre le backend et l’écosystème frontend.
Et finalement, c’est peut-être la partie la plus intéressante de Reprise : il fait volontairement moins de choses qu’Encore.
Faut-il utiliser Reprise dès maintenant ?
Il reste tout de même un détail important avant de remplacer Encore sur les 47 projets clients vendredi à 17 h 52 : Reprise est encore expérimental.
Le projet est actuellement en version 0.x et Symfony prévient que son API peut encore évoluer de manière significative.
Pour tester un nouveau projet, un prototype ou simplement découvrir l’intégration avec Vite, c’est donc très intéressant. Pour une application critique qui doit rester parfaitement stable pendant plusieurs années, attendre que l’API se stabilise est probablement une décision raisonnable.
Encore ne va pas s’autodétruire parce que Reprise existe.
Une évolution finalement assez logique
Reprise illustre surtout un changement de philosophie intéressant chez Symfony.
À l’époque d’Encore, Webpack était puissant mais suffisamment complexe pour justifier une abstraction complète. Aujourd’hui, les outils frontend modernes ont déjà énormément simplifié leur propre utilisation.
Symfony n’a donc plus besoin de construire un « Vite Encore » reproduisant exactement le même modèle.
Reprise préfère définir un contrat léger entre les deux mondes.
AssetMapper pour les projets qui n’ont pas besoin d’un bundler. Reprise pour ceux qui en ont réellement besoin. Et derrière Reprise, des outils modernes comme Vite ou Rsbuild qui restent libres de faire ce pour quoi ils ont été conçus.
Quant à Webpack Encore, il peut commencer à profiter tranquillement de sa préretraite. Il aura passé des années à nous éviter d’écrire nous-mêmes des configurations Webpack de 300 lignes, et rien que pour ça, il mérite probablement une médaille.
Ou au minimum qu’on ne supprime pas son webpack.config.js avant d’avoir vérifié que le nouveau build fonctionne.