Symfony Reprise: What Comes After Webpack Encore
Webpack Encore is in maintenance mode. Symfony Reprise wires Vite and Rsbuild into Symfony instead, with a near tag-for-tag Twig swap.
Webpack Encore has been the default answer to “how do I get a real front-end build in Symfony” for years. On July 31, 2026, Symfony core contributor Hugo Alliaume published the announcement that changes that answer: Symfony Reprise, a new integration layer that wires Vite and Rsbuild into Symfony instead of Webpack. Encore isn’t being deleted or abandoned, but it has stopped receiving new feature work. If you’re starting a Symfony project today that needs an actual bundler, Reprise is the path the Symfony team wants you on.
Why Encore needed a successor
Encore existed to hide Webpack’s configuration behind a friendly PHP-flavored API: enableSassLoader(), enableTypeScriptLoader(), and a dozen siblings, because Webpack needed every one of those loaders wired up by hand. That was genuinely useful in 2018. It’s much less useful now that Vite, Rsbuild, esbuild, and Rolldown handle TypeScript, JSX, Sass, and Vue natively, with close to zero configuration and dev servers that start in a blink instead of several seconds.
Meanwhile, Symfony AssetMapper picked off the no-build-step crowd, and it has become the default for a large share of Symfony apps that don’t need a bundler at all. That left a gap for everyone in between: teams that genuinely need TypeScript, JSX, Vue, or Svelte, and a real test runner and formatter alongside it, but didn’t want to keep building on top of aging Webpack tooling. The reasoning played out publicly in the Symfony team’s RFC, “The future of Webpack Encore”: rather than keep reinventing JavaScript tooling inside PHP land, lean on the bundlers that already do it well and ship a thin, official Symfony integration on top.
Reprise is that integration.
What Reprise actually does
Reprise ships as two packages that work together: symfony/reprise on Composer (the PHP-side RepriseBundle) and @symfony/reprise on npm (the JavaScript side, built on unplugin so one codebase runs on both Vite and Rsbuild). Deliberately, it does not touch what the bundlers already handle well. Sass, TypeScript, JSX, code splitting, content hashing, source maps, minification, and HMR are all native to Vite and Rsbuild. Reprise’s job stops at the Symfony-specific glue those bundlers leave out: generating an Encore-compatible entrypoints.json and manifest.json, rendering the <script>/<link> tags in Twig, pointing Twig at the dev server for HMR, Stimulus controller registration, CDN public paths, and Subresource Integrity hashes.
Installation is two commands:
composer require symfony/reprise
npm install @symfony/reprise --save-dev
Vite configuration:
// vite.config.ts
import { defineConfig } from 'vite'
import Symfony from '@symfony/reprise/vite'
export default defineConfig({
build: {
rolldownOptions: {
input: {
app: './assets/app.ts',
},
},
},
plugins: [
Symfony({
// options
}),
],
})
Rsbuild configuration is nearly identical, just swapping the entry point shape:
// rsbuild.config.ts
import { defineConfig } from '@rsbuild/core'
import Symfony from '@symfony/reprise/rsbuild'
export default defineConfig({
source: {
entry: {
app: './assets/app.ts',
},
},
plugins: [
Symfony({
// options
}),
],
})
Once entrypoints.json exists, rendering it in Twig is one call per tag type, and this is the part that should feel immediately familiar if you’ve used Encore:
{{ reprise_entry_link_tags('app') }}
{{ reprise_entry_script_tags('app') }}
That’s a near tag-for-tag swap for Encore’s encore_entry_link_tags and encore_entry_script_tags. Start the dev server (vite or rsbuild dev) and those same tags repoint themselves at it and inject the HMR client, so saving a file updates the browser in place. Run a production build instead, and the tags resolve to the hashed files on disk. There’s no webpack-dev-server glue to babysit; the dev server is native to whichever bundler you picked, so it starts instantly.
Where Reprise draws the line
It’s worth being precise about what Reprise is not, because it’s easy to assume it’s a drop-in Encore replacement in every sense. It is not a bundler; Vite and Rsbuild do the actual build work. It is not a config wrapper the way Encore was, so you configure Sass, TypeScript, and everything else the native bundler way, not through a Reprise-specific API. And it’s not competing with AssetMapper. AssetMapper stays the right default for apps that want zero build step and no Node.js at all. But that tradeoff means no Vitest, no Playwright, no Vue or React without extra tooling. AssetMapper apps that need those things today stack single-purpose bundles like AssetMapperTypeScriptBundle, SymfonyCasts’ sass-bundle, or tailwind-bundle, one PHP package per JavaScript concern. Reprise is for the point where that stack gets unwieldy and a real bundler earns its keep.
Running Reprise means running Node and installing npm packages. That’s presented as the point, not a compromise: modern bundlers are Node tools, and Reprise leans into that ecosystem rather than hiding it behind a PHP-shaped wrapper.
Migrating from Encore
As of version 0.6.0, released July 26, 2026, Reprise reached near feature-parity with Encore on both Vite and Rsbuild: entrypoints and manifest generation, asset versioning, integrity hashes, file copy, the Stimulus bridge, dev server and HMR, CDN public paths, multiple builds, and per-call tag attributes are all covered. That release also shipped an official “Migrating from Webpack Encore” guide that maps every Encore.* call to its Vite, Rsbuild, or Reprise equivalent, and quite a few of those calls simply disappear because the bundler already does natively what Encore had to configure by hand. Bundle configuration carries over almost key-for-key, too: webpack_encore.output_path becomes reprise.output_path, for example.
There’s no automated migration tool, though. The Twig templates barely change, but webpack.config.js has to be hand-rewritten into vite.config.ts or rsbuild.config.ts.
Where this stands today
Reprise is explicit about its own maturity: it’s still 0.x and the project describes itself as experimental, warning that the configuration API could still change, “possibly drastically,” before a stable release. The bundlers underneath are mature and stable; it’s the Symfony-side glue that’s young. A Symfony Flex recipe for Reprise merged into symfony/recipes alongside an updated StimulusBundle recipe, EasyAdminBundle already supports rendering Reprise assets alongside its existing Encore support, and Symfony UX is extending past Stimulus into this world too. Version 0.5.0 added React HMR support under Vite, and current UX React and UX Vue releases let you register React and Vue components the same way you’d register a Stimulus controller, though the Flex recipes wiring that up automatically are still in review.
If you’re maintaining an Encore project today, nothing forces your hand. Encore keeps getting bug fixes and dependency updates. But if you’re reaching for a bundler on a new Symfony app, or you’ve been feeling the friction of stacking AssetMapper bundles for TypeScript and Sass, Reprise on Vite is worth a spin on a side project before you commit anything production-critical to it. Watch the GitHub repository for release notes; a project this candid about its own 0.x status is one where the API is still genuinely moving.