2017年7月23日日曜日

babel-preset-envとbabel-polyfillとbabel-plugin-transform-runtime

先日NodeSchoolでbabel-preset-envについて話したので、ついでにもう少しこのあたりを調べてみました。


babel-preset-envがやってくれないこと

基本的にbabel-preset-envが変換してくれるのは文法だけなので、ターゲットブラウザに存在しない新しいクラスやメソッドについては何もしてくれません。例えば Promise とか Array.of とか。

そういうものを使いたいときは2通りの方法があります。
はい、タイトルで出落ちしてますね。

babel-polyfill

その名の通り、ポリフィルです。
とりあえずこれを import しておけば、ターゲットブラウザに足りないクラスやメソッドを補完してくれます。

実は、 babel-preset-env のオプションに useBuiltIns: true を指定しておくと、ターゲットブラウザがネイティブ対応していない機能だけ個別に import してくれます。

これを指定しない場合はとりあえず全部 import →ネイティブ対応していない機能だけポリフィる みたいな処理をするので、不要なファイルが含まれてしまいます。

欠点としては、
  • import しないとダメなので、ソースコードに変更が必要
  • 冪等でないので、間違えて複数回 import すると死ぬる
  • ソース内で使っていないクラスやメソッドも問答無用でポリフィる
こんなところです。

babel-plugin-transform-runtime

クラスやメソッドを使っている場所でインラインで別のコードに変換するので、正確にはポリフィルではありません。
なので、ソース内で使っていないければ一切影響はありません。

また、これはプラグインなので、babelの plugins オプションに指定しておけばソースコードを1行も変える必要はなく、複数回 import してしまう心配もありません。

ただし、
  • 使っている場所でその都度変換するので、多数の場所で使っていればコードが無駄に大きくなる
  • ネイティブ対応していようがいまいが問答無用で変換するので非効率
という問題があります。

あれ、あれれ…?

やってほしいこと

カンのいい人なら気づいたとおもいますが、この2つのいいとこ取りをした機能がほしいんです。

具体的には、例えば Promise に関して言うと、
  • ターゲットブラウザが Promise がネイティブで実装されていなくて
  • コード内で Promise を使っている場合のみ
ポリフィってくれるような機能があったらとてもうれしいですよね。

useBuiltIns: true + babel-polyfillは前者は満たすけど後者は満たさない(ネイティブ実装されていなければ、使っていようが使っていまいが埋め込む)

babel-plugin-transform-runtimeは前者は満たさないけど後者は満たす(ネイティブ実装されていようがいまいが、使っているところだけ埋め込む)

という、とても中途半端な状態なのです…

いろいろ調べたけどそういう機能はなさげでした。残念…

いつか実装されることを信じて!

参考

0 件のコメント:

コメントを投稿