7.5.0 Released: dynamic import and F# pipelines
Today we are releasing Babel 7.5.0!
This release includes improved support for a few ECMAScript proposals: the F# variant of the Stage 1 pipeline operator and an official plugin for the Stage 4 dynamic import()
proposal (along with preset-env
support).
It also has support for TypeScript namespace
s (experimental) and for Browserslist's default
query in preset-env
.
You can read the whole changelog on GitHub.
Thanks to Wesley Wolfe, Martin Zlámal, Blaine Bublitz, Letladi Sebesho, Paul Comanici, Lidor Avitan, Artem Butusov, Sebastian Johansson, and Min ho Kim for their first PRs!
We are always looking for help, especially with triaging issues, reviewing pull requests and helping people on Slack. We are experimenting with the new triage role implemented by GitHub, and we want to recognize people from the community who will stand up and help us! 😉
A fantastic example of this are the newest additions to the Babel organization: Tan Li Hau, who has been a great help in triaging issues and fixing bugs, and Thiago Arrais, who helped in implementing the pipeline operator!
In other news, we just announced the start of our own podcast! If you missed it, please check out our post from yesterday!
Our work has made been possible also by our sponsors. We want to thank both Discord and clay for becoming Silver Sponsors on OpenCollective, as well as Linkedin for becoming a Silver Sponsor of Henry on GitHub!
Special thanks go to Handshake, a decentralized, permissionless naming protocol compatible with DNS, for donating $100,000 last year! As a part of their FOSS Community Grant, they pledged $10.2M to various open source communities like Apache, Debian, EFF, and Babel.
If you or your company want to support Babel and the evolution of JavaScript, but aren't sure how, you can sponsor us on Open Collective and, better yet, work with us on the implementation of new ECMAScript proposals directly! As a volunteer-driven project, we rely on the community's support to both fund our efforts in supporting the wide range of JavaScript users and taking ownership of the code. Reach out to Henry at henry@babeljs.io if you'd like to talk more!
F# pipeline operator (#9450 and #9984)
The pipeline operator proposal is still at Stage 1, and thus its specification is still being defined.
This proposal has a few variants that are being thought out. By testing this plugin, you can help the proposal authors gather feedback about how pipelines could work. But also note that refactoring will be required if the semantics change throughout the proposal process (and they will).
Since version 7.3.0, Babel has supported the Smart variant of the pipeline operator proposal, and the "minimal" variant since 7.0.0-beta.
Thanks to the joint efforts of Thiago Arrais and James DiGioia, you can now also test the "# variant! If you have thoughts or comments about this specific proposal variant, you can reach out to James.
How is the F# variant different from the Smart one? Instead of having the concept of "topic references" (#
), arrow functions are used instead. This has the advantage of being more similar to current JavaScript, at the cost of a slightly less concise syntax.
Current JavaScript | F# pipeline | Smart pipeline |
---|---|---|
JavaScript
| JavaScript
| JavaScript
|
Although the two proposals aren't dependent on one another or being developed as a single proposal, you can use F# pipelines alongside with partial application (supported since Babel 7.4.0):
let newScore = person.score
|> double
|> add(7, ?)
|> boundScore(0, 100, ?);
Note that, while it may look the same as the "Smart" pipeline variant, the partial application proposal only supports ?
in function call parameters. This means that, for example, person |> #.score
is a valid "Smart" pipeline whose F# equivalent must use an arrow function: person |> p => p.score
.
The F# pipeline operator is also different regarding how await
is handled:
Current JavaScript | F# pipeline | Smart pipeline |
---|---|---|
JavaScript
| JavaScript
| JavaScript
|
If you want to test this new proposal variant, you can add @babel/plugin-proposal-pipeline-operator
to your Babel configuration:
module.exports = {
plugins: [
["@babel/proposal-pipeline-operator", { proposal: "fsharp" }]
]
};
You can also try it out in the repl, by enabling the "Stage 1" preset.
Dynamic import (#9552 and #10109)
Although Babel has had support for parsing dynamic imports import(source)
for a long time, there hasn't been a consistent way of transforming it.
- If you used
webpack
orrollup
, you would only include@babel/plugin-syntax-dynamic-import
and not transform it with Babel - If you used Node, you could use the
babel-plugin-dynamic-import-node
plugin to transform it - If you used SystemJS,
@babel/plugin-transform-modules-systemjs
in conjunction with@babel/plugin-syntax-dynamic-import
transformed it without explicitly enabling a transform plugin forimport()
Since the dynamic import proposal has been recently merged into the main specification, we have decided to unify these use-cases under a single entry point: @babel/plugin-proposal-dynamic-import
. This plugin must be used alongside one of the module transform plugins because Babel needs to know which module loading system you are targeting. When targeting CommonJS, it internally delegates to babel-plugin-dynamic-import-node
.
For example, this is a valid configuration:
module.exports = {
plugins: [
"@babel/plugin-proposal-dynamic-import",
"@babel/plugin-transform-modules-amd"
]
};
While this isn't:
module.exports = {
plugins: [
"@babel/plugin-proposal-dynamic-import"
]
};
If you want to only allow parsing of import()
expressions without transforming them, you can just include the @babel/plugin-syntax-dynamic-import
package.
If you are using @babel/preset-env
, dynamic import support will be enabled by default. You don't need to worry about webpack
or rollup
support, since both babel-loader
and rollup-plugin-babel
automatically disable the Babel transform to allow the bundler to handle it correctly.
defaults
browserslist query in @babel/preset-env
(#8897)
When @babel/preset-env
is not passed any targets, it runs every syntax transform on your code (emulating the now deprecated babel-preset-latest
).
To support this behavior, we had to work around the fact that Browserslist itself has default choices. This caused @babel/preset-env
to not allow usage of the default
query.
@babel/preset-env
now supports the defaults
query when passing targets directly to the preset:
module.exports = {
presets: [
["@babel/preset-env", {
targets: { browsers: "defaults" }
}]
]
};
You can also set it using a .browserslistrc
file, which is also used by other tools like Autoprefixer or Stylelint.
The default behavior of @babel/preset-env
is still to compile everything, but we might switch it in Babel 8 to use this defaults
query.
Experimental TypeScript namespaces
support (#9785)
Until now, namespaces were the second biggest TypeScript feature not supported by Babel (the first one is type-checking! 😛). Thanks to the work done by community member Wesley Wolfe, you can now enable experimental support for them in the TypeScript plugin, using the allowNamespaces
option of @babel/plugin-transform-typescript
:
module.exports = {
plugins: [
["@babel/plugin-transform-typescript", {
allowNamespaces: true
}]
]
}
Then, you can use namespaces in your code:
namespace Validation {
const lettersRegexp = /^[A-Za-z]+$/;
const numberRegexp = /^[0-9]+$/;
export class LettersOnlyValidator {
isAcceptable(s: string) {
return lettersRegexp.test(s);
}
}
}
⚠️ Warning ⚠️
When TypeScript support was initially added to Babel,
namespaces
were not included since they require type information that only a full TypeScript compiler and type-checker can provide. For this reason, this current (experimental) support has some limitations:
- Namespaces can only export immutable bindings
- When merging multiple namespaces with the same name, their scope isn't shared
You can find the full list of caveats in the
@babel/plugin-transform-typescript
documentation.