blog

babel-polyfillの詳細

Babelにはコンパイルとポリフィルの2つのパートがありますが、今回はポリフィルのパートについて説明します(混同しやすいと思うので)。...

May 15, 2018 · 7 min. read
シェア


Babelはコンパイルとポリフィルの2つの部分から構成されていますが、今回はポリフィルの部分について説明します。

“babel 7”的图片搜索ç"“æžœ

ポリフィル

簡単に言うと、ポリフィルとはその名の通り、ブラウザではまだサポートされていないネイティブAPIを実装するコードのことです。

querySelectorAll;document.querySelectorAll;例えば、多くのモダンブラウザでサポートされているWebネイティブAPIが、古いブラウザではサポートされていないものがあるとします。Polyfiller;このライブラリはPolyfillまたは.NETと呼ばれます。

ポリフィルの起源

Polyfiller;Polyfill(ポリフィル)は、イギリスのウェブ開発者、 レミー・シャープ(Remy Sharp )が喫茶店でしゃがんでいるときに発明しました。ブラウザがサポートしていないネイティブのAPIをJavaScriptで実装することです。しかし、彼は、Shimは通常、ネイティブのサポートされていないAPIを実装するだけでなく、独自のAPIを持っているという事実を思い返し、適切な言葉が思いつかなかったので、彼は怒りにまかせてPolyfillという言葉を作り上げました。さまざまなウェブ会議で講演し、著書『Introducing HTML5』を執筆する中で、彼はこの言葉を頻繁に口にしたため、誰もが良い言葉だと思い、一緒に使うようになったのです。

ヒント:ポリフィルという言葉は、イギリスのホームセンター製品「ポリフィラ」に由来します。古いブラウザはひび割れのある壁だと思ってください。この[ポリフィル]は、この壁のひび割れを滑らかにし、より良い滑らかな壁にしてくれます。

シムとポリフィルの違い

シムとは、古い環境に新しいAPIを導入し、古い環境で利用可能な手段のみに依存するライブラリのことです。この2つを比較する議論はネット上にたくさんあるので、その中から私がより信頼できると思うものを抜粋して紹介します:

ポリフィルはシムの一種です。

実際には、比較のために特にshimのapiを参照しますが、これは標準に従ったものではなく、私が独自に設計したものです。

ヒント: shivというものもあり、これはie6-8のようなHTML5タグをサポートしていないブラウザでもhtml5タグをサポートできるようにするためのものです。

バベルポリフィル

実は、「Babelは構文をコンパイルするだけで、APIをコンパイルしない」というのは完全に正しいとは言えないと以前述べましたが、Babelはビルド時に、翻訳結果はデフォルトではランタイムにES6拡張を含みません。リジェネレータなどは含まれません。

ヒント

  1. 組み込み型は「ネイティブ」とも呼ばれ、String や Number などの組み込みオブジェクトとして解釈できます。
  2. Facebookによって開発されたRegeneratorは、es6のyield構文をes5に変換するツールです。

core-js標準ライブラリ

全てのBabelポリフィルソリューションが依存しているオープンソースライブラリzloirock/core-jsです。 約束シンボルコレクション、イテレータ、型付き配列ECMAScript7+ プロポーザルsetImmediate などを含みます。

regenerator ランタイムライブラリ

babel-runtime ライブラリ

babel-runtimeはBabelによって提供されるポリフィルライブラリで、それ自体はcore-jsとregenerator-runtimeライブラリで構成され、単純なマージとマッピング以外の追加処理は行いません。

例えば、Promiseを使いたい場合、Promiseを使う必要がある全てのモジュールにpromiseモジュールを手動で導入する必要があります:

const c = require('babel-runtime/core-js/promise');

この方法は非常に面倒で、実際interopRequireDefaultメソッドを厳密に使用するため、Babelはbabel-plugin-transform-runtimeというプラグインを提供しています。

babel-plugin-transform-runtime プラグイン

このプラグインを使うことで、BabelはSymbol、Promise、Mapなどの新しい型をコード内で見つけたときに、自動的かつオンデマンドでポリフィルすることができます。"自動的 "ということで、とても人気があります。

Babelの公式サイトでは、ライブラリを開発するのであれば、グローバル変数やプロトタイプの汚染がないので、このアプローチを使うことをお勧めします、と念を押しています。

