#daiizメモ

Cosenseに夢中

Polymerをもっと格好良く使いたい

Polymerを使うときの現状

例えば、Polymerを用いて作ったカスタムエレメントを使うことを考えます。どのようなカスタムタグを使う場合であっても、HTMLの中で<link rel="import" href="">を書いて、Polymerやmy-elementのコードを読み込む必要があります。以下のように書きます。

<html>
    <head>
        <meta charset="utf-8">
        <title>Demo</title>
        <!-- カスタムタグを読み込む -->
        <link rel="import" href="bower_components/polymer/polymer.html">
        <link rel="import" href="bower_components/price-tax/price-tax.html">
    </head>
    <body>
        <!-- 読み込んだカスタムタグを使う -->
        <price-tax price="100" rate="8" switchable="true">商品A</price-tax>
        <price-tax price="300" rate="8" switchable="true">商品B</price-tax>
    </body>
</html>

linkタグに書かれたリソースは、タグがブラウザに発見され次第ダウンロードしてもらえます。この例では、head内に書いてあるので、bodyの解釈が始まる前にカスタムエレメントに必要なコードはすべてダウンロードされます。

気になりポイント

  • <link rel="import" href="">の部分が格好悪い。「<price-tax>というカスタムエレメントを作りました!使ってみてね!」と言わたら、importとかのことをあまり気にせずに、すぐ使えるようにしたい。
  • importしているpolymer.htmlprice-tax.htmlは、頻繁に更新される訳ではないので、ローカルから読み込みたい。

イデア1

Chrome拡張機能の機能に、「Content Scripts」というものがあります。これは、Chromeにインストールされた拡張機能が、ユーザーによって表示されている(閲覧されている)ウェブページに対して独自にレイアウトなどを追加できる機能です。これを使って、先の気になりポイントを少しだけ解決してみました。

PolymerをChrome拡張側から提供する

代表的なPolymer Elementsのコードをバックグラウンドで提供するだけの拡張機能を導入することで、HTMLを<link rel="import" href="">を宣言せずに、以下のように書けるようになります。

<html>
    <head>
        <meta charset="utf-8">
        <title>Demo</title>
        <!-- linkタグは不要!!!! -->
    </head>
    <body>
        <!-- 拡張機能で読み込んだカスタムタグを使う -->
        <price-tax price="100" rate="8" switchable="true">商品A</price-tax>
        <price-tax price="300" rate="8" switchable="true">商品B</price-tax>
    </body>
</html>

拡張機能のメインファイルは以下のようになっており、

/*
 * ふだん <link rel="import" ~> で読み込んでいるリソース
 */
var uris = [
    "bower_components/polymer/polymer.html",
    "price-tax.html"
];

// linkタグをheadに追加する
uris.forEach(function (uri) {
    var link = document.createElement('link');
    link.rel = 'import';
    // 拡張機能パッケージ内のファイルのURLを得るには、
    // chrome.extension.getURLメソッドを用いる。
    link.href = chrome.extension.getURL(uri);
    link.onload = function(e) {
        console.info('Loaded Polymer.');
    };
    link.onerror = function(e) {
    };
    document.head.appendChild(link);
});

動的にlinkタグを生成して、表示中のページのheadタグ内に追記しています。

試作品

GitHubで公開しています。デモの実行を終えたら、アンイントール or 機能OFFにするのをお忘れなく。

github.com

課題

  • 読み込みのタイミング
  • 当然ですが、すべてのカスタムエレメントを網羅できないこと

manifest.jsoncontent_scriptsフィールドには、いまは

{
    "matches": ["http://*/*", "https://*/*"],
    "js": [
        "bower_components/webcomponentsjs/webcomponents.js",
        "main.js"
    ],
    "run_at": "document_idle"
}

のように書いていますが、これだとPolymerコードの提供タイミングが遅くなってしまい、表示時に一瞬レイアウトが崩れてしまいます。

{
    "matches": ["http://*/*", "https://*/*"],
    "html": [
        "bower_components/polymer/polymer.html",
        "bower_components/price-tax/price-tax.html"
    ],
    "run_at": "document_idle"
}

上のような記述で、<head>の読み込みが完了した時点で、content scriptから直接htmlを読み込むことができるようにな仕組みができると嬉しいです。🍣

イデア2

HTMLを以下のように書いて、ブラウザが勝手にbower installみたいなことをやってくれるようになったらもっと気軽にカスタムタグを使えるようになると思った。<daiz713.price-tax ~>という記法は、「https://github.com/daiz713/price-taxにカスタムエレメントのメインファイルがあるよ!」と教えてあげるアイデアです。

<html>
    <head>
        <meta charset="utf-8">
        <title>Demo</title>
        <!-- linkタグは不要!!!! -->
    </head>
    <body>
        <!-- カスタムタグの入手先を教えてあげる記法 -->
        <daiz713.price-tax price="100" rate="8" switchable="true">商品A</price-tax>
        <daiz713.price-tax price="300" rate="8" switchable="true">商品B</price-tax>
    </body>
</html>

このHTMLを、一番最初に書いたHTMLにトランパイルする作戦で何かデモを作ってみたい。でもこれだとHTMLを書くのはラクになるけれど、最終生成物は現状と変わらないことになるので微妙です。🍣