仕事が忙しいほどブログを書きたくなる。
◆何の話か
SPAのサイト作ってて、古いブラウザ使ってる人にメッセージ出したいと思いました。任意の画面を表示させたい。
Babel使えば動くんだけど、「動くように」はしたくない。だって古いブラウザだもの。新しいやつ使いやがれ。
◆以下に紹介されるやり方が正しいか
知らん。考えてたらひらめいたというだけ。もっといい方法あるかもね。
◆結論
一例だけど。
<script> function r() { document.body.innerHTML = "<main>そのブラウザは古いです。申しわけありませんが動かねぇよバカが。</main>"; }; window.addEventListener('DOMContentLoaded', function(event) { (function (){ "use strict"; try { window.Function("var foo = (x) => x"); // ES6のアロー関数 window.Function("let { ...x } = { y: 1 };"); // ES2016+のobject-rest-spread } catch (e) { r(); } })(); }); </script>
これをHTMLのhead要素にぶち込んだれや。なるべく上のほうにね。
◆作戦
- あるブラウザで任意の記法が利用できるかどうかを確認したい。
- でも、その記法が書いてあったら画面がぶっ壊れる。
- どうしよ…
- 天啓「実行時に構文解析して例外をキャッチすればいいんじゃね?」
- あー…え?それできるの?
- できるわ。
文字列をコードとして変換するのはeval…じゃのうて、Window.Functionのコンストラクタを使いましょう。
文字を変換できなかった場合(古いブラウザだった場合)は、bodyのHTMLを上書きしてしまえ。IE死ね!
変換のタイミングはDOMがロードされた後。DOMContentLoadedにしてみる。変えてもいいと思うけど。
▼body書き換え
function r() { document.body.innerHTML = "<main>そのブラウザは古いです。申しわけありませんが動かねぇよバカが。</main>"; };
単にbodyを書き換える関数「r」。
このrを「古いブラウザって判定された時」に動かす。
▼判定
function (){ "use strict"; try { window.Function("var hoge = (x) => x"); // ES6のアロー関数 window.Function("var { ...hoge } = { fuga: 1 };"); // ES2016+のobject-rest-spread } catch (e) { r(); } }
たとえば
- アロー関数が使えない
- オブジェクトのスプレッドが使えない
を判定したいときはこうなる。window.Functionってので文字列を関数に変換できる。変換に失敗したブラウザはcatchに入る。
この判定スクリプトをDOMロード時に即時実行すればよい。
おまえ「EcmaScriptのバージョンでは判定してなくね?」
せやね。機能Xが実装されてるかどうかで判別するほかない。この記事はタイトル詐欺だ。
◆どういうスクリプトを動かせばいいんや
ES6に対応してないなら「var hoge = (x) => x」の変換でエラーがでるんだったな。ES5では?
調べよう。
ECMAScrip compatibility tableってサイトがある。
上の「5」「6」「2016+」とかクリックして調整したり「Show obsolete platforms」のチェックボックスをONにしてみたりで。
例えば「Array.isArray」はES5から使えるようになった機能らしいんで、「Array.isArray(0)」の変換を試みればいいじゃない。目当てのブラウザとそのバージョンにおける実装状況を眺めつつな。
◆結
なんとなく動く。はず。headのなるべく上に書くことを忘れずに。あと、もっといい方法あったら教えろ。
コメントを残す