From Encore to AssetMapper: Migrating a Symfony Frontend in Practice
AI generated
SF
{ }
Symfony · AssetMapper · Frontend Build
From Encore to AssetMapper
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.

19 min read Encore to AssetMapper · Importmap · Stimulus Symfony 7.x · PHP 8.4

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.

11. FAQ: Encore to AssetMapper

1Does migration need to happen in one step?
No, both systems can coexist during the transition period.
2Are CommonJS packages supported?
No, only native ES modules. CommonJS packages must be checked beforehand.
3What happens to Sass?
No built in compilation, either Tailwind instead of Sass or a standalone Sass script.
4Wiring in npm packages?
Through importmap:require, automatic download and entry in importmap.php.
5Still need Node.js in production deployment?
Only if Sass is still used. Otherwise Node.js disappears entirely from the build.
6Stimulus controller registration?
Through assets/controllers.json instead of Webpack's require.context.
7Is AssetMapper suitable for React?
Only to a limited extent, no JSX transformation. Encore or Vite remain the better choice.
8Checking ESM compatibility?
Through the module or exports fields in package.json, plus a test run with importmap:require.
9Still need Babel transpilation?
AssetMapper does not transpile, usually no longer needed with modern target browsers.
10How risky is the migration?
Low with step by step migration, since both systems can be tested in parallel.