LoginSignup
87

More than 5 years have passed since last update.

Babel で IE8 対応する地獄

Last updated at Posted at 2015-03-16

IE8 対応が必要な JavaScript に Babel (+ webpack) を使っているんだけど、素直に書くと動かないところがあったのでメモ。

とある事情により Polyfill も叶わない環境を想定している。

大体これと同じ内容:

class を使うためには・・・

class を使ったコードを Babel に変換させると Object.defineProperties を使って class 相当を実現させようとする。しかし、IE8 以下の古い IE には Object.defineProperties が無いため、エラーになる。

IE8 でも class が使いたいときは、loose mode の es6.classes を使う:

class-test.js
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 とは:

lib.js
export function foo() {
  console.log('foofoo');
}
main.js
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

Loose mode · Babel

2つに分かれているので注意。

他にも

今回は困らなかったので紹介しないが、class での static method の継承が上手く行かない話や、getter/setter にも Object.defineProperty が使われる話が、Caveats · Babel に書かれている。

おわり。そもそも IE8 対応がつらい。

参考にしたもの

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
87