Babel7.4で非推奨になったbabel/polyfillの代替手段と設定方法
Babel7.4.0 から、長いことお世話になってきた @babel/polyfill が非推奨となりました。加えて、@babel/preset-env と @babel/ransform-runtime が core-js@3 に対応したようです🎉
これらに伴いpolyfill周りの設定方法が変わったので、その内容をメモしておこうと思います。
Babel と core-js の関係のおさらい
Babelが提供する @babel/polyfill や @babel/preset-env などのモジュールを利用すると
- built-ins objects(Promise, WeakMap等)
- static methods(Object.assign, Array.from等)
- instance methods(Array.prototype.includes等)
といった新しい機能を使った実装が可能になりますよね。これらのBabelモジュールは core-js が提供するpolyfillを内部的に読み込んでいます。特に @babel/polyfill は core-js と regenerator-runtime を束ねて提供するpolyfill集です。
Babel7.4.0からはこの @babel/polyfill が非推奨になり、代わりにcore-jsのバージョンを指定して直接読み込む方法が提案されています。
これからのpolyfill設定方法
1. preset-env と useBuiltIns:usage で必要なpolyfillだけ読み込む方法
@babel/preset-env は(指定した実行環境にあわせた)必要な構文変換や、polyfillの読み込みをしてくれるものです。そしてこのpresetのオプションのuseBuiltins
で「どのようにpolyfillを読み込むか」を指定できます。
useBuiltIns: usage
とし、必要なpolyfillだけを読み込む設定例から見ていきます。
@babel/prest-env をinstallする
npm install -D @babel/preset-env
.babelrc または babel.config.js でオプションを指定する
presets: [
["@babel/preset-env", {
useBuiltIns: "usage",
corejs: 3 // or 2
}]
]
指定したバージョンの core-js をinstallする
npm install -S core-js@3 # or core-js@2
useBuiltIns: usage
とすると、コード内からpolyfillが必要な箇所を勝手に判断し、必要なcore-jsを勝手にimportしてくれます。このとき、core-js のバージョンも併せてオプションで指定し、それに応じた core-js をnpm installしておく必要があるわけですね。
ちなみに執筆時点の公式ドキュメントではuseBuiltIns: usage
はまだexperimentalとなっているのですが、core-js@3 では多くの問題が解消されていてもはやexperimentalではないだろう…とのことです。
2. preset-env と useBuiltIns:entry で全polyfillを読み込む方法
上記と同様に @babel/preset-env を使う方法ですが、オプションの内容が変わります。useBuiltIns: entry
とし、index.js などのjsファイルの先頭にてpolyfillをimportすることで、全部のpolyfillを読み込む方法です。
@babel/prest-env をinstallする
npm install -D @babel/preset-env
.babelrc または babel.config.js でオプションを指定する
presets: [
["@babel/preset-env", {
useBuiltIns: "entry",
corejs: 3 // or 2
}]
]
指定したバージョンの core-js と regenerator-runtime をinstallする
npm install -S core-js@3 # or core-js@2
npm install -S regenerator-runtime
jsファイルの先頭で core-js と regenerator-runtime をimportする
import "core-js/stable";
import "regenerator-runtime/runtime";
// import "@babel/polyfill" 今まではこう指定していましたね
@babel/polyfill をimportしていた頃と同じ注意になりますが、core-js や regenerator-runtime 複数回importすると問題が起きる可能性があるので、bundleされるjsの冒頭で1度だけimportするように注意する必要があります。
3. transform-runtime を使う方法
@babel/plugin-transform-runtime を使ってpolyfillを入れると、globalが汚染されないメリットが得られる反面、instance methodsが使えないというデメリットがありました。が、core-js@3に対応したことによりinstance methodsが利用できるようになります🎉
設定の際は、bundleに組み込まれる @babel/runtime と、ビルド時にpolyfill変換などを担う @babel/plugin-transform-runtime を用意します。
@babel/runtime と @babel/plugin-transform-runtime をinstallする
npm install -S @babel/runtime
npm install -D @babel/plugin-transform-runtime
.babelrc または babel.config.js でオプションを指定する
presets: [
["@babel/plugin-transform-runtime", { corejs: 3 }]
]
指定したバージョンの core-js をinstallする
npm install -S core-js@3
Proposal の使い方
@babel/preset-env または @babel/plugin-transform-runtime どちらを利用する場合であっても、core-js@3 ではProposalの機能も利用できるようになりました。設定方法はオプションの内容を変更するだけです。
// before
{ corejs: 3 }
// after
{
corejs: {
version: 3,
proposals: true
}
}
公式ドキュメントには「ECMAScriptの提案は本質的に不安定であり、core-js@4 では変わる可能性があります」との注意書きがありますので、ご承知おきを。
参考
- https://github.com/babel/website/pull/1987
- https://babeljs.io/docs/en/next/babel-polyfill.html
- https://babeljs.io/docs/en/babel-plugin-transform-runtime
- https://babeljs.io/docs/en/babel-preset-env
- https://babeljs.io/blog/2019/03/19/7.4.0
- https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md