Nearing the 7.0 Release

Check out Planning for 7.0 for the last updates throughout the 7.0 pre-releases. If something isn’t clear in this post let me know!

Project Updates

We started a new videos page! We created this for people wanting to learn more about how Babel works and to help others contribute back. This page contains videos of conference talks on Babel and related concepts from team members and people in the community (you can send a PR if you have done a talk like this as well).

We created a new team page as well! We will be updating this page in the future with more information about what people work on and why they are involved. For such a large project, there are many ways to get involved and help out.

This the highest monthly donation we have gotten since the start (next highest is $100/month).

In the meantime, we will use our funds to meet in person and to send people to TC39 meetings. These meetings are every 2 months around the world.

If a company wants to specifically sponsor something, we can create separate issues to track. This was previously difficult because we had to pay out of pocket, or we had to find a conference on the same week to speak at to help cover expenses.

How you can help!

If your company would like to give back by supporting a fundamental part of JavaScript development and it’s future, consider donating to our Open Collective. You can also donate developer time to help maintain the project.

#1 Help Maintain the Project (developer time at work)

Engineer: There's a thing in SQL Server Enterprise blocking usCompany: Let's set up a call next week with them an ongoing discussion to resolve it next quarter

Engineer: There's a thing we need in babel, can I spent 2 days with a PR for itCompany: lol no it's their job https://t.co/icgaoJ0dTe

The best thing we can get on this project are people committed to helping out with the project given the massive amount of work/responsibility it takes. Again, I never felt ready to be a maintainer but somehow stumbled upon it but I’m just one person, and our team is just a few people.

#2 Fund development

Company: "We'd like to use SQL Server Enterprise"MS: "That'll be a quarter million dollars + $20K/month"Company: "Ok!"...Company: "We'd like to use Babel"Babel: "Ok! npm i babel --save"Company: "Cool"Babel: "Would you like to help contribute financially?"Company: "lol no"

#3 Contribute in other ways 😊

Upgrading

We will also be working on a upgrade tool that will help rewrite your package.json/.babelrc files and more. Ideally this means it would modify any necessary version number changes, package renames, and config changes.

Please reach out to help and to post issues when trying to update! This is a great opportunity to get involved and to help the ecosystem update!

Newly Updated TC39 Proposals

Deprecated Yearly Presets (e.g. babel-preset-es20xx)

TL;DR: use babel-preset-env.

What’s better than you having to decide which Babel preset to use? Having it done for you, automatically!

Even though the amount of work that goes into maintaining the lists of data is humongous — again, why we need help — it solves multiple issues. It makes sure users are up to date with the spec. It means less configuration/package confusion. It means an easier upgrade path. And it means less issues about what is what.

babel-preset-env is actually a pretty old preset that replaces every other syntax preset that you will need (es2015, es2016, es2017, es20xx, latest, etc…).

It compiles the latest yearly release of JavaScript (whatever is in Stage 4) which replaces all the old presets. But it also has the abilitiy to compile according to target environments you specify: whether that is for development mode, like the latest version of a browser, or for multiple builds, like a version for IE, and then another version for evergreen browsers.

Not removing the Stage presets (babel-preset-stage-x)

We can always keep it up to date, and maybe we just need to determine a better system than what these presets are currently.

Right now, stage presets are literally just a list of plugins that we manually update after TC39 meetings. To make this managable, we need to allow major version bumps for these “unstable” packages. Part of the reason for this is because the community will re-create these packages anyway, so we might as well do it from an official package and then have the ability to provide better messaging, etc.

Renames: Scoped Packages (@babel/x)

Back then, not a lot of projects used scoped packages, so most people didn’t even know they existed. You may also have had to pay for a npm org account back then, while now it’s free (and supports non scoped packages, too). The issues with searching for scoped packages are solved and download counts work. The only thing left is that some 3rd party registries still don’t support scoped packages, and I think we are at a point where it seems pretty unreasonable to wait on that.

If you want reasons why we prefer scoped packages:

Naming is difficult: we won’t have to check if someone else decided to use our naming convention for their own plugin

Similarly, package squatting

Sometimes people create babel-preset-20xx or some other package because it’s funny, and then we have to make an issue/email to ask for it back.

People have a legit package, but it happens to be the same name as what we wanted to call it. - People see that a new proposal is merging (like optional chaining, pipeline operator) and decide to fork and publish a version of it under the same name. Then, when we publish, it tell us the package was already published 🤔. Then, I have to find their email and email both them and npm support to get the package back and republish.

What is an “official” package and what is a user/community package with the same name? We can get issue reports of people using misnamed or unofficial packages because they assumed it was part of Babel. One example of this was a report that babel-env was rewriting their .babelrc file, and it took them a while to realize it wasn’t babel-preset-env.

So, it seems obvious we should use scoped packages, and, if anything, we should have done it much earlier 🙂!

