JavaScript
Polyfill
babel

@babel/preset-envのuseBuiltInsを使ってpolyfillする

@babel/preset-envのuseBuiltInsに関する記事です。
Babel v7以降で使えるようになるpolyfillを自動補完してくれる機能について紹介します。

更新(2018/08/27)

2018/08/27にBabel v7が正式リリースされました🎉
https://babeljs.io/blog/2018/08/27/7.0.0

Babel v7

@babel/polyfill

  • babelは文法の変換のみ。ブラウザによっては使えない機能はあります。
  • 例えば、IEはPromiseとかSymbolとか使えません。これは文法ではなく、機能です。
  • @babel/polyfillを使えばその辺の穴埋め(polyfill)をしてくます。
  • ソースコードを直接改変する必要があり。以下のようにpolyfillをimportしなければいけません。
import "@babel/polyfill"

@babel/plugin-transform-runtime

  • こちらもpolyfillするbabelのプラグイン
  • babel-polyfillとは違いimportを書く必要がない。babelの設定に追加するだけ
  • babelのプラグインなので変換時にpolyfillします
  • 指定したブラウザとか関係なく問答無用で変換する。ようするにchromeには既に実装済の機能でChromeの最新バージョンに合わせて変換してもChromeがネイティブ対応済のものまでpolyfillします

求めているもの

  • polyfillのためにimportを書いたり、polyfill用のパッケージをインストールしたくない
  • 指定したブラウザやバージョンに無い機能だけpolyfill入れてほしい

@babel/preset-env

  • babel 6の頃はbabel-preset-envだった
  • 指定したブラウザやNodeのバージョンに合わせてネイティブサポートしていない文法のみ変換
  • cssのAutoprefixerのようにbrowserslistを使って文法の変換を行う
  • 上記で書いた「求めているもの」を叶えてくれる優れもの

Install

まずは@babel/preset-envのインストール方法

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

useBuiltIns: "usage"オプション

  • polyfillのための@babel/polyfillのインストールが不要
  • 指定したブラウザやバージョンに合わせて必要なpolyfillだけをimport

@babel/polyfillとbabel-plugin-transform-runtimeのいいとこどり!

Babel v6のbabel-preset-envのpolyfill

useBuiltInsオプションは1.x系からありました。

{
  "presets": [
    [
      "env",
      {
        "targets": {
          "ie": 11
        },
        // trueにすることで必要なpolyfillだけをimportするようにします
        "useBuiltIns": true
      }
    ]
  ]
}
  • 必要なpolyfillのみインポート
  • ただし前述の通り@babel/polyfillをimportしなければいけません。

イメージ的には以下のように@babel/polyfillをimportするコードが必要な分のpolyfillをimportするコードに変換されます

import "@babel/polyfill";

require("babel-polyfill/lib/core-js/modules/es6.promise");

Babel v7の@babel/preset-envからのpolyfill

{
  "presets": [
    [
      "env",
      {
        "targets": {
          "ie": 11
        },
        // 必要な分だけのpolyfillを自動でインポート
        "useBuiltIns": "usage"
      }
    ]
  ]
}
  • @babel/polyfillの別途インストールが不要
  • @babel/polyfillをインポートするコードが不要
  • usageにしてbabelを実行すると勝手に以下ような必要な分だけpolyfillが埋め込まれる

これが自動でコード内に挿入される

require("babel-polyfill/lib/core-js/modules/es6.promise");

開発者はpolyfillいるかいらないか気にしなくてよいようになります

注意

場合によっては別途polyfillが必要だったりもするので万能ではない
以下のような実行しないと型がわからない場合とかは自動でpolyfillできません
そういった場合は必要なpolyfillをimportする必要があります

users.includes("hoge")

GitHubにサンプル置いときました!

shisama/babel-preset-env-useBuiltIns-sample
npm updateしてnpm run buildすれば以下のトランスパイルした結果を出力
- Node.js(4/6/8)
- chrome(v60/v50)
- firefox(v55/beta)
- Safari
- Edge
- IE11

まとめ

  • babelは文法の変換だけ
  • polyfillは@babel/preset-envで "useBuiltIns": "usage" すればどのpolyfillが必要か考えなくてよくなるし、不要なpolyfillは入らない

最後までお読みいただきありがとうございました。質問や不備がございましたらコメント欄またはTwitter(@shisama_)までお願いいたします。