dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

babel-preset-envの使い方(babel-preset-es2015からの移行)

はじめに

ES2015 の変換に babel-preset-es2015 を使っているプロジェクトで、npm install 時に

npm WARN deprecated babel-preset-es2015@6.24.1: 🙌  Thanks for using Babel: we recommend using babel-preset-env now: please read babeljs.io/env to update!

という警告が出ており、あーたしかに babel-preset-env を使った方がいいってどこかで聞いたなと思いつつ env の設定のしかたを調べられていなかったんですが、ようやく少し調べました。
そのときのメモ。

公式の

に加え、Qiita のこちらの記事も参考になりました。

注)この記事を書いた 2018/1/18 時点で Babel のバージョン 7 はベータ版だったので、6 系での設定です。
バージョン 7 での変更点は最後に書いてます。

最初にまとめ

  • babel-preset-es2015 から babel-preset-env にただ切り換えるだけであれば、babel-preset-xxx 部分を置き換えるだけで済む
  • babel-preset-env は何もオプションを指定しなければ、全部 ES5 の記法にトランスパイルする
  • が、モダンなブラウザでは Class など ES2015+ の構文に対応しているので、サポート対象ブラウザに応じて必要なところまでトランスパイルするのが望ましい
  • babel-preset-env では targets オプションで対象ブラウザを指定することが可能
// .babelrc(例)
{
  "presets": [
    ["env", {
      "targets": {
        "browsers": ["last 2 versions", "safari >= 7"]
      }
    }]
  ]
}

(2018/5/11追記)

上記の例の last 2 versions はあまりよくないらしい。という記事を読んだ。

last 2 versions - @jamiebuilds

(追記ここまで)


設定方法

babel-preset-env をインストール

babel-preset-es2015 をアンインストールして、かわりに babel-preset-env を入れます。

$ yarn remove babel-preset-es2015
$ yarn add -D babel-preset-env

.babelrc を修正

まずは単純に es2015 を env に置き換えます。

 {
-  "presets": ["react", ["es2015", { "modules": false }]],
+  "presets": ["react", ["env", { "modules": false }]],
   "plugins": [
     "transform-class-properties",
     "transform-object-rest-spread",
    "react-hot-loader/babel"
  ]
}

webpack で Tree Shaking をするための modules: false というオプションもそのままで大丈夫のようです。
https://babeljs.io/docs/plugins/preset-env/#modules

オプションで対象ブラウザを指定する

https://babeljs.io/docs/plugins/preset-env/#targets
targets というオプションで対象のブラウザを指定できます。
対象のブラウザを指定すると、そのブラウザで対応している構文についてはそのままでトランスパイルせず、未対応の構文のみトランスパイルするという挙動になるようです。

内部的には compat-table のデータを参照しているらしい。

targets の指定方法にはいくつか種類があって、

1) 対象ブラウザとバージョンを決め打ち

{
  "targets": {
    "chrome": 52
  }
}

2) targets.browsers を指定し、クエリを書く(内部的には browserslist を使っている)

"targets": {
  "browsers": ["last 2 versions", "safari 7"]
}

もしくはこれらを複数指定することができます。あとは node オプションで対象の Node のバージョンが指定できたり。
なお

Note, browsers’ results are overridden by explicit items from targets.

とあるので、 browsers の内容は個別に指定したものがあった場合上書きされます。


最終的にこうなった

というわけで、私は一旦こうしました。

// before
{
  "presets": ["react", ["es2015", { "modules": false }]],
  "plugins": [
    "transform-class-properties",
    "transform-object-rest-spread",
    "react-hot-loader/babel"
  ]
}
// after
{
  "presets": [
    "react",
    ["env", {
      "targets": {
        "browsers": ["last 2 versions"]
      },
      "modules": false
      }
    ]
  ],
  "plugins": [
    "transform-class-properties",
    "transform-object-rest-spread",
    "react-hot-loader/babel"
  ]
}

個人の適当なリポジトリで試しただけなので、対象ブラウザとかは深く考えてないです。

参考:

PR はこれ

Babel 7 での変更点

Babel 7 から babel-preset-env も Babel 本体のリポジトリに移動になったので、パッケージ名が @babel/preset-env に変わります。

参考:https://github.com/babel/babel/tree/master/packages/babel-preset-env

$ npm install @babel/preset-env --save-dev

targets の指定方法は変わってないぽいです。