React + TypeScriptのtoCサービスでのIE対応の際にハマったことまとめ

はじめに

OHEYAGOの開発をしている田渕です。
去年の話になるのですが、OHEYAGOでInternet Explorer(以下IE)対応を行いました。

いろいろ詰まる部分があったので、知見として共有します。

経緯

リリース時には、IEの対応を完全に切って、IEでアクセスした場合には、推奨ブラウザについてのダイアログだけが表示されるという状態でした。

リリース後にアクセスを見ると、2%弱はIEからのアクセスでした。
つまり、IEに対応するだけでユーザーを2%弱増やせるわけです。十分やる価値はありそうという判断になり、IE対応を後から生やすことになりました。

babelの設定ファイルを書く

まずは何にせよbabelを通す必要があるので、設定を書きます。ここに関しては別の方が担当してくださったので、設定ファイルだけ貼ります。

module.exports = function(api) {
  api.cache(true);

  const presets = [
    '@babel/preset-typescript',
    '@babel/preset-react',
    [
      '@babel/preset-env',
      {
        targets: {
          edge: '17',
          firefox: '60',
          chrome: '67',
          safari: '11.1',
          ie: '11'
        },
        useBuiltIns: 'usage',
        corejs: 3
      }
    ]
  ];
  const plugins = [
    '@babel/plugin-proposal-class-properties',
    '@babel/plugin-proposal-optional-chaining'
  ];

  return {
    presets,
    plugins,
    babelrcRoots: ['.']
  };
};

デフォルトのbabelによるtranspileでは、

  • const enumに対応していない
  • Optional Chainingが使えない
  • Class Property Declarationsに対応していない

など、微妙なsyntaxの違いがあります。それぞれ、対応するライブラリはありますが、const enumはそもそも使うことをやめました。(union型のほうが利点が大きいと判断したため)
OHEYAGOの場合は、babel-plugin-const-enumbabel-plugin-proposal-class-propertiesの2つを導入して移行しました。

また、file-loaderのバージョンをv4.3.0以上にすると、esModules形式でSassファイルが読み込めるようになります。(書き換える量が減ります)

webpackの設定を変更する

ts-loaderでtranspileしていたところを、babel-loaderでtranspileとpolyfillを行うように変更します。

{
  test: /\.tsx?$/,
  use: [
    {
      loader: 'ts-loader',
      options: { 
        transpileOnly: true,
        happyPackMode: true 
      } 
    }
  ]
}

{
  test: /\.tsx?$/,
  use: [
    {
      loader: 'babel-loader'
    }
  ]
}

に書き換えます。
その際、babel-loaderではTypeScriptの型検査をしてくれなくなるので、Fork TS Checker Webpack Pluginの設定を変更します。

new ForkTsCheckerWebpackPlugin({
   checkSyntacticErrors: true,
})

また、Fork TS Checker Webpack Pluginを使わないCI上でのbuild時には、別でtsc --noEmitを実行するように設定しました。

うまくpolyfillできないライブラリを乗り換える

react-id-swiperは、polyfillを入れてもうまく動かないので、react-slickに乗り換えました。 react-id-swiperを使っている部分すべて書き換えます。

デザインの修正は必要になりましたが、react-slickのほうが活発に開発されていることも考えると、乗り換えは妥当な判断だったと思います。
また、コンポーネント化していたので、実際にreact-id-swiperを利用している箇所は2箇所で済みました。過去の自分にありがとう。

fetch APIの使用をやめてaxiosにする

ここまでで実際にコンパイルは通り、IEでも表示自体はできるのですが、非同期のAPI通信が全滅でした。

IEはfetch APIに対応していないので、whatwg-fetchでpolyfillを試みましたが、headersの解釈ができないようで、動きませんでした。

そもそもfetch APIを使わずに、axiosに乗り換えました。fetch APIを使っている部分すべて書き換えます。
API通信のClientを抽象化していたので、書き換える場所は最小で済みました。

CSSのGridを修正する

AutoPrefixerの設定でIEでもGridが使えるようにします。具体的には、postcss.config.jsに以下のように設定します。

const Autoprefixer = require('autoprefixer')({
  grid: 'autoplace'
});

ただし、現状では完全に対応しているわけではないので、autoplacementなどの一部の書き方は修正する必要がありました。

まとめ

babelの設定は頑張って書く必要がありますが、残りに関しては個別対応で動くライブラリを探す、という感じになりがちだと思います。

結局、依存ライブラリを減らしておくのと、変えても変更箇所が少なくなるように、ちゃんと設計をしておく、ということを日頃から心がけるのが重要だと身にしみて実感しました。