Skip to main content

7.13.0 Released: Records and Tuples, granular compiler assumptions, and top-level targets

· 7 min read

We just published Babel 7.13.0, the first minor release of 2021!

This release includes some important features to @babel/core: a targets option (similar to @babel/preset-env's one) that can be shared across different plugins, an assumptions option to precisely tune your configuration to produce a smaller compilation output, and support for plugins and presets written using native ECMAScript modules.

Babel now supports transforming the Records and Tuples ECMAScript proposal, which brings immutable data structures and structural equality to JavaScript, and parsing the Module Blocks proposal.

Additionally, we added support for some new Flow and TypeScript features.

You can read the full changelog on GitHub.

Funding Update

We have joined the "GitHub Sponsors for organizations" program, so you can now sponsor us directly through GitHub 😊.

These funds are used to support our team's (currently one full-time and three part-time maintainers) continued efforts in improving stability and developing new features.

Both our donations and expenses are openly tracked through our Open Collective page, where we will also track donations coming from GitHub Sponsors.

We welcome donations from both individual and companies. If your company is interested in becoming a Gold tier sponsor ($1k/month) and wants to discuss more, please reach out to [email protected]!

Highlights

Top-level targets option (#12189, RFC)

@babel/preset-env's targets option allows users to specify their target environments, automatically choosing which syntax to transform and what polyfills to inject. Since releasing @babel/preset-env, we've learned that plugins themselves can also benefit from knowing your targets. Currently, this can a bit cumbersome, as you have to specify your targets twice (for example, if you are using our new polyfill plugins). By introducing targets as a top level option, you now only have to specify your targets once:

Old configurationNew configuration
babel.config.json
{
"presets": [
["@babel/preset-env", {
"targets": ">1%, not ie 11"
}]
],
"plugins": [
["polyfill-es-shims", {
"targets": ">1%, not ie 11"
}]
]
}
JSON
{
"targets": ">1%, not ie 11",
"presets": ["@babel/preset-env"],
"plugins": ["polyfill-es-shims"]
}

We recommended converting your Babel config to use the new top-level targets option, as it has the following additional benefits:

  1. It has better handling of the esmodules: true target. (it's intersected with the other targets, rather than replacing them)
  2. As we introduce additional targets-related support in our plugins, you'll automatically benefit from more optimized output!

You can read the details about this new option in its RFC.

🔮 In the future we might explore moving @babel/preset-env into @babel/core so that you don't have to install an additional package to get started with Babel. This new option can be seen as the first step in that direction!

Top-level assumptions option (#12219, RFC)

Many of our plugins have a loose option, which tells Babel to generate smaller/faster output by making certain assumptions about your code and ignoring certain edge cases in the JavaScript spec.

However, loose has some problems that lead to user confusion: the term itself does not help to describe how exactly it affects the compiler's behavior and, worse, sometimes requires setting configuration for multiple plugins to ensure everything compiles.

To help fix these problems, we've added a new top level option to tell Babel which assumptions it can make about your code: assumptions! Similar to the new targets option, every plugin will now receive the assumptions you've enabled, eliminating the need to set the option individually. This is really valuable since a plugin can be influenced by multiple assumptions, and an assumption can influence multiple plugins.

caution

This is advanced functionality. Like the previous loose option, please be careful when enabling assumptions, because they are not spec-compliant and may break your code in unexpected ways.

For example, when transforming classes, Babel will generate this output by default:

InputOutput
JavaScript
class Test {
constructor() {
this.x = 2;
}
}

// You can test the thrown error in the console:
// Uncaught TypeError: class constructors must be invoked with 'new'
Test();
JavaScript
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}

let Test = function Test() {
_classCallCheck(this, Test);

this.x = 2;
};

// You can test the thrown error in the console:
// Uncaught TypeError: class constructors must be invoked with 'new'
Test();

However, enabling the noClassCalls assumption tells Babel "I'm never trying to call classes without new, so you can compile without worrying about it":

JSON
{
"targets": "firefox 30",
"assumptions": { "noClassCalls": true },
"presets": ["@babel/preset-env"]
}
InputOutput
JavaScript
class Test {
constructor() {
this.x = 2;
}
}

// Won't throw since we violated the assumption
Test();
JavaScript
let Test = function Test() {
this.x = 2;
};

// Won't throw since we violated the assumption
Test();

Check out the full list of assumptions over in our documentation, where you can individually enable or disable them to see how they affect the compiled output.

Records and Tuples support (#12145)

Thanks to a collaboration with Bloomberg, Babel now supports transforming the "Records and Tuples" stage 2 proposal.

The Babel plugin transforms records and tuples syntax using the global Record and Tuple functions:

InputOutput
JavaScript
let data = #{
name: "Babel",
ids: #[1, 2, 3]
};
JavaScript
let data = Record({
name: "Babel",
ids: Tuple(1, 2, 3),
});

This means that you will need to load a polyfill for those global functions, such as @bloomberg/record-tuple-polyfill, either by importing it in your code or with a <script> tag:

<script src="https://unpkg.com/@bloomberg/[email protected]/lib/index.umd.js" />

NOTE: No engine currently supports records and tuples, so you always need to load the polyfill.

In order to enable this transform, you need to add @babel/plugin-proposal-record-and-tuple to your configuration.

New Flow features (#12193, #12234)

Babel 7.13.0 has support for two new Flow features:

  • this type annotation in functions, that allow you to specify the type of the this object as if it was a parameter

    JavaScript
    function getPerson(this: Database, id: string): Person {
    this instanceof Database; // true
    }
  • enum declarations with unknown members

    JavaScript
    enum PetKind {
    Dog,
    Cat,
    Snake,
    ...
    }

TypeScript 4.2 support (#12628)

TypeScript 4.2 supports some new syntax features such as abstract constructor signatures.

You can read more about the changes in the TypeScript release post.

Automatic ES modules in @babel/runtime (#12632)

@babel/runtime contains all of the Babel runtime helpers in both CommonJS and ECMAScript module formats.

Until now, you had to manually choose which one you wanted to use, specifying the useESModules option of @babel/plugin-transform-runtime.

We have now reorganized @babel/runtime's internal structure, leveraging the new "exports" package.json field supported by Node.js and bundlers, so that they are able to automatically choose between CJS and ESM.

For this reason, the useESModules option is now deprecated and will be removed in Babel 8.