古いブラウザに自動で polyfill を適用する
古いブラウザへのes6対応です。
古いブラウザにも一応対応したい。ただし、煩わしいことはしたくない。最新ブラウザでpolyfillによるコード量増加などの悪影響を防ぎたい。とかの場合に使うといいかも…。
ただし、HTML5やCSS3、JavaScriptの最新構文を使用できるわけではないです。polyfillなので…。
polyfill.io の中国企業への売却
上記の Issue の通り。 polyfill.io ドメインは、中国の CDN ベンダーに売却されました。そのため、政治的なリスク等から polyfill.io の使用を不安視する声が上がっています。
それに伴い、 Cloudflare / Fastly が polyfill.io のフォークを提供することを発表しています。本記事では、コードを Cloudflare のコードに差し替えることで対応します。
コード
以下のコードを他<script>
より先(先頭)に宣言する。
特に何も気にしない場合
<!--script src="https://polyfill.io/v3/polyfill.min.js?features=default%2Ces5%2Ces6"></script-->
<script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=default%2Ces5%2Ces6"></script>
最新ブラウザでスクリプトの外部読み込みによるパース解析をブロックしたくない場合
polyfill-loader.js/**
* polyfill-loader.js
* 同期的にES6のpolyfillを読み込む(IE9+対応)
*/
(function() {
// アローファンクション構文有無(簡易ES6判定)
function canUseArrowFunction() {
try {
Function('x=>1');
return true;
} catch (e) {
return false;
}
}
// スクリプト同期ローダー
function scriptSynchronousLoader(url) {
// IE7+
var xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
xhr.send(null);
if (xhr.status === 200) {
var script = document.createElement('script');
script.text = xhr.responseText;
var sc = document.getElementsByTagName('script')[0];
sc.parentNode.insertBefore(script, sc);
}
xhr = null;
}
function main() {
if (!canUseArrowFunction()) {
// 他にほしいpolyfillがあれば、URLを変更する
// see https://polyfill.io/v3/url-builder/
//scriptSynchronousLoader('https://polyfill.io/v3/polyfill.min.js?features=default%2Ces5%2Ces6')
scriptSynchronousLoader('https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=default%2Ces5%2Ces6')
}
}
main();
})();
補足
polyfill
polyfill.io
を利用しています。polyfill.io
は、リクエストの User-Agent ヘッダーから、要求元ブラウザに適した polyfill を返してくれます。アクセスしたブラウザを認識して必要最小限の polyfill を自動で返してくれます。
IE8
IE8でObject.defineProperty
が非DOMオブジェクトのプロパティに対する取得/設定関数はサポートされていません。そのため、polyfillの置き換えの際にエラーとなります。そのため、IE9+でしかpolyfillが効きません。(たとえ、Object.defineProperty
のpolyfillを先に適用しても、DocumentFragment, Element, getOwnPropertySymbolsで問題が発生します)
es5対応
// strictモード有無(簡易ES5判定)
function canUseStrictMode() {
return (function() {"use strict"; return typeof this;}).call(1) === 'number';
}
※IE9-を判定する
Babel
コード量の増加や事前コンパイルできる環境であれば、Babelを使用してもいいかも。