グローバル変数汚染とは、babel-plugin-transform-runtimeプラグインがあなたのためにサンドボックスを実装することを意味し、あなたのES6ソースコードが明示的に一見グローバルなPromisesやSymbolを使用していても、Babelはサンドボックスモードでそれらを翻訳します:

ES6コード

const a = Symbol();
const obj = new Promise();
console.log(arr[Symbol.iterator]());

翻訳されたコード

"use strict";

var _getIterator2 = require("babel-runtime/core-js/get-iterator");

var _getIterator3 = _interopRequireDefault(_getIterator2);

var _promise = require("babel-runtime/core-js/promise");

var _promise2 = _interopRequireDefault(_promise);

var _symbol = require("babel-runtime/core-js/symbol");

var _symbol2 = _interopRequireDefault(_symbol);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var sym = (0, _symbol2.default)();

var promise = new _promise2.default();

console.log((0, _getIterator3.default)(arr));

プラグインはグローバルなSymbolとPromise変数をGlobalオブジェクトの下にマウントしないことに気づくでしょう。これにより、bluebirdのようなサードパーティのポリフィルを使用する他のライブラリを導入した場合でも、影響を受けません。

プロトタイプ汚染とは何かというと、ES6のArrayやStringなどの組み込み型が新しいメソッドで拡張されたことです。babel-plugin-transform-runtimeプラグインはArrayプロトタイプを拡張しませんが、これは多くの人が見落としがちなことです。区別すべき点は、ArrayはArrayのプロトタイプであるということです。Array.fromのような静的メソッドもプラグインによってポリフィルされるということです。そのため、babel-plugin-transform-runtimeプラグインは、クラスライブラリの開発に適しています。さらに、オンデマンドでポリフィルを行うことができるので、ポリフィルファイルのサイズをある程度制御することができます。

バベルポリフィル

最後にbabel-polyfillの話に戻りますが、本来の目的はES2015+の完全な実行環境をエミュレートすることです。そのため、Map、Set、Promiseなどの型をグローバル変数としてポリフィルし、Array.prototype.includes()に似た方法で注入します。公式サイトではアプリケーションレベルの開発に最適とされているポリフィルですが、ライブラリを開発している場合はあまりお勧めできません。

babel - polyfill;プラグインとは異なり(babel-plugin-transform-runtimeはプラグインで、.babelrcで設定する必要があります)、プロジェクトに一度に導入するだけでよく、通常は他のサードパーティライブラリと一緒にvendor.jsにパッケージされています。アプリケーションを書いているときは、babel-polyfill の存在を意識することはありません。 ブラウザがすでに Promise をサポートしていれば、まずネイティブの Promise を使用し、そうでなければ polyfill 版を使用します。plugin-transform-runtime プラグインやその他の依存関係を導入する必要はありません。欠点は明らかで、ファイルスペースを取ることと、オンデマンドでカスタマイズできないことです。

ヒント: babel-polyfill は必ずしもグローバル環境を汚染するわけではありません。 js が導入され実行されると、まず現在のメソッドがあるかどうかを判断し、Math.sign()メソッドの置き換えである上の例のように、書き換えるべきかどうかを判断します。

要約すると

babel - plugin - syntax;babel - plugin - transform;babel自体は変換機能を持たず、変換機能を1つのプラグインに分解しています。冒頭のプラグインは構文プラグインで、新しい構文の解析を担当し、冒頭のプラグインは翻訳、つまり構文の解析+コードの変換を担当します。babel - preset - es;翻訳/コンパイルは、操作のビルドフェーズであり、翻訳/コンパイルに加えて、babelはまた、ランタイム拡張との契約のpolyfillの一部が含まれています、babel-polyfillの使用を完了するには、babel-runtimeの主な用途は、envの使用をお勧めします。transform-runtimeの使用を完了するために、babel-runtimeを主に使用します。

Read next

オープンソースアプリケーション:ウィキペディアの全コンテンツをダウンロードするのに30時間かかる。

ウィキペディアのすべてを30時間以上かけてあなたのコンピュータに自動的にダウンロードできる、そんなオープンソースのアプリケーションがあります。

May 8, 2018 · 2 min read