polymer-cli でビルドしたアプリケーションが Chrome 以外のブラウザで動かないときに確認すること

Polymer で作ったアプリケーションが Chrome 以外のブラウザで動かないとき、原因の 1 つとしては Polyfill がうまくロードされていない可能性があります。

<img width="1185" alt="スクリーンショット 2017-02-09 00.52.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/106258/5d5b41ba-8127-24eb-fb13-598e4088d1fb.png">

# polymer-cli の雛形
polymer-cli でアプリケーションの雛形を作ったとき、`index.html` は以下のような感じになります。

```html:index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">

    <title>hoge app</title>
    <meta name="description" content="hoge app description">

    <!-- See https://goo.gl/OOhYW5 -->
    <link rel="manifest" href="/manifest.json">

    <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>

    <link rel="import" href="/src/hoge-app/hoge-app.html">
  </head>
  <body>
    <hoge-app></hoge-app>
  </body>
</html>
```

ここで、`/bower_components/webcomponentsjs/webcomponents-lite.js` が Polyfill で、WebComponents API をサポートしてないブラウザでも Polymer で作ったアプリケーションが動くようにするライブラリなのですが、このまま `polymer build` しても、この `/bower_components/webcomponentsjs/webcomponents-lite.js` はビルドに含まれません:imp:！！！！！


# どうするか
Polymer のビルドの設定ファイルとして、`polymer.json` というものがあります。ここに依存ファイルとして `/bower_components/webcomponentsjs/webcomponents-lite.js` を追記すれば OK です。

`polymer.json` の書き方については私もよく理解してはいないのですが、 https://www.polymer-project.org/1.0/docs/tools/polymer-cli#build を参考に書いていけばいいでしょう。例えば私が作ったソートアルゴリズムを可視化するアプリケーション [^sort] の `polymer.json` は以下のような感じになりました：

[^sort]: デモ: http://kumassy.com/sort/ ソースコード: https://github.com/Kumassy/sort_visualizer

```json:polymer.json
{
  "entrypoint": "index.html",
  "shell": "src/sort-app/sort-app.html",
  "fragments": [
  ],
  "includeDependencies": [
    "bower_components/webcomponentsjs/webcomponents-lite.js",
    "bower_components/webcomponentsjs/webcomponents-lite.min.js"
  ]
}
```

このようにすれば、きちんと Polyfill が読み込まれ、Firefox などの他のブラウザでもうまく動くかと思います :blush:

# Polyfill の条件別ロード
公式サイト (https://www.polymer-project.org/1.0/docs/browsers) ではクライアントサイドで Polyfill が必要かどうか判別して、必要なときのみロードする方法が推奨されているので、やっていきましょう。

まず、`index.html` の `<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>` をコメントアウトしておきます：

```html:index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">

    <title>hoge app</title>
    <meta name="description" content="hoge app description">

    <!-- See https://goo.gl/OOhYW5 -->
    <link rel="manifest" href="/manifest.json">

    <!-- <script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script> -->

    <link rel="import" href="/src/hoge-app/hoge-app.html">
  </head>
  <body>
    <hoge-app></hoge-app>
  </body>
</html>
```

次に、公式サイトのソースコードをコピペします[^document-root]：

[^document-root]: よく見るとソースコードが公式サイトのものとちょっと違って、`'/bower_components/webcomponentsjs/webcomponents-lite.min.js'` ではなく `'bower_components/webcomponentsjs/webcomponents-lite.min.js'` としています。これはアプリケーションを GitHub Pages にデプロイするためです。

```html:index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">

    <title>hoge app</title>
    <meta name="description" content="hoge app description">

    <!-- See https://goo.gl/OOhYW5 -->
    <link rel="manifest" href="/manifest.json">

    <!-- <script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script> -->

    <link rel="import" href="/src/hoge-app/hoge-app.html">
  </head>
  <body>
    <hoge-app></hoge-app>
    <script type="text/javascript">
      (function() {
        if ('registerElement' in document
            && 'import' in document.createElement('link')
            && 'content' in document.createElement('template')) {
          // platform is good!
        } else {
          // polyfill the platform!
          var e = document.createElement('script');
          e.src = 'bower_components/webcomponentsjs/webcomponents-lite.min.js';
          document.body.appendChild(e);
        }
      })();
    </script>
  </body>
</html>
```

これで、Polyfill が不必要なブラウザでは余計なロードが発生しなくなりました :heart_eyes: