Symfony Reprise : migrer un projet Symfony de Webpack Encore vers Vite ou Rsbuild
Annoncé le 31 juillet 2026, Symfony Reprise branche Vite ou Rsbuild sur une application Symfony à la place de Webpack Encore. Sur un projet existant : bascule Twig terme à terme, configuration de build qui disparaît en grande partie, pont Symfony UX préservé, rechargement à chaud en développement, et un statut 0.x qui impose de planifier plutôt que de basculer.
Sommaire(13 sections)
- Pourquoi la question se pose maintenant1
- Ce que Reprise branche, et ce qu'il laisse au bundler2
- Le projet qu'on prend comme fil rouge3
- L'installation : deux commandes, deux écosystèmes4
- Twig et configuration : un remplacement terme à terme5
- webpack.config.js : la partie qui disparaît6
- Stimulus, React et Vue : le pont Symfony UX survit7
- Le rechargement à chaud, le changement le plus visible au quotidien8
- Ce qui reste à la charge de l'équipe9
- Statut 0.x : un chantier à suivre, pas une bascule10
- Ce qu'on en retient chez Koul11
- Pour aller plus loin12
- Sources13
Un back-office Symfony en production depuis quatre ans. Quelques points d'entrée TypeScript, des feuilles de style Sass, une poignée de contrôleurs Stimulus pour les interactions, deux composants Vue sur les écrans les plus riches. Le tout assemblé par Webpack Encore, avec un webpack.config.js que plus personne n'ouvre parce qu'il fonctionne. À chaque montée de version, la même question revient : on garde cette chaîne de build, ou on la remplace par quoi ?
Le 31 juillet 2026, l'équipe Symfony a annoncé sur son blog officiel Symfony Reprise, une couche d'intégration entre Symfony et les bundlers JavaScript modernes. Elle vise exactement ce profil de projet. Reste à savoir ce que son adoption change vraiment sur une application déjà en production, et pourquoi le statut actuel du projet en fait un chantier à planifier plutôt qu'une bascule immédiate.
Pourquoi la question se pose maintenant
Webpack Encore n'est pas abandonné. L'annonce officielle le dit noir sur blanc : le projet continue de recevoir des correctifs de bugs ainsi que des mises à jour de dépendances et de pair-dépendances. Le paquet symfony/webpack-encore-bundle publie d'ailleurs toujours des versions, la 2.4.1 datant du 24 juin 2026 sur Packagist, le registre officiel des paquets PHP. Ce qui s'est arrêté, c'est le développement de nouvelles fonctionnalités : Encore est en mode maintenance, plus en développement actif.
Entre-temps, Symfony AssetMapper, la solution sans étape de build du framework, est devenue selon l'éditeur le choix par défaut d'une grande part des applications Symfony. Le raisonnement se tient tant que le projet n'a pas besoin d'un bundler. Mais un back-office avec du TypeScript, du Sass, du JSX ou des composants Vue en a besoin, et se retrouve donc sur un outil en maintenance. C'est cet angle mort que Reprise vient couvrir, avec une continuité de personne peu courante dans une succession d'outils : le projet est signé Hugo Alliaume (Kocal sur GitHub), membre de la Symfony UX Core Team, qui indique maintenir à la fois Symfony UX, Webpack Encore et Reprise. C'est lui qui avait ouvert, le 5 février 2025, la discussion publique sur l'avenir d'Encore face aux bundlers modernes, sur le dépôt officiel du framework.
Ce que Reprise branche, et ce qu'il laisse au bundler
Techniquement, Reprise est un couple : un bundle Symfony installé par Composer (symfony/reprise) et un plugin npm (@symfony/reprise), construit sur unplugin, une interface commune à plusieurs bundlers. Deux cibles sont documentées officiellement, Vite et Rsbuild, chacune avec sa section de configuration dans la documentation. Le tout est publié sous licence MIT.
Le périmètre est volontairement étroit, et l'annonce officielle ne laisse aucune ambiguïté là-dessus : les bundlers modernes gèrent déjà nativement Sass, Less, PostCSS, TypeScript, JSX, Vue, Svelte, le découpage de code, le hachage de contenu, les source maps, la minification et le rechargement à chaud, et ils le font bien. Reprise ne réimplémente rien de tout ça. Il apporte uniquement la glue côté Symfony : le rendu des points d'entrée dans Twig, la génération de entrypoints.json et manifest.json, le pont Symfony UX et Stimulus, le support d'un CDN et l'intégrité des ressources (SRI, en sha384 par défaut).
C'est une philosophie différente de celle d'Encore, qui enveloppait la configuration de Webpack derrière une API Symfony. Reprise ne réexpose pas la configuration du bundler : l'équipe travaille directement avec l'API de Vite ou de Rsbuild. Moins de couche intermédiaire, mais aussi moins d'abri.
Le projet qu'on prend comme fil rouge
Pour rendre la suite concrète, gardons le même scénario : une application Symfony existante, back-office ou outil métier, sous Encore depuis plusieurs années. Trois points d'entrée TypeScript, du Sass, une dizaine de contrôleurs Stimulus, deux composants Symfony UX Vue. Premier filtre, et il est brutal : les prérequis actuels du bundle sont PHP 8.4 ou supérieur et Symfony 7.4 ou 8.0, d'après les métadonnées publiées sur Packagist. Un projet resté sur Symfony 6.4 ou PHP 8.2 ne peut pas commencer par Reprise ; il commence par sa montée de version, qui est un chantier à part entière. C'est souvent la vraie question posée derrière « est-ce qu'on migre le build ? ».
Pour un projet déjà aligné sur Symfony 8 et une version récente de PHP, la migration se découpe en trois blocs bien séparés : la partie Symfony (configuration et templates), la partie build (le fichier de configuration du bundler) et la partie Symfony UX. Les trois n'ont pas du tout le même coût.
L'installation : deux commandes, deux écosystèmes
Côté PHP, on retire l'ancien bundle et on installe le nouveau. Côté JavaScript, on ajoute le plugin en dépendance de développement, plus le bundler cible s'il n'est pas déjà là.
composer remove symfony/webpack-encore-bundle
composer require symfony/reprise
npm install @symfony/reprise --save-dev
La recette Symfony Flex du bundle, fusionnée dans le dépôt officiel des recettes, prend en charge l'enregistrement et la configuration de base. À ce stade, l'application ne construit plus rien : c'est normal, il reste à écrire la configuration du bundler.
Twig et configuration : un remplacement terme à terme
C'est la partie qui rassure. La documentation officielle décrit la bascule des templates comme un remplacement direct, fonction pour fonction. Le préfixe change, la signature et l'usage restent identiques :
| Webpack Encore | Symfony Reprise |
|---|---|
encore_entry_link_tags('app') | reprise_entry_link_tags('app') |
encore_entry_script_tags('app') | reprise_entry_script_tags('app') |
encore_entry_css_files('app') | reprise_entry_css_files('app') |
encore_entry_js_files('app') | reprise_entry_js_files('app') |
encore_entry_exists('app') | reprise_entry_exists('app') |
Sur notre projet fil rouge, ça représente une recherche-remplacement dans les templates et une relecture des blocs stylesheets et javascripts. Rien à repenser. La configuration YAML du bundle suit la même logique : les clés se transposent quasiment à l'identique sous la racine reprise, y compris output_path, crossorigin, preload, cache, strict_mode, script_attributes et link_attributes. Les deux fichiers générés changent de producteur, Vite ou Rsbuild au lieu de Webpack, mais gardent exactement le même rôle : entrypoints.json pour que Twig sache quelles balises rendre, manifest.json pour résoudre chaque nom logique vers son URL avec hachage de contenu.
Autrement dit, le côté Symfony du projet bouge très peu. Pour une équipe backend, la courbe d'apprentissage reste faible.
webpack.config.js : la partie qui disparaît
L'essentiel de l'effort se déplace côté JavaScript, et il prend une forme inattendue : une bonne partie de l'ancienne configuration ne se traduit pas, elle se supprime. La documentation de migration liste les appels Encore qui n'ont tout simplement plus lieu d'être, parce que le bundler fait la même chose nativement.
enableSassLoader(),enableLessLoader(),enableStylusLoader(): on installe le préprocesseur et on importe le fichier.enablePostCssLoader(): unpostcss.config.jssuffit, il est repris automatiquement.enableTypeScriptLoader()etconfigureBabel(): transpilation native, par esbuild sous Vite et par SWC sous Rsbuild.splitEntryChunks(),enableSourceMaps(),cleanupOutputBeforeBuild(): comportements par défaut du bundler.configureImageRule(),configureFontRule(),addAliases(),addExternals(): gestion native des assets,resolve.alias, option d'externals du bundler.
Les presets framework changent simplement d'adresse : enableVueLoader() devient @vitejs/plugin-vue sous Vite ou @rsbuild/plugin-vue sous Rsbuild, et enableReactPreset() suit exactement la même logique. Sur notre fil rouge et ses deux composants Vue, c'est une ligne de configuration Encore échangée contre un plugin officiel du bundler.
Ce qui reste de spécifiquement Symfony devient une option du plugin : outputPath et publicPath, integrity pour les hachages d'intégrité, copy pour la copie de fichiers, stimulus pour le pont Symfony UX. Le versioning n'a même plus d'option, le hachage de contenu étant actif par défaut. Et configureDevServerOptions() ne correspond à rien non plus, puisqu'on lance directement le serveur de développement du bundler.
Le fichier d'arrivée tient en quelques lignes. Version Vite :
// vite.config.ts
import { defineConfig } from 'vite'
import Symfony from '@symfony/reprise/vite'
export default defineConfig({
build: {
// sur Vite 7 ou plus ancien, utiliser rollupOptions
rolldownOptions: {
input: { app: './assets/app.js' },
},
},
plugins: [Symfony({})],
})
Sur un projet réel, cette réécriture est le poste de travail principal. Elle est manuelle, mais elle produit un fichier nettement plus court que le webpack.config.js qu'il remplace, et surtout un fichier standard : un développeur front qui connaît Vite le lit sans avoir à apprendre une API spécifique à Symfony.
Stimulus, React et Vue : le pont Symfony UX survit
C'est le point qui inquiète le plus les équipes ayant investi dans Symfony UX, et la réponse est rassurante. Le pont Stimulus se reconfigure via une option du plugin pointant vers assets/controllers.json, et le point d'entrée appelle startStimulusApp() importé depuis @symfony/reprise/stimulus. La convention de nommage ne change pas : tout fichier assets/controllers/*_controller.js ou .ts est enregistré automatiquement, le nom de fichier devient l'identifiant, hello_controller.js donne hello et admin/user_controller.js donne admin--user. Les contrôleurs existants sont repris sans modification.
Pour les composants plus riches, Reprise supporte le Fast Refresh de React sous Vite depuis sa version 0.4. Les composants Symfony UX React et Symfony UX Vue s'utilisent dans une application Reprise et s'enregistrent de la même manière que les contrôleurs Stimulus, à partir des versions 3.4 de ces deux paquets, publiées le 25 juillet 2026 d'après Packagist. Une nuance pratique quand même : au moment de l'annonce, les recettes Symfony Flex de ces deux intégrations étaient encore en revue. Sur les deux composants Vue de notre fil rouge, il faut donc prévoir un câblage manuel plutôt qu'une installation automatique.
Le rechargement à chaud, le changement le plus visible au quotidien
C'est probablement ce que l'équipe front remarquera en premier, dès le premier jour. En développement, on ne lance plus une commande de build en mode surveillance : on démarre le serveur de développement du bundler, vite ou rsbuild dev. Reprise repointe alors entrypoints.json vers ce serveur et injecte le client de rechargement à chaud (HMR), si bien que reprise_entry_script_tags charge les modules directement depuis le processus en cours d'exécution.
La documentation résume l'effet en une phrase : on enregistre un fichier, le navigateur se met à jour sur place, sans reconstruction ni rechargement complet de la page. Sur un formulaire d'administration à moitié rempli ou un écran atteint après cinq clics, l'écart avec un rebuild suivi d'un rechargement complet se rejoue à chaque enregistrement de fichier. C'est le genre de gain qui ne se chiffre pas dans une note de version, mais qui se ressent immédiatement.
Ce qui reste à la charge de l'équipe
Reprise n'est pas un outil de migration automatique, et l'annonce officielle le précise elle-même. La réécriture de webpack.config.js vers vite.config.ts ou rsbuild.config.ts se fait à la main, projet par projet. Ce n'est pas anodin sur une configuration Encore qui a accumulé des réglages spécifiques au fil des années, même si beaucoup de ces lignes se suppriment au lieu de se traduire.
Trois patterns Encore n'ont par ailleurs aucun équivalent direct et doivent être repensés. Les variables globales injectées automatiquement (autoProvideVariables, autoProvidejQuery) sont à remplacer par de vrais imports, ce qui est une bonne pratique mais peut toucher beaucoup de fichiers sur un projet ancien. Les notifications de build et l'intégration ESLint sortent du build et deviennent des scripts séparés. Enfin, les branchements Encore.isProduction(), isDev() et when() se remplacent par un test sur le mode du bundler.
Dernière limite, plus structurelle : puisque Reprise ne réexpose pas la configuration du bundler, l'équipe doit apprendre l'API de Vite ou de Rsbuild directement. Sur un projet où la connaissance du build n'est pas partagée, c'est un point à traiter explicitement, avec de la documentation et du temps de montée en compétence, sinon on remplace une boîte noire par une autre.
Statut 0.x : un chantier à suivre, pas une bascule
Le calendrier est le facteur décisif, et il mérite d'être regardé froidement. Reprise est explicitement expérimental et toujours en 0.x, avec un avertissement officiel qui annonce des changements possibles, y compris importants, tant que la conception se stabilise. La cadence de publication le confirme : six versions du bundle entre le 13 juillet et le 4 août 2026, de la 0.1.0 à la 0.6.1, d'après l'historique Packagist. Ni l'annonce ni la documentation ne fixent de date pour une version 1.0.
En face, le blog officiel indique qu'à la version 0.6, publiée le 26 juillet 2026, Reprise a atteint une quasi-parité fonctionnelle avec Encore. Les deux informations ne se contredisent pas, elles disent deux choses différentes : le périmètre fonctionnel est là, la stabilité de l'API ne l'est pas encore.
Concrètement, pour une équipe qui envisage la migration aujourd'hui, ça veut dire traiter l'adoption comme un chantier suivi dans la durée : veille sur les publications, tests avant chaque montée de version, et de préférence un premier passage sur un module à faible enjeu avant de toucher à une application critique. Pas une bascule ponctuelle et définitive en production.
Ce qu'on en retient chez Koul
Sur les projets Symfony que notre équipe accompagne, que ce soit en reprise et modernisation d'un existant ou en développement web sur-mesure pour une nouvelle brique, la chaîne de build fait partie des premiers points regardés, parce qu'elle conditionne le confort de tous les développements suivants. Reprise coche plusieurs cases intéressantes : la surface de configuration à maintenir se réduit, le côté Symfony bouge à peine, et le pont Symfony UX est préservé. Le fait que le mainteneur de Reprise soit aussi celui d'Encore réduit le risque de rupture de vision fonctionnelle entre les deux outils.
Reste que la décision ne se prend pas sur la fiche technique. Elle dépend de la version de Symfony et de PHP déjà en place, du volume de configuration Encore accumulée, de la présence ou non de patterns sans équivalent direct, et de la tolérance du projet à une dépendance en 0.x. C'est typiquement ce qu'un audit et étude de cadrage tranche en quelques jours plutôt qu'en quelques réunions : état des lieux du build existant, estimation réelle de la réécriture, séquencement avec les autres chantiers techniques. Sur une application déjà suivie en maintenance applicative, ce type de migration se planifie très bien entre deux lots fonctionnels, une fois que le rythme des versions du projet sera retombé.
Pour aller plus loin
- Développement Symfony : notre approche des applications métier et des back-offices Symfony.
- Développement PHP : montées de version, dette technique et modernisation progressive.
- PHP 8.5, les nouveautés de la version majeure : utile quand le prérequis PHP 8.4 devient le vrai sujet.
- Symfony chez Veolia : ce que donne le framework sur une plateforme à grande échelle.
- Cloud et DevOps : intégration continue et déploiement, là où une nouvelle chaîne de build se branche vraiment.
Sources
- Introducing Symfony Reprise: the Symfony integration layer for modern bundlers (blog officiel Symfony, 31 juillet 2026)
- Symfony Reprise, documentation officielle du bundle (Symfony)
- symfony/reprise sur Packagist, registre officiel des paquets PHP (versions et prérequis)
- symfony/webpack-encore-bundle sur Packagist (statut de maintenance d'Encore)
- symfony/ux-react sur Packagist (version 3.4, 25 juillet 2026)
- symfony/ux-vue sur Packagist (version 3.4, 25 juillet 2026)
- symfony/reprise, dépôt officiel sur GitHub (licence MIT, avertissement expérimental)
- Discussion publique sur l'avenir de Webpack Encore, dépôt symfony/symfony (5 février 2025)
- Profil GitHub de Hugo Alliaume (Symfony UX Core Team, mainteneur d'Encore et de Reprise)
