babel-logo

IE サポートしなきゃだめ?

ブログのデザインを調整したり、古くなってきている JavaScript を新しい機能で置き換えたりしようとしていたのですが・・・
IE のサポート辛いです!

でも先月 2018 年 2 月のアクセス解析をみると

Windows10 (46.5%)
Chrome 64 30.3%
Chrome 6327.3%
IE 1113.3%

Windows7 (33.3%)
IE 11 30.0%
Chrome 63 26.0%
Chrome 64 23.3%

Windows8.1 (6.1%)
IE 11 29.9%
Chrome 63 28.1%
Chrome 64 24.1%

18% くらいが IE11!
ところで世界の平均は 6.9 % みたいです

IE で新しい機能動かすために事前に変換ってやること増えてますし デバッグもめんどうです
IE なら IE 自身で動くコードに変換して動かせばいいのに・・・

なんて思ってたら JavaScript 自身で JavaScript を変換するツールもありました

最新機能が使える

その機能を使ってこんなものを作ってみました

<script nomodule>
function loadLibraries(urls, cb){
var loaded = 0
var onload = function(){
if(++loaded === urls.length){
cb()
}
}
urls.forEach(function(url){
var scr = document.createElement("script")
scr.defer = false
scr.async = false
scr.src = url
scr.onload = onload
document.head.appendChild(scr)
})
}
function baberun(code){
var compat_code = Babel.transform(code, {presets: ["latest"]}).code
eval(compat_code)
}
function onready(){
var modules = Array.from(document.querySelectorAll("script[type=module]"))
modules.reduce(function(promise, e){
return promise.then(function(){
return new Promise(function(resolve){
if(e.src){
var request = new XMLHttpRequest()
request.open('GET', e.src)
request.send()
request.onload = function(){
baberun(request.responseText)
resolve()
}
}else{
baberun(e.innerHTML)
resolve()
}
})
})
}, Promise.resolve())
}
!function(){
loadLibraries([
"https://unpkg.com/babel-standalone@6/babel.min.js",
"https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.26.0/polyfill.min.js",
], onready)
}()
</script>

まずは、IE で動くように変換するライブラリを読み込みます
そのライブラリの機能でIEで使えるように変換して実行します
IE でだけこの変換をするために nomodule という機能を使ってます

使い方

<!doctype html>
<meta charset="utf-8"/>

<script type="module">
!(async () => {
const a = [...`${2**10}`]
alert(a)
})()
</script>

<script nomodule>
上のやつ
</script>

こういう HTML を書いて Chrome と IE で開きます
どちらも 「1,0,2,4」 とアラートが出るはずです

async、アロー関数、...演算子、**演算子、テンプレートストリング、const など新しい構文をいっぱい使ってみましたが IE でも動いてます
これで IE でも気にせずに新しい機能が使えますよ

でもちょっと不便なところもあって、対応してくれるのは JavaScript の ECMAScript という規格で決まってるところだけなんです
「div タグ消したい」→「.remove メソッド使おう」
「URL のページのデータがほしい」 → 「fetch 関数使おう」
というのはできません
このあたりの機能は Web 独自のものだからです
Node.js でも動く機能だけ使えるといえば分かる人にはわかりやすいかも

module について

自分でも後から困りそうなので module 周りについて書いておきます

モジュールとして JavaScript を読み込む新しい機能です
script タグに type="module" を指定すると使えます
「<script type="module"></script>」
こんな感じ

古いブラウザだと type="module" を理解できません
理解できない type だと何もしないという決まりがあるので IE だとこの script タグは無視されます

また nomodule というのもあります
「<script nomodule></script>」
module を使えるブラウザだと何もしません
module を使えない古いブラウザだと nomodule を無視するという機能もありません
なので nomodule は実行されます

まとめると
新 → moduleを実行してnomoduleを実行しない
古 → nomoduleを実行してmoduleを実行しない

上に書いた JavaScript は nomodule なので IE でだけ動くものです
有名なものだと IE だけですがそれ以外でもゲーム機のブラウザなど古いものだと実行されます
Edge、Firefox、Chrome、Safari、Opera では module 機能が使えるので実行されません

この nomodule の中で変換機能のライブラリを読み込みます
読み込めたら module が設定された script タグを取得します
それを順番に変換して実行していきます

こうすることで最終的に IE でも module の script が実行されています
このコードをブログに入れておけば、 IE で動かない新機能を使っても script タグを module にしておけば自動で実行してくれます