Upgrade to Babel 8
Refer users to this document when upgrading to Babel 8 from Babel 7. If you are a plugin developer or integration developer, please also check migration guide for integration.
If you are upgrading from Babel 6, please check here for Babel 7 migration guide.
All of Babel
Node.js support
All Babel 8 packages require Node.js ^18.20.0 || ^20.17.0 || >=22.8.0
.
We highly encourage you to use a newer version of Node.js (LTS v20) since the previous versions are not maintained. See nodejs/Release for more information.
This just means Babel itself won't run on older versions of Node. It can still output code that runs on old Node versions.
ESM only
Babel is now shipped in native ECMAScript modules. (#11701)
@babel/core
requirements
All presets and plugins require @babel/core@^8.0.0
as peer dependency.
@babel/eslint-parser
and @babel/eslint-plugin
The parser and plugin require eslint@^8.9.0
as peer dependency. (#15563)
Package Renames
The following packages has been renamed to -transform
as they have reached Stage 4 (#15614). The rename process has been landed in Babel 7.22 so you can start the migration prior to the upgrade.
Babel 7 | Babel 8 |
---|---|
@babel/plugin-proposal-async-generator-functions | @babel/plugin-transform-async-generator-functions |
@babel/plugin-proposal-class-properties | @babel/plugin-transform-class-properties |
@babel/plugin-proposal-class-static-block | @babel/plugin-transform-class-static-block |
@babel/plugin-proposal-duplicate-named-capturing-groups-regex | @babel/plugin-transform-duplicate-named-capturing-groups-regex |
@babel/plugin-proposal-dynamic-import | @babel/plugin-transform-dynamic-import |
@babel/plugin-proposal-export-namespace-from | @babel/plugin-transform-export-namespace-from |
@babel/plugin-proposal-json-strings | @babel/plugin-transform-json-strings |
@babel/plugin-proposal-logical-assignment-operators | @babel/plugin-transform-logical-assignment-operators |
@babel/plugin-proposal-nullish-coalescing-operator | @babel/plugin-transform-nullish-coalescing-operator |
@babel/plugin-proposal-numeric-separator | @babel/plugin-transform-numeric-separator |
@babel/plugin-proposal-object-rest-spread | @babel/plugin-transform-object-rest-spread |
@babel/plugin-proposal-optional-catch-binding | @babel/plugin-transform-optional-catch-binding |
@babel/plugin-proposal-optional-chaining | @babel/plugin-transform-optional-chaining |
@babel/plugin-proposal-private-methods | @babel/plugin-transform-private-methods |
@babel/plugin-proposal-private-property-in-object | @babel/plugin-transform-private-property-in-object |
@babel/plugin-proposal-unicode-property-regex | @babel/plugin-transform-unicode-property-regex |
Package Discontinued
@babel/runtime-corejs2
Please upgrade to @babel/runtime-corejs3
(#11751). After
you install the new runtime, please set the corejs
version to 3.
{
"plugins": ["@babel/transform-runtime", {
- corejs: 2
+ corejs: 3
}]
}
@babel/plugin-syntax-import-assertions
The proposal evolved into import attributes, which now Babel supports parsing by default. You can remove @babel/plugin-syntax-import-assertions
from your config, and replace the following patterns in your codebase:
- import value from "module" assert { type: "json" };
+ import value from "module" with { type: "json" };
Syntax plugins
The following syntax plugins are no longer needed, you can safely remove them from your config and node modules:
@babel/plugin-syntax-async-functions
@babel/plugin-syntax-async-generators
@babel/plugin-syntax-bigint
@babel/plugin-syntax-class-properties
@babel/plugin-syntax-class-static-block
@babel/plugin-syntax-dynamic-import
@babel/plugin-syntax-exponentiation-operator
@babel/plugin-syntax-export-extensions
@babel/plugin-syntax-export-namespace-from
@babel/plugin-syntax-import-meta
@babel/plugin-syntax-json-strings
@babel/plugin-syntax-logical-assignment-operators
@babel/plugin-syntax-module-string-names
@babel/plugin-syntax-nullish-coalescing-operator
@babel/plugin-syntax-numeric-separator
@babel/plugin-syntax-object-rest-spread
@babel/plugin-syntax-optional-catch-binding
@babel/plugin-syntax-optional-chaining
@babel/plugin-syntax-private-property-in-object
@babel/plugin-syntax-top-level-await
@babel/plugin-syntax-trailing-function-commas
@babel/plugin-syntax-unicode-sets-regex
The following plugins are discontinued and their functionality is not available anymore:
@babel/plugin-syntax-import-assertions
. Use@babel/plugin-syntax-import-attributes
instead, and see the@babel/parser
section for more information.
Configuration Changes
@babel/core
-
The root AMD/UMD/SystemJS options, namely
moduleIds
,getModuleId
,moduleRoot
,moduleId
andfilenameRelative
are moved to plugin options (#5473, #12724).Migration: Move these options to the module plugin, for example, if you are using
@babel/plugin-transform-modules-systemjs
:babel.config.jsmodule.exports = {
plugins: [
['@babel/plugin-transform-modules-systemjs', {
moduleIds: true,
moduleRoot: 'myApp',
getModuleId (name) {
return name + "suffix";
},
}],
],
};Adapt the example above if you are using
@babel/plugin-transform-modules-amd
or@babel/plugin-transform-modules-umd
. You can start the migration prior to Babel 8.0.If you are using
@babel/cli
and passing--module-ids
,--module-root
and--module-id
from command line, please create a Babel configbabel.config.js
and specify options there.
@babel/preset-env
-
The
loose
andspec
options have been removed (#16043)Migration: You can use the
assumptions
top-level option instead. See "Migrating from @babel/preset-env's "loose" and "spec" modes" for the ready-to-copy equivalent configuration.
-
includes
andexcludes
respect renamed package names (#15576)Migration: If
includes
orexcludes
contain any plugins mentioned in the Packages Renames section, change it to the new name. For example,babel.config.json{
"presets": [[
"@babel/preset-env",
{
- "includes": ["proposal-optional-chaining"]
+ "includes": ["transform-optional-chaining"]
}
]]
}
-
Remove
uglify
target (#12594)Migration: The
uglify
target had been deprecated since 7.0.0, if you still need this, use theforceAllTransforms
option. -
Removed syntax plugins can not be used in
includes
andexcludes
(#15810)Migration: You can safely remove them if you are using any of syntax plugins listed above in the
includes
andexcludes
options.
@babel/preset-react
-
Make the
development
option default to the configured env (#16927)Note that Babel's env, set through
envName
option, defaults toprocess.env.BABEL_ENV || process.env.NODE_ENV || "development"
: if you don't specify neither theenvName
option nor theBABEL_ENV
orNODE_ENV
environment variables, it will default todevelopment
.Migration: In production builds, set the
BABEL_ENV
orNODE_ENV
environment variables, or theenvName
Babel option, to"production"
. If you want to run only this preset in production mode, then you can explicitly set thedevelopment
option tofalse
.
-
Remove
useSpread
anduseBuiltIns
options (#12593)Migration: Babel 8 always compiles JSX spread elements to object spread:
input.jsx<div {...props}></div>
// transforms to
jsx("div", { ...props })If your app targets to modern browsers released after 2019, you can safely remove these options as object spread has less code footprint.
If your code needs to run in an environment which doesn't support object spread, you can either use
@babel/preset-env
(recommended) or@babel/plugin-transform-object-rest-spread
. If you want to transpileObject.assign
down, you also need to enable@babel/plugin-transform-object-assign
. In Babel 7.7.0, you can opt-in this behavior by using theuseSpread
option. -
Type check input options (#12460)
Migration: The preset will also report invalid option names. Refer to the docs and ensure valid usage.
-
Disallow
filter
option in automatic runtime (#15068)Migration: The
filter
option can only be used with theclassic
runtime. If you have switched toautomatic
runtime, you can safely remove this option. Otherwise please specifyruntime: "classic"
.
@babel/preset-typescript
-
Remove
isTSX
andallExtensions
options (#14955)Migration:
-
isTSX: true
andallExtensions: true
If you are already using
@babel/preset-react
,@babel/plugin-transform-react-jsx
or any other third-party jsx presets such as@vue/babel-preset-jsx
, and you want to transpile.tsx
files, you can safely remove these two options. Babel 8 will automatically handle.tsx
files using this preset and the other JSX plugin.babel.config.json{
"presets": [
["@babel/preset-react", { "runtime": "automatic" }],
- ["@babel/preset-typescript", { "allExtensions": true, "isTSX": true }]
+ ["@babel/preset-typescript"]
]
}If you want to transpile files other than
.tsx
, such as.vue
, useignoreExtensions: true
:babel.config.js{
overrides: [{
include: /\.vue$/,
presets: [
['@babel/preset-typescript', {
- allExtensions: true, isTSX: true
+ ignoreExtensions: true
}]
]
}]
}If you want to preserve the JSX format but transpile the TypeScript part, use
ignoreExtensions: true
and add@babel/plugin-syntax-jsx
toplugins
. -
isTSX: false
andallExtensions: true
Use
ignoreExtensions: true
, see the example above. -
isTSX: false
andallExtensions: false
You can safely remove them.
-
-
Remove
allowDeclareFields
option (#12461)Migration: Remove the option from your config, since it's now enabled by default. Previously
allowDeclareFields
enables transforming thedeclare
syntax introduced in TypeScript 3.7, in Babel 8 we support the syntax without such a flag. See also the compilation changes section. -
Type check input options (#12460)
Migration: The preset will also report invalid option names. Refer to the docs and ensure valid usage. For example,
runtime
is not a validpreset-typescript
option and thus should be removed.
@babel/plugin-transform-typescript
-
Remove
allowDeclareFields
option (#12461)Migration: Remove the option from your config.
@babel/plugin-syntax-typescript
-
Remove
isTSX
option (#14955)Migration: If you are using
isTSX: true
, remove this option and add@babel/plugin-syntax-jsx
toplugins
:{
"plugins": [
- ["@babel/plugin-syntax-typescript", { "isTSX": true }]
+ ["@babel/plugin-syntax-typescript"]
+ ["@babel/plugin-syntax-jsx"]
]
}If you are using
isTSX: false
, you can safely remove them.
@babel/preset-flow
-
Remove
allowDeclareFields
option (#12457)Migration: Remove the option from your config, since it's now enabled by default. Previously
allowDeclareFields
enables transforming thedeclare
syntax introduced in Flow 0.120.0, in Babel 8 we support the syntax without such a flag. See also the compilation changes section. -
Remove
enums
option (#16792)Migration: Remove the option from your config. The
enums
option was used to enable Flow enums, which are now supported by default. -
Type check input options (#12460)
Migration: The preset will also report invalid option names. Refer to the docs and ensure valid usage.
@babel/plugin-transform-flow-strip-types
-
Remove
allowDeclareFields
option (#12457)Migration: Remove the option from your config. You will probably be fine with the new behaviour.
-
Remove
enums
option (#16792)Migration: Remove the option from your config. The
enums
option was used to enable Flow enums, which are now supported by default.
@babel/parser
-
Remove
estree
plugin optionclassFeatures
(#13752)Migration: Remove the option from your config, since it's now enabled by default. Previously the
classFeatures
plugin enables@babel/parser
to produce class properties AST compatible with ESLint 8, following the ESTree specification. In Babel 8 theeslint-parser
only works with ESLint 8 and above.- Remove
decimal
plugin option #16741
Migration: Migrate your project to the latest proposal and remove the plugin from your config since the latest proposal doesn't have syntax anymore.
example.js- 1.03m
+ new Decimal("1.03")
- decimal1 + decimal2
+ decimal1.add(decimal2) - Remove
-
Remove
importAssertions
parser plugin (#16770)This plugin was for an old version of the import attributes proposal, using the
assert
keyword instead ofwith
. The proposal moved ahead without theassert
keyword.Migration: Replace the plugin with
importAttributes
. If you are still using theassert
keyword it's recommended that you migrate towith
: if it's not possible to do so, you can use the["importAttributes", { deprecatedAssertSyntax: true }]
option.` -
Remove
importReflection
parser plugin (#16808)The "import reflection" proposal does not exist anymore, and it was superseeded by the "source phase imports" proposal, which uses the
source
modifier for imports instead ofmodule
.Migration: Replace the plugin with
sourcePhaseImports
, and migrate your code to usesource
instead ofmodule
in import declarations.
@babel/generator
-
Remove
jsonCompatibleStrings
generator option (#9943, #12477)Migration:
@babel/generator
allows to specify options for jsesc, a library used to escape printed values. If you are using thejsonCompatibleStrings
option, you can replace it withjsescOption: { json: true }
.
@babel/eslint-parser
-
Remove
allowImportExportEverywhere
option (#13921)Migration: Use
babelOptions.parserOpts.allowImportExportEverywhere
instead..eslintrc{
"parser": "@babel/eslint-parser",
"parserOptions": {
- "allowImportExportEverywhere": true,
+ "babelOptions": {
+ "parserOpts": {
+ "allowImportExportEverywhere": true
+ }
+ }
}
}
-
parserOpts.allowSuperOutsideMethod
defaults tofalse
(#13921)Migration: If you want to restore to Babel 7 behaviour, set
babelOptions.parserOpts.allowSuperOutsideMethod
totrue
. -
allowReturnOutsideFunction
is inferred fromecmaFeatures.globalReturn
(#13921)Migration: If you want to enable
allowReturnOutsideFunction
, setecmaFeatures.globalReturn
totrue
..eslintrc{
"parser": "@babel/eslint-parser",
"parserOptions": {
"ecmaFeatures": {
"globalReturn": true
}
}
}
@babel/plugin-transform-modules-systemjs
-
Require
@babel/plugin-transform-dynamic-import
when transformingimport()
to SystemJS (#12700)Migration: Add
@babel/plugin-transform-dynamic-import
to your config: you can already do it in Babel 7. If you are using@babel/preset-env
, you don't need to do anything.babel.config.js.diff{
"plugins": [
+ "@babel/plugin-transform-dynamic-import",
"@babel/plugin-transform-modules-systemjs",
]
}Notes: All the other plugins which support dynamic import (
transform-modules-commonjs
andtransform-modules-amd
) require the separate plugin since it was introduced. We couldn't change it fortransform-modules-systemjs
because that package did already support dynamic import.
@babel/plugin-proposal-decorators
-
Only support
legacy
and2023-11
. The plugin now requires aversion
option (#12712, #15676)Migration: You should migrate to the latest version of the proposal
"2023-11"
, if you are using the"2018-09"
or you have not specified aversion
option.babel.config.json{
"plugins": [
["@babel/plugin-proposal-decorators", {
- "decoratorsBeforeExport": true,
- "version": "2018-09",
+ "version": "2023-11"
}]
]
}The syntax is the same, but you will need to rewrite your decorator functions. The spec repo provides comparison between the latest version and the
2018-09
version. You can already migrate since Babel 7.22.0, using the"version": "2023-05"
option of@babel/plugin-proposal-decorators
.Although Babel 8 still supports the
legacy
version, it is advisable to migrate to the2023-05
version regardless: both Babel 8 and TypeScript 5.0 support the2023-05
version, while there are a few behaviour differences in thelegacy
version between Babel andtsc
's implementation.
@babel/plugin-transform-runtime
-
The
corejs
option has been removed (#16311)Migration: To inject polyfills, you can use
babel-plugin-polyfill-corejs3
or babel-plugin-polyfill-corejs2 directly.
-
The
useESModules
option has been removed (#16141)Migration: Delete it from your configuration.
@babel/runtime
will now automatically expose ES modules when needed, usingpackage.json#exports
. -
The
runtime
andhelpers
options have been removed (#16311)Migration: Delete them from your configuration:
@babel/runtime
will now always import helpers. If you don't want to inject imports to helpers, remove@babel/plugin-transform-runtime
from your config.
@babel/node
-
The
-gc
and-d
command-line flags have been removed (#15956) Migration: Use the--expose-gc
and--inspect
Node.js flags respectively. Note that although-d
was short for--debug
, the latter has been deprecated since Node.js 7.7.0. -
Command-line flags for Node.js and Babel must now be passed before the filename, while flags for the script itself must be passed after. (#16706)
Compilation Changes
Default target
-
Use browserslist's
defaults
as default compilation target (#12989, #15551).Migration: If you are already using
targets
or have a.browserslist
config file, this change won't affect you. Otherwise, you'll probably be fine with the new behavior since the browserslist'sdefautls
covers most modern browsers.If you need to support legacy browsers, create a
.browserlist
config.
@babel/preset-env
-
Enable the
bugfixes
option by default (#13866)Migration: You will probably be fine with the new behaviour as Babel now tries to compile the broken syntax to the closest non-broken modern syntax supported by your target browsers. If anyhow you want to restore the Babel 7 behaviour, you can specify
bugfixes: false
.
JSX
-
Use the new JSX implementation by default (#12630)
Migration: If you are using a modern version of React or Preact, it should work without any configuration changes. Otherwise, you can pass the
runtime: "classic"
option to@babel/preset-react
or@babel/plugin-transform-react-jsx
to be explicit about your usage ofcreateElement
(or the equivalent function in other libraries).
-
Transforms JSX spread properties using object spread (#12593)
Migration: See the Configuration changes / preset-react section.
-
Disallow sequence expressions inside JSX attributes (#12447)
Migration: Find and replace the following code patterns. You can start the migration prior to Babel 8:
input.jsx- <p key={foo, bar}></p> // Invalid
+ <p key={(foo, bar)}></p> // Valid -
Disallow
{
,}
,<
and>
in JSX text (#12451)Migration: Use
{'{'}
,{'}'}
,{'<'}
and{'>'}
instead. Find and replace the following code patterns. You can start the migration prior to Babel 8:input.jsx- <p>">" is greater than.</p>
+ <p>"{'>'}" is greater than.</p>Notes: This is technically a spec compliance fix becase the JSX specification already forbids them. However, we have chosen to postpone it until Babel 8 because it could break someone's code.
TypeScript
-
Preserve uninitialized class fields (#12461)
Migration: Use the new
declare
syntax, introduced in TypeScript 3.7, if you don't want fields to be initialized toundefined
:input.tsclass A {
foo: string | void; // initialized to undefined
declare bar: number; // type-only, will be removed
}
Flow
-
Preserve uninitialized class fields (#12457)
Migration: Use the new
declare
syntax, introduced in Flow 0.120, if you don't want fields to be initialized toundefined
:input.jsclass A {
foo: string | void; // initialized to undefined
declare bar: number; // type-only, will be removed
}
Misc
-
Output non-ASCII characters as-is in string literal (#12675)
If you are using any one of
@babel/cli
, WebPack, Rollup, create-react-app or other Node.js powered bundlers, the transformed code is always encoded withutf-8
and your app will not be affected. The issue only affects if you are manually calling thebabel.transform
API and your web server is not serving js files in theutf8
encoding.Migration: Ensure your server is always serving js files in the
utf8
encoding. If you can not control the server output, specify thecharset
attribute of thescript
tag in the html files.<script charset="utf-8" src="your-app.js"></script>
You can also restore to the Babel 7 behaviour by
babel.config.js{
generatorOpts: {
jsescOption: {
minimal: false
}
}
}