After 8 years since Babel 7, Babel 8 is here — and it's a modernization release, not a feature drop. ESM-only packages, TypeScript types for everything, and updated defaults that reflect the modern JavaScript ecosystem. Here's exactly what changed and how to migrate your project.
On June 16, 2026, the Babel team released Babel 8.0.0 — the first major version bump in 8 years. This is not a feature release. Babel 8 contains no new transforms, no new parser features, and no new proposals over what Babel 7 already supports. Instead, it's a modernization release that cleans up 8 years of accumulated technical debt and pushes the JavaScript ecosystem forward.
Babel's usage has exploded over the past 8 years: from 1.7 million weekly downloads
in 2018 to 651 million weekly downloads in June 2026. With that scale comes enormous
responsibility — even minor breaking changes can block hundreds of thousands of developers. The Babel team
has taken an exceptionally careful approach, with a long beta period (the first alpha was published in 2023)
and a multi-year deprecation cycle for changes like the loose option.
Here's what Babel 8 changes compared to Babel 7:
@types/babel__* packages needed.@babel/preset-env defaults to Browserslist defaults (~ES2023).loose and spec removed from preset-env, deprecated in plugins. Use assumptions instead.corejs/useBuiltIns replaced by babel-plugin-polyfill-corejs3.Below I'll walk through each change in detail, with migration steps and code examples.
The biggest structural change in Babel 8 is that all Babel packages now ship as ES modules only.
This applies to @babel/core, @babel/preset-env, @babel/parser,
@babel/cli, and every other official package.
Why? With require(esm) now supported in all active LTS versions of Node.js, the ESM-only change
is a natural step. It lets the Babel team modernize their own codebase, reduce package sizes, and simplify
their build pipeline — while not breaking projects that still use CommonJS in application code.
If you use Babel programmatically (e.g., require('@babel/core') in a CommonJS file), you have
two options:
"type": "module" to your package.json
and use import instead of require().import() in CommonJS files — const babel = await import('@babel/core').
This works in all currently supported Node.js versions.// Before (Babel 7, CJS):
const babel = require('@babel/core');
babel.transformSync(code, options);
// After (Babel 8, async import in CJS):
const babel = await import('@babel/core');
const result = await babel.transformAsync(code, options);
// After (Babel 8, ESM project):
import * as babel from '@babel/core';
const result = await babel.transformAsync(code, options);
Note: If you only use Babel through your build tool (webpack, Vite, or a framework like Next.js), the bundler or framework handles this internally. You probably don't need to change anything.
Babel 8 requires Node.js 22, 24, 26, or newer. Node.js 20 and 25 reached end-of-life earlier in 2026 and will not receive further security fixes. If you're still on an older Node.js version, upgrade first, then migrate to Babel 8.
Babel 8 ships first-party TypeScript type definitions (.d.ts files) for every
official Babel package. This means you no longer need to install @types/babel__* packages
from DefinitelyTyped — the types come directly from the Babel source, so they're always in sync with the code.
// Before — needed separate types:
npm install @babel/core @types/babel__core
// After — types ship with the package:
npm install @babel/core
// Types are included — use them directly:
import { transformAsync, TransformOptions } from '@babel/core';
This is a quality-of-life improvement for TypeScript users. The Babel team has been maintaining their own types internally for years, and now they're shipping them to users. The types cover the full public API: core, parser, generators, preset-env, and all official plugins and presets.
This is the change that will affect the most projects. In Babel 7, @babel/preset-env
defaulted to compiling everything down to ES5 — the level of Internet Explorer 11.
In Babel 8, preset-env defaults to Browserslist defaults, which currently targets
approximately ES2023.
What this means in practice: less code is compiled away. Features like async/await,
class syntax, arrow functions, for...of, and template literals are no longer
downleveled by default. Your bundles get smaller and your build times get faster.
// Babel 7 default: compiles everything to ES5
// Babel 8 default: uses browserslist defaults (~2% market share)
// If you still need ES5 support, set targets explicitly:
// babel.config.json
{
"presets": [
["@babel/preset-env", {
"targets": "> 0.25%, ie 11"
}]
]
}
Similarly, @babel/preset-env now outputs ES modules by default instead of
CommonJS. This aligns with modern bundlers and runtimes. If you need CommonJS output, you can set
sourceType: "commonjs" in your config (this option was added in Babel 7.28).
Migration tip: Before upgrading to Babel 8, build your project with
targets: "defaults" (which is what browserslist defaults resolves to) while still on
Babel 7. Verify that your supported browsers can handle the reduced output. If the build output still
works in your target environments, Babel 8 will be a seamless upgrade for you.
loose and spec Deprecated — Use Assumptions
For years, Babel supported loose and spec options to trade off between spec compliance
and output size/performance. The problem: it was often unclear what these options actually did. A developer
setting loose: true on preset-env might not realize it affected everything from class fields to
computed properties to iterables.
In Babel 8, loose and spec are removed from @babel/preset-env
and deprecated from individual plugins. The replacement is assumptions —
a fine-grained system introduced in Babel 7.13 that lets you control exactly which spec deviations to allow.
// Before (Babel 7):
{
"presets": [
["@babel/preset-env", { "loose": true }]
]
}
// After (Babel 8) — use assumptions instead:
{
"assumptions": {
"setPublicClassFields": true,
"privateFieldsAsProperties": true,
"noDocumentAll": true,
"iterableIsArray": true
},
"presets": [
["@babel/preset-env"]
]
}
Migrate before upgrading. Assumptions have been supported since Babel 7.13.0,
so you can switch from loose/spec to assumptions while still on Babel 7,
then upgrade to Babel 8 when ready. The Babel docs
have a mapping table showing which assumption corresponds to each previously-loose behavior.
Babel 8 removes the corejs and useBuiltIns options from
@babel/preset-env and @babel/plugin-transform-runtime.
These are replaced by babel-plugin-polyfill-corejs3, a dedicated polyfill injection plugin
from the babel-polyfills
project.
// Before (Babel 7):
npm install core-js@3
// babel.config.json
{
"presets": [
["@babel/preset-env", {
"useBuiltIns": "usage",
"corejs": "3.38"
}]
]
}
// After (Babel 8):
npm install core-js@3 babel-plugin-polyfill-corejs3
// babel.config.json
{
"plugins": [
["polyfill-corejs3", {
"method": "usage-global",
"version": "3.38"
}]
],
"presets": [
["@babel/preset-env"]
]
}
The new plugin provides more granular control over polyfill injection. You can choose between
usage-global (inject polyfills as global imports, matching the old useBuiltIns: "usage"
behavior) and usage-pure (inject without globals, matching the old runtime approach).
Migrate this before upgrading to Babel 8. The standalone babel-plugin-polyfill-corejs3
works with Babel 7 already, so you can swap out your useBuiltIns/corejs
configuration while still on Babel 7.
Babel 8 drops support for several long-deprecated features:
babel-eslint — use @babel/eslint-parser instead (has been the recommended option since 2020).@babel/polyfill — removed. Use core-js and regenerator-runtime directly.@babel/register — still available but uses ESM imports.yearly presets — @babel/preset-es2015, preset-es2016, etc. removed. Use @babel/preset-env.@babel/preset-typescript — no longer supported. Use @babel/preset-flow for Flow projects.The Babel team used the major release to clean up internal code structure. While invisible to most users, these changes make Babel easier to maintain and contribute to:
Here's a step-by-step plan to migrate your project from Babel 7 to Babel 8:
loose/spec options with assumptions in your Babel config.useBuiltIns/corejs with babel-plugin-polyfill-corejs3.targets: "defaults" to verify the new defaults work for your project.@types/babel__* packages — you'll remove them after upgrading.@babel/* packages to ^8.0.0.import() or convert to ESM.@types/babel__* packages — types are now included.corejs/useBuiltIns from preset-env config if you migrated in Phase 1.loose/spec from preset-env config if you migrated in Phase 1.babel --version — should print 8.0.0.The JavaScript compilation landscape has diversified since Babel 7 launched. While Babel remains the most popular transpiler by a wide margin (651M weekly downloads), it's worth understanding how the alternatives position themselves. For a broader view of the JavaScript tooling ecosystem, check my guide to the Zod Compiler, which takes a similar build-time optimization approach.
| Feature | Babel 8 | SWC | Oxc |
|---|---|---|---|
| Language | JavaScript (ESM) | Rust | Rust |
| Plugin ecosystem | Hundreds of plugins, 8+ years of maturity | Growing, but smaller | Early stage |
| Speed | Fast (JS) | Very fast (Rust) | Very fast (Rust) |
| TypeScript support | Stripping only, no type checking | Stripping + some type-aware transforms | Stripping only |
| TypeScript types bundled | Yes (new in Babel 8) | No (separate @types) | In progress |
| ESM distribution | Yes (new in Babel 8) | Yes | Yes |
| LTS / stability | Very high, 8 years of proven reliability | High, widely adopted | Newer, maturing |
For most projects, Babel remains the safest choice due to its massive plugin ecosystem, proven stability, and the new TypeScript type definitions. SWC and Oxc are excellent for speed-critical pipelines where Rust performance matters more than plugin availability.
Babel's growth has been staggering. From 1.7 million weekly downloads in 2018 to 651 million weekly downloads in June 2026 — that's a 383× increase. The project has doubled its download count in the last year alone. This is not a dying project; it's the most popular JavaScript compiler in the world by a vast margin.
However, the Babel team faces a funding challenge. Donations through OpenCollective and GitHub Sponsors have been steadily decreasing even as usage skyrockets. The Babel core team — currently consisting of Huáng Jùnliàng, liuxingbaoyu, and Nicolò Ribaudo — relies on support from the Sovereign Tech Agency (Germany) and Igalia, but those funding sources are time-limited.
If your organization relies on Babel (and there's a good chance it does — directly or through a framework), consider supporting the project. At 651M weekly downloads, even a tiny contribution rate would secure the project's future for years.
Babel 7 will continue to receive security fixes only until June 2027. No new features or non-security bug fixes will be backported. If you absolutely cannot migrate within a year, plan your migration carefully — but don't wait until the last minute. The ESM-only change and the TypeScript types are strong incentives to move to Babel 8 sooner rather than later.
import instead of require() for programmatic usage. (2) @babel/preset-env no longer compiles to ES5 by default — it uses browserslist defaults (~ES2023). (3) loose/spec options are removed from preset-env in favor of assumptions. All three can be migrated incrementally while still on Babel 7.targets in your preset-env configuration. The change is only about the default, not about removing the capability. If your project still needs to support IE11 or other legacy browsers, you can target them explicitly: targets: "> 0.25%, ie 11".import natively — all listed versions do. If you're still on an older Node.js, upgrade first. For the latest on Node.js release changes, see my guide on the new Node.js release schedule.loose option to its equivalent assumption. For example, loose: true for classes maps to assumptions.setPublicClassFields = true. You can make this change while still on Babel 7 — assumptions have been supported since Babel 7.13. Do this migration first, then upgrade to Babel 8.@babel/preset-env and @babel/plugin-transform-runtime in Babel 8. The replacement is babel-plugin-polyfill-corejs3, which gives you more control over polyfill injection. You can choose between usage-global (global polyfills, like the old useBuiltIns: "usage") and usage-pure (pure imports without globals). Install it separately and migrate before upgrading to Babel 8.Babel 8 is a net positive for the JavaScript ecosystem. The ESM-only packaging, bundled TypeScript types, and modern defaults all point in the right direction. The migration is not trivial — it requires updating configs, possibly changing how you import Babel, and verifying your output targets. But the 12-month security window for Babel 7 gives you plenty of time to plan and execute the migration carefully.
If you're working on a complex build pipeline and need help planning this migration or evaluating how it affects your project's toolchain, get in touch. I help teams migrate their build configurations and can provide a clear migration path tailored to your stack.
Need help migrating your build pipeline to Babel 8 or modernizing your JavaScript toolchain? I provide free initial consultations.