古いブラウザでウェブサイトにアクセスされた時、推奨ブラウザをインストールするように勧める画面を表示する


Motivation

  • IE 対応したくないけど、画面が真っ白になるのは避けたい
  • せめてサービスの紹介くらいは IE からでも見られるようにしたい
  • IE 対応したくない

TL;DR

  1. UA で判断せず、 window.Symbol !== undefinedtry { eval('async () => {}') } catch(e){} で判断
  2. モダンブラウザとそれ以外で js のエントリーポイントを分ける
    • Webpack なら multi entry
    • CDN 通してるなら、 js コードの共通化は考えないで、全部バンドルしよう
  3. .babelrc を2つ書く
  4. https://www.browserling.com で結果を確認

User Agent で判断しない

  • あなたが対応したいのはどのブラウザのどのバージョンのですか?
  • 明確に「このバージョンだけ対応できれば OK」と答えられるなら UA で判断しても良いが、多くの場合は「このコードを実行してもエラーが出ないかどうか」が知りたい
  • それを UA でひとつずつ確認していくのはしんどい
    • たとえ Chrome や Safari であっても、5年前からアップデートされていなければ、もはや別物

→ 実行時に確認する

実際に使ったコード(あなたのプロジェクトに合わせて変えください)


const requirements = ['Symbol', 'Proxy', 'URLSearchParams'];
const isOldBrowser = !requirements.every(key => key in window);

if (isOldBrowser) {
  // ここで古いブラウザ向けのビューを表示する
}
  • このファイルは Babel するので const なども使っています
  • Babel してないよという方は var にするなり every を for 文に置き換えるなりお願いします

どうやってこの3つに決めたのか

  • https://rollbar.com/ というエラーレポートサービスを使っている
  • 実際にブラウザ上で発生したエラーを見ながら付け足していった
  • そのため、これは正解でもなんでもない、当てずっぽうな実装でしかない
    • 機械的に判断する方法が思いつかなかっただけなので、良い方法があればコメントしていただけると嬉しいです

モダンブラウザとそれ以外で js のエントリーポイントを分ける

つまり、最終的にこうなっていることを目指す

<html>
    <head>
        <script src="モダンブラウザ向け.js"></script>
        <script src="それ以外向け.js"></script>
    </head>
</html>

Webpack

  • multi entry point にする
  • ソースのディレクトリを2つに分ける
    • 必ずしもこうする必要はないが、分けたほうが babel-loader のルールがシンプルになって良い
    • ここでは srcfallback の2つに分けた
module.exports = {
  entry: {
    for_modern_browser: './src/index', // 通常のアプリケーションのエントリーポイント
    for_other_browser: './fallback/index' // モダンブラウザ以外のエントリーポイント
  }
};

.babelrc を2つ書く

  • webpack.config.js
module.exports = {
  entry: {
    for_modern_browser: './src/index', // 通常のアプリケーションのエントリーポイント
    for_other_browser: './fallback/index' // モダンブラウザ以外のエントリーポイント
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        include: ['src']
      },
      {
        test: /\.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            // ↓ fallback ディレクトリ以下の js ファイルは fallback/.babelrc に基づいてトランスパイルする
            babelrcRoots: ['fallback']
          }
        },
        include: ['fallback']
      }
    ]
  }
}
  • fallback/.babelrc
{
  "presets": [
    [
      "@babel/env",
      {
        "targets": { "ie": "9" }
      }
    ]
  ]
}
  • 上記のコードは一部抜粋なので、コピペせず、実際のプロジェクトに合わせて使ってください
  • とくに、 fallback/.babelrcuseBuiltIn プロパティの設定は必須です

browserling で動作を確認

  • IE9 は Vista、 IE10 は Windows 7 でしか動かない
  • Windows 端末を持っていない場合は https://www.browserling.com を使うと良い