riot.js v3では画像が無駄に読み込まれているかも
アドベントカレンダー2021 Riot.js 7日目の記事です。
今更ですがriot.js v3でifディレクティブを使用する時の注意点です。
例とするケース
「表示」ボタンを押すと、画像が4枚されるというタグです。
実装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<riot-main> <button onclick="{ehToggle}">表示</button> <div if="{isShow}"> <img src="https://dummyimage.com/90x90/aaa/111.gif"> <img src="https://dummyimage.com/90x90/aaa/222.gif"> <img src="https://dummyimage.com/90x90/aaa/333.gif"> <img src="https://dummyimage.com/90x90/aaa/444.gif"> </div> <script> let tag = this; tag.isShow = false; tag.ehToggle = function(){ tag.isShow = !tag.isShow; }; </script> </riot-main> |
発生する問題
表示ボタンを押す前の、画像が表示されていない段階で、画像が読み込まれてしまいます。
通常、初期読み込み時点ではifディレクティブがfalseのため、画像部分のdomは生成されないので画像も読み込まれないと考えると思います。
しかしriot.js v3ではタグの解析のためにバックグランドで一度innerHTML的な処理を行い、domを生成してパースしています。
mount$1() -> createTag() -> mkdom() -> setInnerHTML()
その時点では解析前なのでifディレクティブは無視されdomが生成され画像が読み込まれてしまいます。
これでは画像部分を隠しておいても無駄な通信コストが発生してしまいます。
解決策
画像のURLを{}のテンプレート変数を使った文字列で指定します。
こうすると解析時は正しいURLでないからか、読み込みが行われません。
1 2 3 4 5 6 |
<div if="{isShow}"> <img src="{'https://dummyimage.com/90x90/aaa/111.gif'}"> <img src="{'https://dummyimage.com/90x90/aaa/222.gif'}"> <img src="{'https://dummyimage.com/90x90/aaa/333.gif'}"> <img src="{'https://dummyimage.com/90x90/aaa/444.gif'}"> </div> |
実際の動作
表示ボタンを押した後に画像が読み込まれ、正しく動作しています。
v4以降では問題なし
この画像が読み込まれてしまう仕様はriot.js v4以降では解決されています。
追記 2022-03-16
下記の様に属性値に{}が入っていれば読み込み時のみ属性名がriot-srcに変更されて画像にアクセスしない仕組みになっているようです。
<img src="/img/a.jpg{}">
通常のテキストで変換されないのはバクなのでしょうか。一応issue報告しておきます。
下記のあたりが関係ありそうです。
1 2 3 4 5 |
//function parseAttribs(内) if (RE_HASEXPR.test(v)) { if (k === 'value') { vexp = 1; } if (RIOT_ATTRS.indexOf(k) !== -1) { k = 'riot-' + k; } } |