Skip to main content

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 ^16.20.0 || ^18.16.0 || >=20.0.0.

We highly encourage you to use a newer version of Node.js (LTS v18) 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 7Babel 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.

babel.config.json
{
"plugins": ["@babel/transform-runtime", {
- corejs: 2
+ corejs: 3
}]
}

@babel/plugin-syntax-import-assertions

Please migrate to @babel/plugin-syntax-import-attributes (#15536). After you replace the plugin, you should search and replace the following patterns in your codebase:

input.js
- 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

Configuration Changes

@babel/core

medium

  • The root AMD/UMD/SystemJS options, namely moduleIds, getModuleId, moduleRoot, moduleId and filenameRelative 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.js
    module.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 config babel.config.js and specify options there.

@babel/preset-env

high

medium

  • includes and excludes respect renamed package names (#15576)

    Migration: If includes or excludes 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"]
    }
    ]]
    }

low

  • Remove uglify target (#12594)

    Migration: The uglify target had been deprecated since 7.0.0, if you still need this, use the forceAllTransforms option.

  • Removed syntax plugins can not be used in includes and excludes (#15810)

    Migration: You can safely remove them if you are using any of syntax plugins listed above in the includes and excludes options.

@babel/preset-react

medium

  • Remove useSpread and useBuiltIns options (#12593)

    Migration: Babel 8 always compiles JSX spread elements to object spread:

    <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 transpile Object.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 the useSpread option.

  • Type check input options (#12460)

    Migration: The preset will also report invalid option names. Refer to the docs and ensure valid usage.

low

  • Disallow filter option in automatic runtime (#15068)

    Migration: The filter option can only be used with the classic runtime. If you have switched to automatic runtime, you can safely remove this option. Otherwise please specify runtime: "classic".

@babel/preset-typescript

high

  • Remove isTSX and allExtensions options (#14955)

    Migration:

    • isTSX: true and allExtensions: 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, use ignoreExtensions: 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 to plugins.

    • isTSX: false and allExtensions: true

      Use ignoreExtensions: true, see the example above.

    • isTSX: false and allExtensions: false

      You can safely remove them.

medium

  • Remove allowDeclareFields option (#12461)

    Migration: Remove the option from your config, since it's now enabled by default. Previously allowDeclareFields enables transforming the declare 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 valid preset-typescript option and thus should be removed.

@babel/plugin-transform-typescript

medium

  • Remove allowDeclareFields option (#12461)

    Migration: Remove the option from your config.

@babel/plugin-syntax-typescript

high

  • Remove isTSX option (#14955)

    Migration: If you are using isTSX: true, remove this option and add @babel/plugin-syntax-jsx to plugins:

    {
    "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

medium

  • Remove allowDeclareFields option (#12457)

    Migration: Remove the option from your config, since it's now enabled by default. Previously allowDeclareFields enables transforming the declare syntax introduced in Flow 0.120.0, 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.

@babel/plugin-transform-flow-strip-types

medium

  • Remove allowDeclareFields option (#12457)

    Migration: Remove the option from your config. You will probably be fine with the new behaviour.

@babel/parser

low

  • Remove estree plugin option classFeatures (#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 the eslint-parser only works with ESLint 8 and above.

@babel/generator

medium

  • 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 the jsonCompatibleStrings option, you can replace it with jsescOption: { json: true }.

@babel/eslint-parser

medium

  • Remove allowImportExportEverywhere option (#13921)

    Migration: Use babelOptions.parserOpts.allowImportExportEverywhere instead.

    .eslintrc
    {
    "parser": "@babel/eslint-parser",
    "parserOptions": {
    - "allowImportExportEverywhere": true,
    + "babelOptions": {
    + "parserOpts": {
    + "allowImportExportEverywhere": true
    + }
    + }
    }
    }

low

  • parserOpts.allowSuperOutsideMethod defaults to false (#13921)

    Migration: If you want to restore to Babel 7 behaviour, set babelOptions.parserOpts.allowSuperOutsideMethod to true.

  • allowReturnOutsideFunction is inferred from ecmaFeatures.globalReturn (#13921)

    Migration: If you want to enable allowReturnOutsideFunction, set ecmaFeatures.globalReturn to true.

    .eslintrc
    {
    "parser": "@babel/eslint-parser",
    "parserOptions": {
    "ecmaFeatures": {
    "globalReturn": true
    }
    }
    }

@babel/plugin-transform-modules-systemjs

medium

  • Require @babel/plugin-transform-dynamic-import when transforming import() 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 and transform-modules-amd) require the separate plugin since it was introduced. We couldn't change it for transform-modules-systemjs because that package did already support dynamic import.

@babel/plugin-proposal-decorators

medium

  • Only support legacy and 2023-11. The plugin now requires a version 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 a version 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 the 2023-05 version regardless: both Babel 8 and TypeScript 5.0 support the 2023-05 version, while there are a few behaviour differences in the legacy version between Babel and tsc's implementation.

@babel/plugin-transform-runtime

low

  • The useESModules option has been removed (#16141)

    Migration: Delete it from your configuration. @babel/runtime will now automatically expose ES modules when needed, using package.json#exports.

@babel/node

low

  • 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.

Compilation Changes

Default target

medium

@babel/preset-env

low

  • 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

high

  • 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 of createElement (or the equivalent function in other libraries).

medium

low

  • Disallow sequence expressions inside JSX attributes (#12447)

    Migration: Find and replace the following code patterns. You can start the migration prior to Babel 8:

    - <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:

    - <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

high

  • 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 to undefined:

    class A {
    foo: string | void; // initialized to undefined
    declare bar: number; // type-only, will be removed
    }

Flow

high

  • 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 to undefined:

    class A {
    foo: string | void; // initialized to undefined
    declare bar: number; // type-only, will be removed
    }

Misc

low

  • 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 with utf-8 and your app will not be affected. The issue only affects if you are manually calling the babel.transform API and your web server is not serving js files in the utf8 encoding.

    Migration: Ensure your server is always serving js files in the utf8 encoding. If you can not control the server output, specify the charset attribute of the script 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
    }
    }
    }