IE8 対応が必要な JavaScript に Babel (+ webpack) を使っているんだけど、素直に書くと動かないところがあったのでメモ。
とある事情により Polyfill も叶わない環境を想定している。
大体これと同じ内容:
class
を使うためには・・・
class
を使ったコードを Babel に変換させると Object.defineProperties
を使って class
相当を実現させようとする。しかし、IE8 以下の古い IE には Object.defineProperties
が無いため、エラーになる。
IE8 でも class が使いたいときは、loose mode の es6.classes を使う:
class Foo {
foo() { }
}
console.log(new Foo());
# ダメ
$ babel class-test.js -o t.js
$ grep 'Object.defineProp' t.js | wc -l
1
# こうする
$ babel class-test.js -o t.js --loose es6.classes
$ grep 'Object.defineProp' t.js | wc -l
0
loose mode はその名前の通り、コードが少なくなる代わりに ES6 の class の仕様とは少し違ってしまうので注意:
Method enumerability
Method assignment
Loose mode · Babel
Named exports を使うためには・・・
Named exports をする時、class
と同様の問題が起きる。Named export とは:
export function foo() {
console.log('foofoo');
}
import * as lib from 'lib';
lib.foo(); // => foofoo
というように foo
という名前を付けて export
する書き方。(きちんとした名前知らない。要調査。)
この lib.js
を babel にかけると:
$ babel lib.js
"use strict";
exports.foo = foo;
Object.defineProperty(exports, "__esModule", {
value: true
});
function foo() {
console.log("foofoo");
}
このように IE8 では使えない Object.defineProperty
を使ってしまう。
これは loose mode の es6.modules を有効にすると良い:
# ダメ
$ babel lib.js -o t.js
$ grep 'Object.defineProp' t.js | wc -l
1
# こうする
$ babel lib.js -o t.js --loose es6.modules
$ grep 'Object.defineProp' t.js | wc -l
0
こちらも副作用があるので注意が必要:
es6.modules
es6.modules
2つに分かれているので注意。
他にも
今回は困らなかったので紹介しないが、class での static method の継承が上手く行かない話や、getter/setter にも Object.defineProperty
が使われる話が、Caveats · Babel に書かれている。
おわり。そもそも IE8 対応がつらい。