a Symfony frontend migration in practice
Migrating Encore to AssetMapper does not mean rewriting the frontend, it means moving entrypoints, npm packages and Sass files piece by piece onto Symfony's built in importmap mechanism, until Node.js is no longer strictly required for the production build.
Table of Contents
- 1. Why migrate from Encore to AssetMapper at all
- 2. Taking stock: what Encore currently handles
- 3. Installing AssetMapper, keeping Encore for now
- 4. Replacing entrypoints one by one
- 5. Moving npm packages to the importmap
- 6. Retiring Sass: PostCSS and Tailwind instead of Webpack loaders
- 7. Running Stimulus controllers without a build step
- 8. Production deployment without Node.js
- 9. Encore and AssetMapper compared directly
- 10. Summary
- 11. FAQ
1. Why migrate from Encore to AssetMapper at all
The move from Encore to AssetMapper is rarely a spontaneous decision, it is usually the result of growing frustration with build times, Node version conflicts and the complexity of a Webpack configuration that has grown over years. Symfony AssetMapper takes a fundamentally different approach: instead of bundling and transpiling modules, it serves JavaScript modules directly as ES modules over HTTP/2 and relies on native browser capabilities like importmaps, which are by now supported by every relevant browser.
The switch from Encore to AssetMapper pays off especially for projects that do not use React, Vue or TypeScript with complex type transformation on the frontend, but instead rely on Stimulus, vanilla JS and Tailwind. In that scenario, Webpack practically adds no more value, only extra build time and one more toolchain to maintain. Projects with genuine build requirements such as JSX compilation or complex tree shaking over npm packages with CommonJS exports still benefit from Encore or a dedicated Vite setup.
An important point for the decision to move from Encore to AssetMapper: the migration does not have to happen in a single step. Both systems can coexist in the same project during the transition period, which considerably reduces the risk of a big bang cutover.
2. Taking stock: what Encore currently handles
Before the migration from Encore to AssetMapper begins, it is worth taking an honest inventory of the webpack.config.js. Most projects use Encore for four things: bundling several JavaScript files into entrypoints, compiling Sass or Less to CSS, transpiling modern JavaScript for older browsers through Babel, and versioning plus cache busting of the shipped files through hashes in the filename.
AssetMapper natively covers versioning and cache busting, as well as plain delivery of JavaScript modules without transpilation. What AssetMapper does not bring along is Babel style transpilation for very old browsers, and no native Sass compilation. These gaps must either be closed with external CLI tools, or the requirement simply disappears because modern browsers already natively support the needed JavaScript features.
# Audit: what does the existing Encore config actually do?
grep -E "addEntry|enableSassLoader|enablePostCssLoader|configureBabel" webpack.config.js
# List all npm packages actually imported in JS entrypoints
grep -rhoE "from ['\"][a-zA-Z@][^'\"]*['\"]" assets/ | sort -u
3. Installing AssetMapper, keeping Encore for now
The safe entry point into Encore to AssetMapper is a parallel installation. AssetMapper gets installed as an additional bundle while Encore keeps handling the existing entrypoints. Symfony lets you keep rendering templates with encore_entry_script_tags() for legacy sections while using importmap() for already migrated templates. Both functions can coexist in the same layout, as long as they do not claim the same global variables or DOM IDs.
This coexistence is the core of a low risk migration strategy for Encore to AssetMapper: instead of switching every page over in a single day, migration happens page by page, section by section, with the option to roll back at any time if a migrated module causes unexpected trouble.
# Install AssetMapper alongside the existing Encore setup
composer require symfony/asset-mapper symfony/asset symfony/stimulus-bundle
# AssetMapper needs its own directory structure
bin/console debug:asset-map
4. Replacing entrypoints one by one
Every Encore entrypoint corresponds in AssetMapper to its own importmap entry file, registered through bin/console importmap:require. The difference: instead of a bundled package with all dependencies inlined, the browser fetches each module as a separate file, addressed through the generated importmap in the <head>. For the migration from Encore to AssetMapper, that means checking every import statement in existing JavaScript code for ES module compatibility, since AssetMapper does not support CommonJS.
In practice, migrating an entrypoint proceeds as follows: the file is first copied unchanged into assets/, then every require() call is rewritten as an import statement, and finally the template is switched from encore_entry_script_tags() to importmap(). For Stimulus controllers, symfony/stimulus-bundle handles automatic registration, so in most cases no manual import code is needed anymore.
// Before (Encore, CommonJS-style require still common in older configs)
const Sortable = require('sortablejs');
// After (AssetMapper, native ES module import)
import Sortable from 'sortablejs';
// Stimulus controllers are auto-discovered via symfony/stimulus-bundle
// assets/controllers.json lists every registered controller and its enabled state
5. Moving npm packages to the importmap
The most time consuming part of migrating Encore to AssetMapper is usually moving npm packages. By default, AssetMapper downloads packages through jsdelivr.com as a CDN proxy for npm modules and stores them locally in the assets' vendor directory, so no external request is needed at runtime anymore. The importmap:require command handles resolution, download and registration in importmap.php automatically.
Not every npm package is suited for this path. Packages that internally rely on CommonJS require calls or Node.js specific APIs such as fs or path do not work as a pure ES module in the browser. For the migration from Encore to AssetMapper, this means checking libraries for ESM compatibility beforehand, ideally through the "module" or "exports" fields of the respective package.json.
# Migrate npm packages one by one to the importmap
bin/console importmap:require sortablejs
bin/console importmap:require chart.js
bin/console importmap:require @hotwired/stimulus
# Verify the resulting entries
cat importmap.php
6. Retiring Sass: PostCSS and Tailwind instead of Webpack loaders
Since AssetMapper does not ship a Sass compiler, the CSS side of migrating Encore to AssetMapper is often the part with the biggest structural change. Projects that already use Tailwind CSS have it easy: the standalone Tailwind CLI build runs completely independently of Encore or AssetMapper and only needs to keep running as a package.json script. Projects with extensive Sass structures full of mixins and variables must either switch to native CSS with custom properties or run a standalone Sass compiler outside of Symfony.
A pragmatic intermediate step when migrating Encore to AssetMapper: the Sass compiler stays around as a standalone npm script and continues to produce a compiled CSS file, which is then delivered like any other static file through AssetMapper. In this case AssetMapper only handles delivery and versioning, not the actual Sass compilation.
7. Running Stimulus controllers without a build step
Stimulus controllers are the ideal case for Encore to AssetMapper, because they are usually already written as pure ES modules and need no complex build transformation. After the migration, symfony/stimulus-bundle automatically registers every controller through the assets/controllers.json file, something Encore projects usually never had in this form, because Encore solved registration through bootstrap.js and Webpack's context import mechanism.
For teams that previously used require.context() to automatically collect all controller files, the switch from Encore to AssetMapper is actually an improvement: the explicit list in controllers.json makes it visible which controllers are active, and allows disabling individual controllers per environment without deleting code.
{
"controllers": {
"@symfony/ux-dropzone": {
"dropzone": { "enabled": true, "fetch": "eager" }
},
"app": {
"sortable": {
"enabled": true,
"fetch": "lazy",
"autoimport": { "sortablejs/modular/sortable.core.esm.js": true }
}
}
},
"entrypoints": []
}
8. Production deployment without Node.js
An often underestimated benefit of migrating Encore to AssetMapper: once Sass compilation is no longer needed, Node.js disappears entirely as a build dependency in production deployment. bin/console asset-map:compile handles versioning and copying every asset into public/assets, entirely through PHP, without an npm install or yarn build ever running in the deployment script.
That considerably reduces the attack surface for supply chain issues through npm dependencies in the production build, because at runtime only the actually used, already downloaded vendor files sit in the repository. For deployment pipelines using Deployer or similar tools, the build step for Encore to AssetMapper shrinks noticeably, since the time consuming Webpack compilation step disappears entirely.
Another aspect that is frequently underestimated when migrating Encore to AssetMapper is the impact on local development time. Without a Webpack dev server, the initial compilation on first starting the development server disappears too, every change to a JavaScript file becomes visible on the next browser reload without waiting for a rebuild. For teams with many small frontend iterations, this saved waiting time adds up noticeably over the course of a workday.
9. Encore and AssetMapper compared directly
The decision between the two systems depends heavily on the scope of existing frontend requirements. The following overview summarizes the most important differences to consider when migrating Encore to AssetMapper.
| Aspect | Webpack Encore | Symfony AssetMapper |
|---|---|---|
| Node.js needed in production build | Yes | No (without Sass) |
| CommonJS packages supported | Yes | No, ESM only |
| Sass/Less compilation built in | Yes | No |
| Build time on large projects | Grows with project size | No classic build |
| JSX / TypeScript transformation | Yes | No |
For React or Vue heavy frontends with JSX compilation, Encore or a dedicated Vite setup remains the better fit. For Stimulus based, server rendered Symfony applications with Tailwind, Encore to AssetMapper is in most cases a clear win in simplicity and build speed.
Mironsoft
Symfony frontend migrations without downtime
Encore build too slow, Node version chaos in deployment?
We migrate existing Symfony projects step by step from Encore to AssetMapper, check npm packages for ESM compatibility, and cleanly replace Sass with Tailwind.
Migration audit
Analyzing the existing Encore configuration and npm packages
Step by step migration
Moving entrypoint by entrypoint to AssetMapper, without big bang risk
Deployment optimization
Removing Node.js from the production deployment
One last practical tip worth keeping in mind throughout the whole Encore to AssetMapper effort: keep a rollback path open for every migrated area until it has run in production for at least one full release cycle, since some edge cases in browser importmap support only surface under real traffic patterns.
10. Summary
Migrating Encore to AssetMapper is not a rewrite, it is a step by step move that can also run alongside Encore during the transition period. Entrypoints are switched over individually, npm packages are checked for ESM compatibility and wired in through the importmap, and Sass is either replaced with native CSS plus Tailwind or kept running as a standalone build script. Stimulus controllers benefit the most from the migration, because their registration through controllers.json becomes more transparent than through Webpack's context import.
For projects with no JSX or TypeScript transformation needs, Node.js disappears entirely as a production build dependency by the end of migrating Encore to AssetMapper, which shortens deployment times and reduces the attack surface for supply chain risks. Anyone who still needs complex Sass structures or JSX compilation should keep Encore for those parts for now and migrate only the simpler areas.
Encore to AssetMapper — The essentials at a glance
Parallel operation
Encore and AssetMapper can coexist in the same project during migration.
ESM required
Only pure ES modules work, CommonJS packages must be checked beforehand.
Sass gap
No built in Sass compilation, replace it with Tailwind or a standalone Sass script.
Deployment win
Node.js disappears from the production build, shorter deployment times.