Examples of the scoped name change:

babel-cli -> @babel/cli

babel-core -> @babel/core

babel-preset-env -> @babel/preset-env

Renames: -proposal-

Any proposals will be named with -proposal- now to signify that they aren’t officially in JavaScript yet.

So @babel/plugin-transform-class-properties becomes @babel/plugin-proposal-class-properties, and we would name it back once it gets into Stage 4.

Renames: Drop the year from the plugin name

Previous plugins had the year in the name, but it doesn’t seem to be necessary now.

Since years were only the case for es3/es2015, we didn’t change anything from es2016 or es2017. However, we are deprecating those presets in favor of preset-env, and, for the template literal revision, we just added it to the template literal transform for simplicity.

Peer Dependencies + Integrations

We are introducing a peer dependencies on @babel/core for all the plugins (@babel/plugin-class-properties), presets (@babel/preset-env), and top level packages (@babel/cli, babel-loader).

peerDependencies are dependencies expected to be used by your code, as opposed to dependencies only used as an implementation detail. — Stijn de Witt via StackOverflow.

babel-loader already had a peerDependency on babel-core, so this just changes it to @babel/core. This is just so that people weren’t trying to install these packages on the wrong version of Babel.

For tools that already have a peerDependency on babel-core and aren’t ready for a major bump (since changing the peer dependency is a breaking change), we have published a new version of babel-core to bridge the changes over with the new version babel-core@7.0.0-bridge.0. For more information check out this issue.

Similarly, packages like gulp-babel, rollup-plugin-babel, etc, all used to have babel-core as a dependency. Now these will just have a peerDependency on @babel/core. This lets these packages not have to bump major versions when the @babel/core API hasn’t changed.

You might remember that after Babel 6, Babel became a set of npm packages with its own ecosystem of custom presets and plugins.

However since then, we have always used a “fixed/synchronized” versioning system (so that no package is on v7.0 or above). When we do a new release such as v6.23.0 only packages that have updated code in the source are published with the new version while the rest of the packages are left as is. This mostly works in practice because we use ^ in our packages.

Unfortunately this kind of system requires that a major version be released for all packages once a single package needs it. This either means we make a lot small breaking changes (unnecessary), or we batch lots of breaking changes into a single release. Instead, we want to differentiate between the experimental packages (Stage 0, etc.) and everything else (es2015).

This means we intend to make major version bumps to any experimental proposal plugins when the spec changes rather than waiting to update all of Babel. So anything that is < Stage 4 would be open to breaking changes in the form of major version bumps and same with the Stage presets themselves (if we don’t drop them entirely).

This goes with our decision to change TC39 proposal plugins to use the -proposal- name. If the spec changes, we will do a major version bump to the plugin and the preset it belongs to (as opposed to just making a patch version which may break for people). Then, we will need to deprecate the old versions and setup an infrastructure to automatically update people so that everyone is up to date on what the spec will become (and so they don’t get stuck on something, like we have with decorators).

if the target environment happens to support polyfills other than padStart or padEnd.

However in order to make that even better, we should only import polyfills that are “used” in the codebase itself. Why even import padStart if it’s not even used in the code?

"useBuiltins": "usage" is our first attempt to begin that idea. It does an import at the top of each file but only adds the import if it finds it used in the code. This approach means that we can import the minimum amount of polyfills necessary for the app (and only if the target environment doesn’t support it).

So if you use Promise in your code, it will import it at the top of the file (if your target doesn’t support it). Bundlers will dedupe the file if it’s the same so this approach won’t cause multiple polyfills to be imported.

import"core-js/modules/es6.promise";vara=newPromise();

import"core-js/modules/es7.array.includes";[].includesa.includes

With type inference we can know if an instance method like .includes is for an array or not, and having a false positive is ok until that logic is better since it’s still better than importing the whole polyfill like before.

Either implement or have plan in place for versioning and handling polyfills independently from helpers, so we aren’t explicitly tied to core-js 2 or 3, since people may have things that depend on one or the other and won’t want to load both a lot of the time.

Thanks

Shoutout to our team of volunteers: Logan who has been really pushing hard to fix a lot of our core issues regarding configs and more and the one doing all of that hard work, Brian who has been taking over maintainence of a lot of preset-env work and just whatever I was doing before 😛, and Daniel who has always been stepping in when we need the help whether it be maintaining babel-loader or helping move the babylon/babel-preset-env repo’s over. And same with Nicolo, Sven, Artem, and Diogo for stepping up in the last year to help out.

I’m really looking forward to a release (I’m tired too; it’s almost been a year 😝), but also don’t want to rush anything just because! Been a lot of ups and downs throughout this release but I’ve certainly learned a lot and I’m sure the rest of the team has as well.

And if I’ve learned anything at all this year, I should really heed this advice rather than just write about it.