Important
v7.0.0 is ESM-only, Encore.getWebpackConfig() is now async, Babel 8 is required, and CSS
minification is no longer enabled by default. These are real breaking changes, so please follow
the steps below.
The Node.js ecosystem has largely moved to ESM as the standard module format. Most actively maintained
packages now ship ESM-only, and since Encore already requires Node.js ^22.13.0 || >=24.0 (which has
full ESM support), continuing to publish as CJS would mean fighting the ecosystem: pinning to older
dependencies, adding workarounds, and missing out on tree-shaking and static analysis.
Moving to ESM also unlocks async/await in Encore's internals. Now that getWebpackConfig() is
natively async, Encore can adopt modern async APIs from the ecosystem without hacks.
-
Migrate from CommonJS to ESM: the package now requires
"type": "module"in your project or the use of.mjsfile extensions. Update yourwebpack.config.js:// Before (CJS) const Encore = require('@symfony/webpack-encore'); // ... module.exports = Encore.getWebpackConfig(); // After (ESM) import Encore from '@symfony/webpack-encore'; // ... export default await Encore.getWebpackConfig();
Note:
Encore.getWebpackConfig()is now async and returns aPromise. Useawaitat the top level of your webpack config (webpack supports async config files natively). -
If you prefer not to add
"type": "module", rename your webpack config towebpack.config.mjsinstead; webpack detects the.mjsextension and treats it as ESM automatically. -
Replace
__dirnameand__filenamewith their ESM equivalents in your webpack config:// Before (CJS) path.resolve(__dirname, 'src/utilities/'); config: [__filename]; // After (ESM) path.resolve(import.meta.dirname, 'src/utilities/'); config: [import.meta.filename];
-
Replace
require()calls in your webpack config withimportstatements:// Before (CJS) const path = require('path'); // After (ESM) import path from 'path';
Similarly,
require.resolve()becomesimport.meta.resolve():// Before (CJS) options.implementation = require.resolve('sass-embedded'); // After (ESM) import { fileURLToPath } from 'url'; options.implementation = fileURLToPath(import.meta.resolve('sass-embedded'));
If you need to require a CJS-only package, use
createRequire:import { createRequire } from 'module'; const require = createRequire(import.meta.url); const somePackage = require('cjs-only-package');
-
If you use StimulusBundle, update the
require.context()call in yourassets/stimulus_bootstrap.jsfile (previouslyassets/bootstrap.js) to webpack's ESM-friendlyimport.meta.webpackContext(), sincerequire.context()is not available in ESM modules:// Before (CJS) export const app = startStimulusApp( require.context( '@symfony/stimulus-bridge/lazy-controller-loader!./controllers', true, /\.[jt]sx?$/ ) ); // After (ESM) export const app = startStimulusApp( import.meta.webpackContext( '@symfony/stimulus-bridge/lazy-controller-loader!./controllers', { recursive: true, regExp: /\.[jt]sx?$/, } ) );
-
Config files using CJS syntax (
module.exports,require()) must be renamed to.cjsif your project has"type": "module"in itspackage.json, for example:postcss.config.js->postcss.config.cjsbabel.config.js->babel.config.cjs
Or, preferably, rewrite them as ESM:
// postcss.config.js (ESM) import autoprefixer from 'autoprefixer'; export default { plugins: [autoprefixer()], };
-
With
"type": "module", webpack enablesresolve.fullySpecifiedby default, so file extensions are now required in some imports that previously worked without them:- Relative imports:
import('./my-dependency')->import('./my-dependency.js') - Deep package imports from packages without an
"exports"field, for example:import delegate from 'licia/delegate'->import delegate from 'licia/delegate.js'import 'jquery-ui/ui/widgets/progressbar'->import 'jquery-ui/ui/widgets/progressbar.js'
- Relative imports:
-
The package
"exports"field is now restrictive: only"@symfony/webpack-encore"and"@symfony/webpack-encore/lib/plugins/plugin-priorities.js"are exposed as public entry points. Direct imports of other internal modules will no longer work. -
Drop support for Babel 7 and require Babel 8:
@babel/core,@babel/preset-env,@babel/preset-react,@babel/preset-typescript, and@babel/plugin-transform-react-jsxnow require^8.0.0. Upgrade your Babel dependencies and follow the migration guide. -
Raise the minimum Node.js version to
^22.18.0 || ^24.11.0 || >=26.0(required by Babel 8). -
Yarn Plug'n'Play users must upgrade to Yarn
>=4.6.0for proper resolution of ESM-only Babel 8 packages:yarn set version 4.6.0. -
The
useBuiltInsandcorejsoptions ofEncore.configureBabel()/Encore.configureBabelPresetEnv()are no longer supported: Babel 8 removed them from@babel/preset-env. Encore now throws an explicit error when they are set. To polyfill, usebabel-plugin-polyfill-corejs3viaEncore.configureBabel((babelConfig) => babelConfig.plugins.push(...))or an external Babel config. -
Without a
browserslistconfiguration, Babel 8's@babel/preset-envtargets modern browsers by default instead of compiling to ES5. Add abrowserslistconfiguration to your project to transpile for older browsers. -
The archived
css-minimizer-webpack-pluginandterser-webpack-pluginpackages have been replaced by the unifiedminimizer-webpack-plugin. Minifier packages (lightningcss,cssnano,csso,clean-css,esbuild,@swc/*,uglify-js) are now optional peer dependencies, installed on demand. In particularcssnano, previously pulled in transitively bycss-minimizer-webpack-plugin, is no longer installed by default. -
Encore.configureTerserPlugin()has been removed. UseEncore.configureJsMinimizerPlugin()instead (it takes the same callback). -
CSS minification is no longer enabled by default. Choose and configure a CSS minifier via
configureCssMinimizerPlugin(); otherwise CSS is not minified in production. The JS minimizer (Terser, bundled insideminimizer-webpack-plugin) still works with no extra setup.The
MinimizerPluginclass is passed as the second argument of the callback, so you don't need to importminimizer-webpack-pluginyourself (it would not resolve under pnpm, being a transitive dependency of Encore):// Lightning CSS, fast Rust-based minifier (npm install --save-dev lightningcss) Encore.configureCssMinimizerPlugin((options, MinimizerPlugin) => { options.minify = MinimizerPlugin.lightningCssMinify; }); // cssnano, PostCSS-based, closest to previous default (npm install --save-dev cssnano postcss) Encore.configureCssMinimizerPlugin((options, MinimizerPlugin) => { options.minify = MinimizerPlugin.cssnanoMinify; });
Other supported CSS minimizers:
csso,clean-css,esbuild(esbuildMinifyCss),@swc/css(swcMinifyCss). See the minimizer-webpack-plugin documentation for all available options.