stylesheet

2017-03-17

chrome-extension を riotjs と shadow DOM で作成した時のメモ

作ったのはbackground.jsからexecuteScriptで表示中のタブにウィジェットコードを注入するchrome拡張。 キーワードはこんな感じ。

  • es6: 2017年だけれども。
  • riotjs: reactより簡単、軽量。
  • shadowDom: スタイルのカプセル化でreset.cssいらず。
  • yarn: ものは試しに速いと噂の。
  • gulp: タグコンパイルもbabelもwebpackもgulpタスクで。

以下、ハマりどころと対処法。vivaパワープレイ。

style-loaderがshadowDOMに非対応

style-loaderを使ってshadow-root内に直接スタイルを流し込めない。 一旦headにスタイルを流しこんでから、Shadow DOMスコープへstyleを移動させてなんとかした。

require('style-loader!css-loader!./shadow.css');
let style = document.querySelectorAll('head style').pop();
let shadow = document.querySelector('#app-container').attachShadow({mode: 'open'});
document.head.removeChild(style);
shadow.appendChild(style);

@font-faceがShadow DOMスコープで動作しない

Shadow DOMスコープ内では@font-faceは使えないようだ。 スタイルを分割して@font-faceの部分をShadow DOMスコープ外へ移動させた。

<head>
  <style type="text/css">
    @font-face {
      font-family: "Beautiful Font";
      src: url(data:application/font-woff2;base64,...);
    }
</style>
</head>
<body>
  ...
  <div id="app-container">
    #shadow-root (open)
    <style type="text/css">
      .beauty {
        font-family: "Beautiful Font";
      }
    </style>
    <p class="beauty">Beautiful!</p>

riotタグのスタイルはheadに追加される

tagファイルに記述したスタイルはheadに差し込まれるので、Shadow DOMスコープ内に反映できない。 ::shadow/deep/は廃止されたため、カスタムタグへ書いていたスタイルをShadowDOMへ注入するスタイルシートへ移動させた。

riotタグのonclickがDOMエレメントのonclickハンドラに登録される

カスタムタグに記述したonclick={foovar}がそのままDOMエレメントのonclickハンドラにセットされてHTMLElement.onclick = {foobar}な状態になった。

クリックすると当然エラー出力。
ただ、riotでaddEventHandlerもされているようで、動くことは動く。 extension経由でなければ発生しないので、chrome側でごちゃごちゃやってるようだ。

結果的にはonclickという属性名に反応してしまうようなのでriotjsへパッチを当てて回避。

- var EVENTS_PREFIX_REGEX = /^on/;
+ var EVENTS_PREFIX_REGEX = /^r-on/;

タグではonclick={foobar}の代わりにr-onclick={foobar}と書くようにする。 (実際にはpack済みのjsに対してgulpでreplace('/^on/', '/^r-on/')するようにした)

riotjs@3.3.1, google-chrome@57(beta)