Upgrade to Babel 7 (WIP)

Posted Mar 1, 2017 by Sven SAULEAU, Henry Zhu

Refer users to this document when upgrading to Babel 7 (currently alpha).

Because not every breaking change will affect every project, we’ve sorted the sections by the likelihood of a change breaking tests when upgrading.

All of Babel

Support for Node.js 0.10 and 0.12 has been dropped #5025, #5041, #5186 high

We highly encourage you to use a newer version of Node.js (LTS v4, LTS v6) since the previous versions are not maintained. See nodejs/LTS 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.

“use strict” and ‘this’ in CommonJS

Babel 6’s transformations for ES6 modules ran indiscriminantly on whatever files it was told to process, never taking into account if the file actually had ES6 imports/exports in them. This had the effect of rewriting file-scoped references to this to be undefined and inserting "use strict" at the top of all CommonJS modules that were processed by Babel.

This behavior has been restricted in Babel 7 so that for the transform-es2015-modules-commonjs transform, the file is only changed if it has ES6 imports or exports in the file. (Editor’s note: This may change again if we land https://github.com/babel/babel/issues/6242, so we’ll want to revisit this before publishing).

If you were relying on Babel to inject "use strict" into all of your CommonJS modules automatically, you’ll want to explicitly use the transform-strict-mode plugin in your Babel config.

Option parsing

Babel’s config options are stricter than in Babel 6. Where a comma-separated list for presets, e.g. presets: 'es2015,es2016' technically worked before, it will now fail and need to be changed to an array #5463. This does not apply to the CLI, where --presets es2015,es2016 will certainly still work.

Resolving string-based config values

In Babel 6, values passed to Babel directly (not from a config file), were resolved relative to the files being compiled, which led to lots of confusion. In Babel 7, values are resolved consistently either relative to the config file that loaded them, or relative to the working directory.

For presets and plugins values, this change means that the CLI will behave nicely in cases such as

babel --presets es2015 ../file.js

Assuming your node_modules folder is in ., in Babel 6 this would fail because the preset could not be found.

This change also affects only and ignore which will be expanded on next.

Path-based only and ignore patterns

In Babel 6, only and ignore were treated as a general matching string, rather than a filepath glob. This meant that for instance *.foo.js would match ./**/*.foo.js, which was confusing and surprising to most users.

In Babel 7, these are now treated as path-based glob patterns which can either be relative or absolute paths. This means that if you were using these patterns, you’ll probably need to at least add a **/ prefix to them now to ensure that your patterns match deeply into directories.

only and ignore patterns do still also work for directories, so you could also use only: './tests' to only compile files in your tests directory, with no need to use **/*.js to match all nested files.

Babel’s CLI commands

The --copy-files argument for the babel command, which tells Babel to copy all files in a directory that Babel doesn’t know how to handle, will also now copy files that failed an only/ignore check, where before it would silently skip all ignored files.

babel-node

The babel-node command in Babel 6 was part of the babel-cli package. In Babel 7, this command has been split out into its own babel-node package, so if you are using that command, you’ll want to add this new dependency.

babel-preset-stage-3

Remove Stage 4 plugins from Stage 3 #5126 high

These plugins were moved into their yearly presets after moving to Stage 4:

babel-plugin-syntax-trailing-function-commas (babel-preset-es2017) babel-plugin-transform-async-to-generator (babel-preset-es2017) babel-plugin-transform-exponentiation-operator (babel-preset-es2016)


Instead of any yearly preset, we suggest that you use the newly created babel-preset-env which uses the correct plugins based on your environment.

Before:

{
  "presets": ["es2015", "es2016", "es2017"]
}

After:

{
  "presets": ["env"]
}
{
  "presets": [
    ["env", {
      "targets": {
        "browsers": ["last 2 versions", "safari >= 7"]
      }
    }]
  ]
}

See /docs/plugins/preset-env/ for more information.

Spec Compliancy

A trailing comma cannot come after a RestElement in objects #290 medium

This is when you are using babel-plugin-transform-object-rest-spread.

Before:

var { ...y, } = { a: 1};

This will now throw a syntax error.

After:

var { ...y } = { a: 1};

babel-core

babel-core/register.js has been removed #5132 low

The deprecated usage of babel-core/register has been removed in Babel 7; instead use the standalone package babel-register.

Install babel-register as a new dependency:

npm install --save-dev babel-register

Upgrading with Mocha:

mocha --compilers js:babel-core/register

to:

mocha --compilers js:babel-register

See babel-register documentation for more information.

babel-plugin-transform-class-constructor-call

babel-plugin-transform-class-constructor-call has been removed #5119 low

TC39 decided to drop this proposal.

Before:

class Point {

  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  call constructor(x, y) {
    return new Point(x, y);
  }

}

let p1 = new Point(1, 2);
let p2 = Point(3, 4);

You can move your logic into the constructor or into a static method.

Example with a static method:

class Point {

  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  static secondConstructor(x, y) {
    return new Point(x, y);
  }

}

let p1 = new Point(1, 2);
let p2 = Point.secondConstructor(3, 4);

See /docs/plugins/transform-class-constructor-call/ for more information.

babel-plugin-transform-es2015-template-literals

Template Literals Revision updated #5523 low

See the proposal for Template Literals Revision.

It cause Babel 6 to throw Bad character escape sequence (5:6).

tag`\unicode and \u{55}`;

This has been fixed in Babel 7 and generates something like the following:

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
var _templateObject = _taggedTemplateLiteral([], ["\\unicode and \\u{55}"]);
tag(_templateObject);

babel

Dropping the babel package #5293 low

This package currently gives you an error message to install babel-cli instead in v6. We will just not publish a v7 version. It also doesn’t make sense if we switch to scoped package babel -> @babel/babel?

babel-generator

Dropping the quotes option #5154] none

If you want formatting for compiled output you can use recast/prettier/escodegen/fork babel-generator.

This option was only available through babel-generator explicitly until v6.18.0 when we exposed parserOpts and generatorOpts. Because there was a bug in that release no one should’ve used this option in Babel itself.

Dropping the flowUsesCommas option #5123 none

Currently there are 2 supported syntaxes (, and ;) in Flow Object Types.

This change just makes babel-generator output , instead of ;.

babel-core

Remove babel-core/src/api/browser.js #5124 none

babel-browser was already removed in 6.0. If you need to use Babel in the browser or a non-Node environment, use babel-standalone.