Svelte をIE11で動作させる

## はじめに

この文章は、[Svelte 環境構築まとめ](https://qiita.com/hidekatsu-izuno/items/ce5a5dd46886b0084e42) の続きです。環境構築の前提条件についてはそちらを参考にしてください。

そちらの文章でも触れましたが、Svelte 2系からはデフォルトでは ES6 のソースコードを出力するため、レガシーな環境……ようは IE11 で動作しません。

本稿では、Babel や様々な polyfill を用いて Svelte を IE11 対応します。

## Babel の設定

ここでは、Babel をインストールし、webpack に ES6 から ES5 への変換設定を行っていきます。

### Babel のインストール

Babel をインストールします。以前は、babel-preset-es2015 を使うのが一般的でしたが、現在はサポート環境に従って自動的に設定を行う babel-preset-env を使うことが推奨されています。

```bash
npm install --save-dev babel-core babel-preset-env babel-loader
```

### webpack.config.js への Babel 設定の追加

webpack.config.js に Babel の変換設定を加えます。テンプレートとなる html ファイルと js ファイルの両方に設定を追加します。

```javascript:webpack.config.js
  module: {
      rules: [
          {
              test: /\.html$/,
              include: path.resolve(__dirname, './src'),
              use: [
                  {
                      loader: 'babel-loader',
                      options: {
                          presets: ['env']
                      }
                  },
                  {
                      loader: 'svelte-loader'
                  }
              ]
          },
          {
              test: /\.js$/,
              include: path.resolve(__dirname, './src'),
              use: [
                  {
                      loader: 'babel-loader',
                      options: {
                          presets: ['env']
                      }
                  }
              ]
          }
      ]
  },
```

### package.json への対応ブラウザ設定の追加

ブラウザリストについては、babel-loader のオプションとしても指定できますが、postcss-preset-env など他のプラグインでも利用されるため、package.json に記載し共有できるようにします。[^browserlist]

```json:package.json
  "browserslist": [
    ">0.25%",
    "ie 11"
  ],
```

[^browserlist]: "last 2 versions" がよく使われていますが、これだと進みが早すぎ、ある程度シェアの残っているブラウザまで切り捨ててしまうため、">0.25%" の方がよいようです。

### babel-polyfill の追加

IE11 対応するには、単に ES6 から ES5 に変換するだけでなく Promise など各種ライブラリが必要です。方法としては、ソースコード自体を書き換えることで最小限の導入に留める babel-plugin-transform-runtime とグローバル領域にライブラリを読み込む babel-polyfill のふたつがあります。

最適化という意味では、babel-plugin-transform-runtime の方が望ましいのかもしれませんが、開発者コンソールから操作する際に困ることが多いので、ここでは babel-polyfill を使います。

まずは、babel-polyfill をインストールします。

```bash
npm install --save-dev babel-polyfill
```

次に、polyfills.js を作成し読み込みます。

```javascript:polyfills.js
require('babel-polyfill');
```

polyfill 自体は、プログラム自体には関係ないものとも言えるので、index.js から読み込むのではなく、webpack から読み込むようにします。

```javascript:webpack.config.js
    entry: {
        main: [
            './src/polyfills.js',
            './src/index.js'
        ]
    },
```

## その他の Polyfill の導入

Svelte そのものの動作については、Babel の導入だけで十分なのですが、IE11 には現在のブラウザであればサポートされているいくつかの機能が不足している部分があるため、それを補完します。

```bash
npm install --save-dev whatwg-fetch dom4 url-search-params
```

|ライブラリ         |説明                                                    |
|:-----------------|:-------------------------------------------------------|
|whatwg-fetch      |WhatWG の fetch 関数を導入します。                       |
|dom4              |DOM4 で導入された append メソッドや KeyEvent の正規化を行います。|
|url-search-params |WhatWG の URLSearchParams を導入します。                 |

あとは polyfills.js に追記するだけです。[^addition]

[^addition]: 他にも有用な polyfill があれば教えてください。

```javascript:polyfills.js
require('babel-polyfill');

// fetch() polyfill
require('whatwg-fetch');

// DOM4 ployfill
require('dom4');

// URLSearchParams polyfill
if (typeof URLSearchParams === 'undefined') {
  window.URLSearchParams = require('url-search-params');
}
```