フロントエンドパフォーマンスチューニングができるやつ、モテるらしいぞ![レンダリングをスケスケにする編]
「この番組は、エンジニアの成長は楽しい学びからをモットーに、昨日より少し成長できる学びを届けるエンタメ系テックポッドキャストでございます」
「こんにちは」
「でございます。よいしょ。ということで、前回までのおさらい」
「お願いします」
「CoreWebVitalsが、えー、Webパフォーマンスの指標」
「はあ」
「うんうん。いろんな計測、いろんな計測ツールがある」
「うん。あ、ち、ちなみにちょっと質問していいですか、早速」

「はい」
「あの、前回のエピソードのうちにやっとけよっていう質問なんですけど」
「まじか。まじか、はい。えー、Web、えっと今話してるのって、フロントエンドのパフォーマンスの話ですか、それともユーザビリティの話ですか」
「えー、まあパフォーマンスとユーザビリティは紙一重だと思ってもらってください。あの純粋なスピードだけではないっす」
「ああ、はいはいはいはい」
「ユーザーが感じる快適さみたいなところっすね、どっちかっていうと」
「うん。前回の指標はだから多分そっちによってですね、そのユーザビリティによってて」
「うん」

「で、そのユーザビリティの中では、まあ結構やっぱパフォーマンスが占めてる割合が多いですと」
「そう」
「で、今日はパフォーマンスですか」
「で、えーっとね、基本的に改善するところはね、パフォーマンスの話がほとんどメインだと思います」
「ああ、はい。分かりました。お願いします」
「ということで、えー、まずですね、あのー、ま、パフォーマンスを上げるってなったときに、えー、できること、いっぱいあるんですけど」
「うん」
「じゃ、まず、えー、改善をしてくにあたってですね、一番大事なこと」

「はい」
「それはですね、ブラウザをよく知るということですね」
「うん。ブラウザをよく知る?」
「はい。まあ要はブラウザスケスケ能力。スケスケブラウザ」
「へー」
「なんか最近は、あれ?違うか。エディターか」
「はい。ん?エディター?」
「付けるのは。ブラウザ付けることはないっすね、あんまりね」

「ブラウザ付けたらね、見づらいっすからね」
「そうっすね」
「うん。だけど、じゃあさ、あのー、ページ表示するまでの流れってよく聞くじゃないっすか、なんかこう、特にWebの基礎とかでさ」
「うん」
「うん。まあサーバーにリクエスト送ったらレスポンスがこう受け取られて、で、ブラウザで描画されてるんですよみたいな」
「うん」
「そのブラウザで描画されてるんですよのところを解像度上げてく話っすね」
「おー、気になるなー」

「なので今日はちょっとまずね、レンダリングの話からしていきましょうか」
「はい」
「うん」
「はい」
「まだ、まだこれをすると速くなるような話に入らないんですね?」
「いや、えーと、ここ、うーん、この仕組みの中で何できるかをちょっと話していきます」
「ああ、なるほど」
「うん。まず、このレンダリングっていう動作、要はレスポンスを受け取ってから描画完了するまでのことをレンダリングっていうんですけど」

「うん」
「えー、これにおいてですね、えー、クリティカルレンダリングパスっていうのがあるんですよ」
「かっこいい」
「クリティカルパスでええやん」
「クリティカルレンダリングパスと呼ばれてます」
「レンダリングのクリティカルパスでええやん」
「そういうことです、でも」
「うん」

「まさにそのとおりです。で、絶対にこの道を通って、えーと、レンダリングが完了しますよっていう道があって」
「うん」
「で、ざっくり言うと。まずDOMツリーっていうのを作りますと」
「うん、聞いたことある」
「DOMツリーっていうのは、まあ、あのタグ構造あるじゃないっすか。で、あのタグの構造って実は木構造で書けるんですけど、まずはそういうふうにして、えー、計算可能な形にしますと」
「うん」
「で、続いてCSSOMツリーっていうのを作りますと」
「OM?」

「はい。まあ、あのDOMのCSSバージョンですね。DOMがドキュメントオブジェクトモデルで、CSS、えー、CSSOMは、えー、カスケーディングスタイルシートオブジェクトモデルツリーですね」
「うんうんうん」
「まあCSSにもDOMと同じようになんかこうツリー状のデータを裏で持ってるんですよ」
「うん」
「うんうん。で、えー、二つのツリーが今できあがりましたと」
「ちなみにちょっと質問いいっすか。CSSのツリーって」
「はい」
「どうツリーになってるんですか」

「なんて怖い質問をするんだ、君」
「プロパティがツリーになってるってことなのかな。その描画の順番ってのはいいな。あのプロパティの適用順があるみたいな話、前回のエピソードでされてたじゃないですか」
「はいはいはい」
「だからなんかプロパティにツリーがあんのかなってちょっと想像してるんですけど」
「うーん、これはでもクラスのたどり方なんじゃないかなって気がしてるんだよな」
「うん」
「セレクターというか」
「あー、なんかありますね、その、このCSS聞いてないよのときに」

「うん」
「実はその別の部分で定義してるCSS優先されてるよみたいな」
「うんうんうんうん」
「やつのお話してます?」
「いや、えっとね、もうちょいシンプルなところを言ってたけど、あのー、このクラスの中のこの要素みたいな」
「あー、はい」
「そんな感じでセレクター書いてくじゃないっすか」
「書いてきますね」

「おそらくあれと中身のプロパティをぶら下げてんじゃないかなって気がしてるんだけど」
「うんうんうんうん」
「そういうのをたどれるようにしてるんじゃないかなって気がしてるんですけど」
「うんうん」
「ちょっとこの内部構造までは調べてないっす」
「うん。今さくっとほんとかどうか分かんないけど、Geminiとかに聞けないっすかね」
「行ってみますか。うーん、ちょっと今さくっと調べたんですけど。まあこのCSSって継承実はされてるんですよ、裏でこっそり。例えばボディーでさ、フォントサイズとか指定したら、えーとその配下にあるタグ全部十六。例えば同じフォントサイズに継承されるんですよ」
「そうですね、はい」

「明治的に書いてなくても実は継承されてるスタイルがあって。で、そういうのを、まあなんか、あー、ツリー状にして分かりやすくしてるっぽい」
「うーん。うんうんうんうん」
「うん」
「ああ、はい、分かりました」
「だからこれ結構DOMと近しい形になるんじゃないかなって気がする」
「そうっすね」
「うん。でもDOMとは違います」
「うん」

「うん。で、このDOMツリーとCSSOMツリー、こいつらを合体させるんすよ、その次のステップで」
「別物だったっていう説明をせっかくしたのに一緒にするんすね」
「別物だったんですけど、えー、なぜ別物だったかっていうと、そのあと一緒にしてるから別物だったってことが分かったっていう、この、この順番なんですけど」
「そうですね。まあまあまあまあ、まあ絶対別物っすね」
「はい。つまりここで合体させてレンダリングツリーっていう、もう、なんだ、最強のツリーを作りますと」
「うん」
「で、こいつが、まあレンダリングの、まあ設計書だよね。で、えー、そのあとに、えー、レイアウトっていうフェーズがあります」
「うん」

「で、これは、えー、もう実際に描画のところに入ってるんですけど、要素の大きさを計算してどこに何を配置するかっていうのを計算する作業っすね」
「うんうんうん」
「で、最後ペイント、色塗って。完成ですと」
「まあ、びょ、びょ、描画ですね?」
「うん」
「うん。へー」
「まずこういう流れです。HTMLのツリーを作って、CSSのツリーを作って、えー、それらを合成した、あのー、最強ツリーを作って。それを元にレイアウトを計算して、えー、ペイントしてくっていう」
「うん」

「うん。まあざっくりとこういう流れになってますよと」
「うん。まあなんか、人間が絵描くときと一緒っすね。パーポとか。なんかざっくりレイアウト作って」
「あー、確かにね。俺もあのときよくDOMツリーとか作るわ」
「いや、気持ち悪。なんだそれ。どう、どういう、どういう育ち方したらそうなるんすか」
「右手で。左手でCSSOMツリー作って。うん。うーんってやる」
「間違えてるな」
「うん。ちなみにこれね、あのCSSOMなのか、CSSOMなのか、CSOMなのか、謎です」
「謎ですね?」

「はい」
「うん」
「謎ですね。一応、えん、あのAIに聞いたときにCSSOMだよって言われたから、CSSOMって言うんですけど」
「うん」
「たまにCSSOMって言っちゃう」
「あ、のりさんが?」
「うん」
「あなたの、あなたの都合じゃないですか、それは」

「これ俺のくせなんで、あのー、気にしないでください」
「うん。まあでもDOMっていうならね、合わせてほしいっすけどね」
「ねえ」
「CSSがね、なんかもうCSSで派遣取っちゃったから」
「うん」
「今更ね、OMさんがOMって言えなくなっちゃったっすね」
「そうなんですよ」
「はい」

「もうCSSもさ、CSSっていう単語に、単語と見なしてさ、もうCOMで良かったんじゃないかなっていう」
「あー、Cね」
「うん」
「確かに。全然それでいいね」
「ねえ」
「DとCでなんか仲良さそうだしね」
「いや、まあ隣だからね」
「隣だしね」

「でもね、隣だからといって仲いいとは限んないからね」
「ちょっと大人だな、のりさんのほうが」
「やっぱ逆にねっていうときもあるからね」
「そうっすね」
「で、まあさっき言ったこのクリティカルレンダリングパスが、まあその流れなんですけど」
「うん」
「まあこれをそれぞれ縮めればレンダリングの速度は速くなりますよと」
「うん」

「ってことで順番にいきますよ。まずDOMツリーの、えー、小さくし方」
「そんなんね」
「うん」
「ページシンプルにすればいいんじゃないっすか」
「まさにそれっす。だからHTMLを小さくする」
「うん」
「うん。DOMをね、無駄に増やさない。あのー、なんでこんなたくさんdivがいっぱい重なってるんですかみたいなのを作らない」
「あー、なるほどね」

「うん」
「うんうん」
「要は必要な量で作ろうっていうことっすね」
「うん」
「タグ」
「うん」
「あ、そ、そ、それって」
「うん」

「えっとー、ページのレイアウトを変えないでやるっていう話なのか、もうそもそもページのレイアウトリフォームしようぜって話なのかで言うと、どっちもですか」
「あ、いや、うーんと、まあそれはどっちも聞くと思う、もちろん。あのタグが減れば減るほどいいわけだから」
「うん」
「だけど、まあレイアウト変えたくないなら、なんか無駄なタグは作んないほうがいいんじゃないって思う」
「ああ、そういうことっすね」
「同じ、同じレイアウトでもさ、タグ三個でもできるときもあれば、タグをそれ同じのを一個でできたりもするじゃないっすか」
「うん」
「で、特に、あのー、まあHTMLってファイル数も多いんで」

「うん」
「やっぱなんか気づいたら謎のdivとかいっぱいある気がするんすよね」
「ああ、ありそう、ありそう」
「これなくてもいけねえみたいな、なんか無駄に深くなっちゃってるやつ」
「うん」
「まあそういうのは無駄に増やさないにしようねっていう」
「うんうん」
「うーん。そして、もう一つあります」

「はい」
「えー、同期的に読み込むJSを減らしましょう」
「うーん、なるほど」
「うん。で、えー、このDOMツリーの、えーと、制作って最初にやるじゃないっすか」
「はい」
「で、えーと、JSって、あの要素を変える可能性あるじゃないっすか、書き換えちゃう可能性」
「うん」
「なので、そのJS読み込まれると待っちゃうんですよ、このDOMツリー完成するのを」

「うーん、なるほど」
「そう。なので、例えば初期描画とまったく関係ないようなツール、ツールというかJSとかに関しては非同期で読み込むようにしてあげましょうねっていう」
「うんうんうん」
「うん。で、非同期にすればページ表示したあとにあとから、あのー、追っかけでダウンロードできるんで」
「うんうん」
「で、非同期にするのもめっちゃ簡単です。スクリプトの要素タグにDeferかASyncを付ける」
「うんうん」
「だけでいけます」

「うんうん」
「なんで基本的に。まあほとんど非同期になると思いますね」
「まあ同期である必要、あるのってなんだろうね、ずっとね」
「そう。で、え、代表的なツールだと、まあA/Bテスト用のツールとかね」
「ふーん。あ、最初に読み込みたいからってこと?」
「そう。A/Bテストって、えっと要はJSとかでAのパターンを出すかBのパターンを出すか決めるわけじゃないっすか」
「うんうん」
「だから最初に読み込んでないと、えー、あとからひ、非同期で読み込んだらレイアウトシフトみたいなことが起きるはず」

「うんうんうん」
「なんでこういうのを最初に読み込みましょうと」
「うん」
「まああとは、えー、なんか読み込み初期のエラーまでちゃんと監視したいよっていうような監視用のスクリプトとか」
「うんうんうん」
「は、えーと同期的に読み込む必要がありますと」
「うん」
「でもほとんどのJSは意外と同期的じゃなくても大丈夫だよっていう気がする」

「うん。そうっすよね」
「うん。ち、ちなみに」
「はい」
「あんまり分かってないだけなんですけど、そのへんってJSのライブラリが、あ、違うな、えっとウェブページって大体JSのライブラリで実装するじゃないですか」
「うんうんうん」
「で、そのスクリプト部分、スクリプトタグの部分ってJSのライブラリがよしなにやってくんないんですか」
「やってるんじゃないかな」
「ってことっすよね、多分ね」

「やってるんじゃないかな。どうなんだろうね」
「さすがにやってよ、ライブラリ。歴史長いし、そこそこって」
「うん、なんか」
「思っちゃうけど」
「バンドル、ビルドツールとかでやってるんじゃないかなって気がするけどね」
「だから今の話は割とHTMLベタ書きしてる人用ってことなんですかね」
「もしかしたら書かないといけないケースはあるかもしんないっすね。なんかそのライブラリを使っていても」
「まあライブラリのオプションでなんか入れなきゃいけないことがあるかもしれない」

「うん」
「デフォルトで非同期にしててほしい。が、どうなんでしょうね」
「まあライブラリはもしかしたらちょっとうまくやってくれるかもしんないんですけど。一旦そのへん、あの生成された、あのーページ見てみるといいかもしんないっすね」
「うん、そうですね」
「うん」
「それは確かに。まああとはそのスコアとか見れば」
「うん」
「別にね、スコア見て悪くなかったら別に気にする必要ないですし」

「まあそうね」
「うん」
「まあ悪かったらそこ見てみるといいってことっすね」
「そうそうそうそうそう。まあというのでDOMツリーを小さくするというか、えーとここの作成を早くする方法はまあこんな感じですと」
「うんうん」
「で続いてCSSOMツリー」
「うん」
「まあこれもねだいぶシンプルですよ」

「もうこれCSS減らすしかないでしょ」
「さようでございます。だから未使用のCSS消せよっていう話っすね」
「ああ、うんうんうん。うわあでもなんかなあ増えがちだなあCSS多分」
「ね」
「なんか消しづらいんっすよねCSSって」
「うーん」
「どこで使ってるかよく分かんないから」
「確かにね。あれしかもさなんかぐ、Chromeのツール使ってもさ、このページでは読み込まれてないけどほかのページでは使ってるよみたいな感じのことあるから結構ね」

「うーん」
「気を使って消さないといけないよね」
「うん。まあ今どきはね、もうAIがよしなにやってくれそうですけど」
「うん」
「数年前はなんか消せなかったなあ僕」
「うんうんうんうん。まあでも消したらもちろんここの描画は速くなりますよと」
「うん」
「あとね、えーメディアクエリの活用っていう方法もあって」

「なんですかそれは」
「C、CSSを読み込むときにメディアクエリ指定できるんすよ実は」
「メディアクエリってなんすか」
「ビューポートのサイズに合わせてさ、なんかレスポンシブ書くときとかさ、あのマックスメディアスクリーン、かっこ千六十八ピクセルみたいななんか書くじゃないっすか」
「はい」
「あれですね」
「で、それをやると?」
「で、えっとその画面サイズによって、えーとこのCSS読み込む読み込まないみたいなのを指定できるんですよ」

「うん」
「そのスタイル、スタイル自体じゃなくてもファイル自体に対してメディアクエリかけると」
「へー」
「で、これに書いておくと。CSSは結局ダウンロードはされるんですけど、最初の描画のときにレンダリングをブロックしなくなるんすね」
「ふーん」
「だから要は、えーまあ関係ないやつは一回後回しにできるっていう」
「うんうん」
「だから例えばPCで開いて、スマホ用のCSSは一旦あとに、後回しにするみたいなことができるっていう」

「なるほど」
「うん。で、あとね、セレクタをシンプルにするっていうのもありますね」
「シンプルにする」
「はい。だからこれの中のこれ、の、これの直下のこれみたいななんかあの入れ子にできるじゃないっすか、セレクタを」
「はい」
「CSSって」
「はい」
「あれやると毎回毎回そのたどってたどって計算するんで、あれ多いとCSSのツリー形成するのに時間かかります、計算量かかりますっていう」

「うんうん」
「だから、えっと理想はクラスを指定して、その一段階でたどれるようにするっていうのが理想的らしいっす」
「ふーん」
「この観点だと」
「なるほど」
「うん。で、えーあとね、ほかにもいろいろあるんですけど、クリティカルCSSっていうテクニックがあって」
「うん」
「ファーストビューに必要な分だけHTMLにスタイルタグで書き込むんすよ」

「ああ」
「うん。で、ほかのCSSは非同期であとから読み込む」
「うーん。そうすると?」
「そうすると、初期描画のときのCSSOMツリーの描画に必要なのがそのスタイルタグの部分だけで良くなるんで」
「うん」
「ここの初期描画速くなります」
「へー、どんぐらい変わるんだろう。あんま想像つかないな。なんか今んとこそんなに遅くなんないっしょって思ってるんすけど」
「まあこれは」

「結構変わるんすかね」
「どうだろうね。結構これ俺カリカリ、カリカリのチューニングレベルの話だと思ってるんですけど」
「やっぱそうですよね、多分ね。なんかそんなことよりもコンテンツとかのほうが重そう」
「うん。ぶっちゃけ見たことない」
「うん」
「現場では」
「うんうん」
「ここまでやってるところは」

「まあでもカリカリにやりたいときは」
「うん」
「ってことっすよね、確かに」
「そう。あとCSSで@import使用しないっていうのもありますね」
「へー」
「インポートすると、そのインポート読み込まれたときに追加で読み込みに行っちゃうんで。で、また通信発生して待つことになるんで」
「うん」
「まああんまりそれは良くないよねっていう」

「うーん」
「で、レンダリングツリー、ここに関してはね、まあDOMとCSSOMを、CSSOMが最適化できてればここでやるべきことは特にないっす」
「うんうんうん」
「足し算してるだけだから俺らの手に負えないというか」
「そうですね」
「うん。関与するとこではないって感じのイメージかな」
「うん。まあ材料はもう出し切っちゃってますもんね」
「うん。そうなんです。で、えー最後、画面描画のところで、まあレイアウトの計算してますと。まあ一応ここはな、何してるかだけ言いますね。まあまず、あのさっき言ったとおり配置計算しますよと。で、配置計算ももうちょい細かく言うと、まずビューポートのサイズが今どうなってるか、要は表示領域どうなってるかっていう確認して、えーさらに、えっと相対的な値を絶対値に変換してます」

「あのーH八十みたいなやつ?」
「H八十」
「八十じゃねえや、えーとなんかパーセントで」
「ああそうそうそう、パーセントとか」
「指定、指数みたいなやつとか」
「パーセントとかMとかRemとかそのへん」
「うんうん」
「とかは、えーと絶対値に変換してます」

「うん」
「で、このレイアウトの部分が実はめちゃくちゃ重い処理で」
「そんな気はする」
「うん。これなぜ重いかっていうと、上の要素変わると下の要素の位置とかが全部ドミノ倒しで変わってくんで」
「うん」
「結構このへんの再描画ってのは重たい処理になりますと」
「うん」
「で、これはでもただ、あのページ生成後も発生するというか。例えば普通にウィンドウをリサイズしたら発生するし。大きさ系のスタイルとかも動くようにしてしまうと発生するので。まあなるべく、うーん、まあアニメーションとかはこのレイアウト関係あるものとかは使わないほうがいいっちゃいい」

「うん」
「で、あと、えーと、あの指標の中にレイアウトシフトってあったじゃないっすか」
「はい」
「描画の段階だとここもちょっと気にする必要があって。えー画像ってさ、あの縦横いつも指定してます?ちゃんとウィスハイト」
「えーっと仕事で作るときは」
「ああ」
「プライベートなやつはあんまり気にしてない」
「そう。あれサイズ指定する必要があるのはレイアウトシフトしなくなるためですね」

「うーん」
「要は最初から画像の大きさ指定してれば、えー画像読み込んでなんかガクって大きさ変わることないので」
「うん」
「レイアウトシフト起きなくなって、まあユーザビリティ上がるというか。あのCoreWebVitalにプラスになるっていう」
「うんうん」
「で、あとはアニメーションはトランスフォームとかを使うといいよっていう」
「うん」
「なぜなら、えー最初のその配置計算のところをやんなくて済むので。まあまず処理的に軽いっていうのと。あと実はね、この、まあ最後のフェーズ、コンポジットっていうフェーズなんですけど、そのレイヤーを重ねたりするやつ。このフェーズだけGPU使うのでぬるぬる動くらしいっす」

「GPU使うんすか」
「らしい」
「GPUないデバイスとかどうすんすかね」
「そんなのないって言ってた」
「そうなの。ほんと?そうなのか」
「そんなのないって言われた俺、AIに」
「まあCPUでもやれることはないと思う」
「まあない場合はCPUでやるんじゃない?」

「うん」
「うん。まあというのがこの描画のフェーズですと。まあこれがあのレンダリングのところの、えーまず改善の方法ですと」
「はい」
「で続いて、えーリソースの読み込み。これもねいろんな戦略があります」
「うん」
「もちろん全部読み込んでページとして成り立ってるわけなんですけど。とはいえここも読み込み戦略大事ですと」
「うん」
「で、えー主に読み込み戦略はね四つの観点があります」

「はい」
「一つ目、遅延読み込みをちゃんとしよう」
「うん」
「これは、まあ一番分かりやすいのだと画像のレイジーローディングですね」
「レイジーローディング」
「レイジーローディングは、お、じゅんぺいくん答えたそうだね」
「違う違う違う、分かんないなと思って。だるい」
「ああそういうこと」

「はい」
「だるい、あだるい」
「レイジー」
「まあレイジー確かにね。怠け者みたいな意味っすもんねこれ。まあこれはあれですね、あとから読み込む画像とかに指定するやつですね」
「うん」
「多分あのネットワークタブとか開きながらねページをねスクロールすると分かりやすいんですけど。近くなったら画像を実は追加で読み込んでるんすよ、レイジーローディングしてるところは」
「うーん」
「でこのへんとかタグで簡単にできるんで。画像の遅延読み込みとかは、えー大事っすね」

「なるほど」
「基本的に」
「よくやりますね」
「あ、やるやるやる。ファーストビューだけ、えーと遅延読み込みせずにしといて。えースクロールしたら表示される領域を大体レイジーローディングにするかな」
「うん」
「で続いて、フェッチプライオリティAPI」
「優先度を取得するんすね」
「そう。まあHTMLというかさ、ページよ、描画のときってまずHTML読み込みます。でその中に記載されてるCSSとかJSとか画像を追加でHTTPでまた取り寄せてくるじゃないっすか。まあそれのダウンロード必要なリソースに対して優先順位を与えるのがこのフェッチプライオリティAPIってですね。まあブラウザの機能かなこれはどっちかっていうと」

「うん」
「なんでタグに、あの指定入れるとこのへんの優先度を決めることができるようになると。で後々出てくるテクニックで、まあJSを細かく分けるみたいなテクニックはあるんですけど。まあそういうのと組み合わせて最初に必要なやつだけ読み込んでおい、の優先度を上げておいて。で、まあ順番を操作することによって、まあ無作為にダウンロードするよりも効率よく感じるよねっていうことができるっていう」
「ふーん」
「で、まああともう一個は困る、よ、まあ読み込みとはちょっと違うかもしんないんですけど、画像の次世代フォーマットをちゃんと使用しようっていう」
「うん。なにそれ」
「WebPとか」
「WebP?あのW」
「WebPって書いて」

「へー」
「WebP?拡張子だね、画像の」
「うわ、知らんかもしれん」
「マジで?」
「はい」
「あ、いいね」
「いいね」
「いいね」

「いい。最近来てるんですか、磁気イメージの画像」
「いや、でも結構前から来てたんじゃないかな。何個かあったはずだけどね、なんかほかにも。ただ、何があるんだ、AVIFとか」
「ああ、iPhoneとかたまにそれですよね」
「え、マジで?」
「なんかスクショ?なんかしたとき、それになって」
「へー。あ、それ多分次世代のあれっすね。てかあのiPhoneさ、ヘイクとかになるない?なんか、HEICみたいな」
「ああ、はいはい」
「まあ要は圧縮効率がレガシーな画像ファイルよりもすごい圧縮できるっていう」

「うん」
「同じクオリティでも小さくなるよっていうやつっすね。で代表的なのがWebPかな」
「すげーな、Pingに比べて二十六パーセント小さくなります」
「そう」
「JPEGよりも二十五から三十四パーセント小さくなりますって。WebPのドキュメントに書いてる。すごい」
「そうなんですね」
「意味が分からない」
「でこれもうなんか昔はね、なんかこれ対応してないブラウザとかもあってなんかめんどくさかったんですけど、最近はもう多分ほとんど対応してると思うんで」

「うん」
「個人的にはもうWebP、WebP乱発してますね」
「うーん」
「WebPerです僕」
「WebPerっていうんだ」
「WebPを使う人」
「PingGarだったのじゃあ」
「うん」

「PingGarかJPGarだったんですか」
「JPGarだったんだけどね。今WebPerっすね」
「WebPerなんだ」
「うん。まあこのへんのあの読み込み戦略、遅延読み込み。とあと新世代フォーマットってのがまず、えーありますと。続いてリソースヒント」
「ヒント」
「はい。まあリソースヒントって言われて僕はあんま名前ピンとこなかったんですけど。プリロードとかプリフェッチとかプリコネクト、DNSプリフェッチって聞いたことあります?」
「あ、はいはいはいはい」
「あのへんのことをまあリソースヒントって言うらしいんですけど」

「へー」
「例えばプリロードだったら、今のページに必要な重要なリソースを、えー早く発見して事前に読み込むみたいな。とか」
「うーん」
「でプリフェッチは、プリロードにな、名前似てるんですけど、これは現在のページじゃなくて、えー次のページに必要なリソースをバックグラウンドでダウンロードしてキャッシュする機能っすね」
「うんうん」
「でプリコネクトとかDNSプリフェッチってのが事前にDNSの解決とかT、TCPのハンドシェイクみたいなのを事前に済ませておいて、え、いざ通信するときにちょっと早くできるみたいな。まあそういう機能ですと。まあこういうのを活用することで、えーなんかより先読みして、あのーリソースを読み込んでおいてキャッシュしておけるんで、えー早く動きますよっていう」
「うん。それはこっち、開発者側でやるものなんですね?」
「あ、そうですそうです」

「へー。でもこれどっちになってくれるんだと思うんすか」
「うーん、これ確かライブラリだったような気がするんだよな」
「うんうん」
「今は違うのかな。ブラウザに組み込まれたのかな。ちょっとそのへん怪しいな」
「うん」
「ブラウザの機能でしたこれ。なんでタグに、えっとーリソースに対して、えーどういう読みか、読み込み方の戦略したいかっていうのを自分で記述する感じになりますね」
「うーん」
「昔はライブラリだったらしいでも」

「うんうんうん」
「うん。昔はこれと似たようなことをJSで再現しようとエンジニアたちが頑張っていた時代もあった。が、今はブラウザネイティブの機能として追加されてますよっていう機能っすね、リソースヒント。で、これをさらに、あの進化させたやつがですね、スペキュレーションルールズAPIっていうのがあって」
「何すんの?」
「これはね、やることはめっちゃ近い。まずプリフェッチに至ってはかぶっている」
「うん」
「次のページのリソースをダウンロードしますと。であと、えーさらに進んだ機能でプリレンダーっていうのがあって。これは次のページの、もう描画まで裏でおら、終わらせておくっていう機能っすね」
「うーん」
「へー。JSの実行とかそういうのも含めて」

「すげーな」
「で、このスペキュレーションルールズAPI使うと、えー書き方が結構変わるんですけど。そのページ内にJSONを書くんすね、そのルールに沿って」
「うん」
「で、えープリフェッチするのはこの様子ですよ。プリレンダーするのはこの様子ですよみたいなことを書くことで、そこで一元管理ができるようになると」
「うん」
「でプラス、えー結構ブラウザ側でいい感じにやってくれてるんで。例えばブラウザの状況に合わせて、えーバッテリー節約モードだったりとか、まあネットワーク細い場合とかだと空気読んでやんなかったりとか」
「へー」
「結構最適化して使わせてくれるみたいな」

「ふーん」
「っていうのがこの最、もっと新しいスペキュレーションルールズAPIっていうやつですね。だからこれクリックとかホバーとかをトリガーにして実行とか、そういう細かい制御もできます」
「そこまでやることあるんだなあ」
「そう。だから、あの、しかもね、クリックもね、結構細かくて、あの、キーダウンだっけな。キーダウンじゃなくてなんけ、クリックのさ、あの、クリックってさ、押して離すがあるじゃん、セットとして、動きとして」
「クリックは押して離すことを指しますね」
「そう。で、その押した段階で読み込み始めるみたいな」
「押下した段階で」
「そう。次のリソースを読み込み始めるっていうふうにしたりとかね」

「へー」
「あとそもそも、えーとコンテンツにマウスが近づいたら読み込むとか、なんかそういうことができるっぽいっすね」
「細かー。そんなん設計超大変ですよ」
「ね」
「なんすか、その。エンジニアの真心で実装されるかされないかが決まるのか、それはひょっとして」
「真心で」
「うーん」
「そうね、これ真心、真心APIっすね」

「POとかデザイナーがそこまで細かく指定するわけないもんな」
「まあそうだね。だから、あのー真心でやるか、もしくは、あーこれもっと早くできないのっていう圧に負けてやるかのどっちかじゃないっすか」
「まあ負けてというか、対応してあげてというか」
「うんうん」
「へー。てかそんなことできんだ」
「そう」
「なるほどねー。勉強になるな」
「でこのへんとかは、あのー、まあデメリットとしては、あのー通信を、まあ無駄にしてしまうってこととか」

「うん」
「あとプリレンダーとかの場合だと、あのーアナリティクスの誤検知みたいなリスクもあるんで。そのへんちゃんと知った設定しないといけないっていうのはあるそうっすね」
「ふーん」
「まあこのスペキュレーションルールズAPIはね、結構新しいし、あの機能的にはおもしろいので、ぜひチェックしてみるといいかもしんないっす」
「うん。そうっすね」
「結構簡単に使えそうだったよ」
「へー。実験用のページとかあると楽しそうだけど」
「うん」

「スペキュレーションルールズAPIを使ってるやつは使ってないけど、同じページを描画させたときにこのぐらい違いますみたいな」
「あーやってみたいね、確かに」
「うん、あったらおもしろいけど。なんか作ってみてもそんな体感できる差にはならなそうだなって勝手に想像してるから気になる」
「激重のサイトならなんかありえそうな気するなあ」
「激重のサイト作んなきゃいけないってことっすよね、だから多分一旦ね」
「作業でござる」
「うん。でも激重のサイトだったら変わるでしょうね」
「うん。だって事前に読み込んでるんだからそれ早いよねっていう」

「うん」
「うん。であとラストね、あの最新のプロトコル使いましょうっていう」
「何?」
「HTTP3」
「あー」
「あーなるほど」
「うん」
「まあこれあのー」

「そんな早くなるのか、早くなるか」
「ん?」
「早くなるん、あ、早くなるんですね」
「あ、そうそうそうそう。特にあのHTTP2までってあのTCP使ってるんですけど。あれの順番保証がネックになっちゃってて。あの通信で順番変わるとなんか後ろの処理がブロックされるみたいな現象が起きてたんすけど」
「うーん」
「HTTP3はね裏側でUDP使ってるんで。でその上で」
「そうなんだ」
「あのしっかり作られてるんすよ」

「へー」
「使えるなら使ったほうがいいっていう」
「そうなんだ」
「まあでもこれあれだけどね、あのフロントと言いつつさ、結局じゃあHTTP3使えるようにするならあのサーバー側の設定いじる必要あると思うんで」
「まあそうっすね」
「うん。まあそういう方法もありますよと」
「へー。なんかフロントの話かと思ったらフロント以外も結局なんか横断的に考える必要がありそうですね」
「まあそうだね、確かに」

「うーん。まあどこでホスティングするとかも関係あるのかもしんないですし」
「ああまあそうね」
「うーん」
「まあちょっとキャッシュ戦略の話とかもあるんですけど」
「うん」
「まあキャッシュ戦略もあのブラウザキャッシュちゃんと使おうねみたいなところって結局レスポンスヘッダーでコントロールすると思うんで。サーバー側のほうの話だと思うし」
「うん」
「あとはまあCDN使おうねっていうのもあるけど。まあCDN使えばあの地理的に近いサーバーから配信できるようになるんで。早くなりますよ。しかもまあクラウドフロントとかならね、多分HTTP3使えるんじゃないっすかね」

「知らないけど使えるんじゃないっすかね」
「うん。使えるんじゃないっすかね、これ。であとラスト、JS効率化。これがね、あのー高速化の大枠のラストでございます」
「うん」
「ここはね、えーまず分かりやすいやつからでいうとコードの削減をしましょうと」
「うん」
「でコードの削減はいろんな方法があるんですけど、まずコードスプリッティングっていう、まあこう一個の巨大なJSにするんじゃなくて、えー分割して必要なものを読み込もうねっていうやつっすね」
「うんうん」
「で、まあページごとに分けるとか。あとボタンの動作に必要なコードとかだったら、あのボタンが表示されたタイミングでロードするみたいな。まあそういう遅延読み込みしたりみたいな」

「うんうん」
「まあ分割したあとに、まあそういう読み込み戦略を変えてくみたいなところで、えーとスピードを上げることもできますと。あとはビルドのときに、ビルドっていうか、まあバンドルか。あのー最近のJSだったら大体ビートとかWebPackとかなんかそういうバンドル扱って一個にまとめるとかやると思うんですけど。そのときにあのちゃんとツリーシェイキングっていう、使用されてないコードを自動的に排除する機能使ったりとか。あとはミニフィケーションっすね。ミニフィケーションピンときます?」
「分かんないですけどちっちゃくするんですよね」
「あ、そう。でもこれあの結構あのあれですよ、泥臭いっすよ。あの空白とか改行とかインデントをまずビルドツールが削除してくれたりとか」
「うん」
「コメントも削除して。で変数名、関数名短縮して」
「うんうん」
「であとね、こんなこともやってんだと思ったんだけどね、あの挙動を変えずに文字の少ない記述に書き換えることもやってるらしいっすよ」

「へー」
「例えばFalse?」
「え?」
「Falseってあるじゃないっすか」
「はい」
「Falseって五文字あるじゃないっすか」
「うん」
「だからびっくり一にするんすよ」

「あーなるほどね」
「そう」
「へー」
「まあでも静的にやってる感じですね、そのへんはね、多分ね」
「ん?」
「多分静的に変えてるんでしょうね」
「そう、これあのビルド時にやってるから。文字数少なくて同じ表現できるやつに変えるっていうこともやってるんですね」
「うんうん」

「うん」
「ちょっとびっくり一はやりすぎててびっくりしたけど」
「びっくりだけに」
「そう。これでも三文字削れますからね、これで」
「どんぐらい影響すんでしょうね。まあでも地理積もなんでしょうね」
「うん。だからあのーなんだっけ」
「いやー、あとどんぐらいかんのそれ」
「ビルド済みのさ、JS見てあれなんか全然読めねえよってなることあると思うんですけど」

「うん」
「まあそれはこのミニフィケーションやってるからっすね」
「うんうん」
「でJSの効率化でいうと、えーあとはねオフメインスレットっていう。まあメインスレット使うなよ、使うなよというかあのメインスレットじゃないところも使おうぜぐらいの感じかな、機能としては」
「うん」
「でJavaScriptってその言語の仕様としてシングルスレットで動いてますと」
「うん」
「だから重い処理が走るとこう画面がこう動かなくなったりするみたいな弊害が起きるんですけど。そういう重い処理をWebWorkersっていう機能がブラウザにあるので。そっちを使って重い処理を実行しようねと」

「ふーん」
「いう話でございます」
「WebWorkersはなんかスレットが複数いるんですね?」
「そう。メインスレットとは別のJS実行用のブラウザの機能になってて。ただメインスレットじゃないからある程度できない機能もあります」
「あ、そういうもんなんすね?」
「そう。DOMの操作とかWindowオブジェクトみたいなやつは、あのーそのワーカー上では使えない」
「あーなるほど」
「うん。なので表、表計算をね、あのぶん投げるといいっすね、WebWorkerには」

「うんうんうん」
「でただこれね、一つ問題点が実はあって。開発体験あんまり良くないらしいんですよ、WebWorkerで動くコード書くの」
「なんだ、デバッグしづらいみたいな?」
「えーとね。いやデバッグはどうなんだろう。ちょっとデバッグは分かんないんですけど、スパゲティコードになりやすいっていう。呼び出し方がとにかくなんかね、あんまり書きやすい感じじゃなかったんすよね、元々」
「あーそうなんっすね」
「うん。だからこのへんとかはその開発者体験あんまり良くないって言われてたんですけど。えーそこに踏み込んできたのがComLinkっていうね」
「会社?」
「あ、いやなんだこれ、ライブラリっすね。そのワーカーとの通信を簡略化できるライブラリみたいなのが出てきて。で、えーこれがあることでそのーワーカーで実行したい処理の呼び出しっていうのを楽に書けるようになりましたよっていうので。今だと開発体験も結構良くなってるんで。まあ重たい処理をそのメインスレットじゃないところに逃がしてあげる」

「うん」
「というようなことをして、えーパフォーマンスを上げるってこともできますよっていうのでね。すごいボリュームでしたね」
「ありがとうございます。すごい。もうスキル」
「そう、多すぎます。何回も聞いてください、これは」
「いいなあ、なんかこれ良きタイミングに。なんか自分のプライベートでやってるサイトを」
「うん」
「このエピソードを聞きながら。その聞いたことをそのままタイピングしてClaudeやっといてって言ってみてえな」
「あーいいね」

「うん」
「台本あげようか、このまま」
「あー確かにね」
「もうチェックリストで使えると思うよ、これ多分」
「イノビューさんというか、あのーなんだ、ひまプロのサイトにイノビューさんが文字起こししてくれるだろうから」
「うんうんうん」
「それを整形しつつ」
「あーそっか、確かにそれでいけるな」

「うん」
「うん」
「かはまあ自分たちでNotebookLMにこの音声食わせて」
「うんうんうん」
「言ってもいいかもしんないしね」
「確かに。まあ超多かったんですけど、まあとりあえずレンダリングの部分からリソース読み込み戦略からJSの効率化みたいなところまでを話しましたね」
「のりさん的に」
「はい」

「まずこの三つ見るかなぐらいのトップスリーとかあります?」
「ありますよ」
「お、教えてください」
「てかあの実際の運用みたいなところを考えたときに、多分パフォーマンスじゃあこれからやるよってなった、やる、やるよってなったら。まず最初に指標把握した上で計測する必要あると思うんすよ」
「うん」
「でその計測はまあ全エピソード、全エピソードというか前のエピソードで紹介したツールとかを使って計測してくとかいいと思いますと」
「うん」
「でその上で今日やった改善をやってくんですけど」

「うん」
「まあ着手順は明らかにこれ優先度あります」
「うん」
「まずステップ一はインフラ設定とか画像圧縮とかCDN、まあ要はCDN使ったりとかその画像次世代フォーマット使ったりとか。まあそういうロジック壊さずにできることをやったほうがいいと思います」
「うーん」
「なぜなら超安全だから」
「なるほど」
「ロジックが壊れないから」

「うんうん」
「まあ特に画像の次世代フォーマットはすごいいいんじゃないかなって感じっすね」
「ふーん」
「でステップ二がリソースの読み込み順序じゃないっすかね」
「うん」
「不要なJSをDeferとかASyncで、あの非同期で読み込むようにして。あとはFirstViewのところの、えーまあFetchPriorityのを上げる、高くする。でFirstViewじゃないところはレイジーローディングにするっていうこのへんっすかね」
「うん」
「でその上でステップ三でコードの削減みたいなところに取り組んでくと、えー安全に結構効果出していけるんじゃないかなって思ってます」

「うん。なるほど」
「うん。一番後回しでいいのは多分メインスレットの処理をWebWorkerに持ってくとかは一番あとでいいんじゃないかなって気がする」
「うーん」
「ピンときましたか」
「ちょっと、あの、聞き、聞き直します。はい。ピンときましたか」
「聞き直します」
「見る順番、見、はい」
「来てないやんけ」

「見る順番」
「第1声で聞き直しますわ」
「そうだね。多すぎたからね」
「まあ、まあでも観点、その、なんですか、全体はあんまり覚えてないっすけど。観点、その順番の観点とかは」
「うんうん」
「はい。なるほどってなってます」
「そうね。まずはロジック壊さないものからやってって、えー次第に危険なものに手を染めてくって感じっすね」
「危険なものに、はい」

「はい。まあというので今回はフロントエンドパフォーマンス、実際の改善編でございました」
「ありがとうございました。まあ」
「ありがとうございます。これを全部やればカリカリにできそうですね」
「これ結構カリカリになるよね」
「うん」
「うん。割とマニアックなとこまで行ったような気がする」
「なんかそこまでしなきゃいけないのかっていう気持ちになりました」
「じゃ個人的には自分の学びとしてはね。あのレンダリングもやっぱ細かく見るとこんなステップを踏んでるんだなっていうのを改めて知ることができてね」

「うん」
「興奮しましたね」
「おもしろかった」
「またちょっと個人的にはSpeculationRulesAPIめっちゃ使ってみたいなと思ったね」
「そうですね。てか、そう、もうなんか職人ですよね、もうそのへんってなんかベストプラクティスとかなさそうで」
「ベストプラクティス確かにな。うん。このページだったらこのタイミングで次読み込むのがいいんだよみたいなのがなんかもうページごとにありそう」
「てかまあサイト、サイトの性質によって変わりそうだよね、なんか」
「うん」

「うちのサイトは次ここに行く人多いんだよなみたいな感じでちょっとアナリティクスちゃんと見てないとあれかもしんないね」
「うん。まあなのでおもろいっすね」
「うん。のりさんの自分のプロダクトに時間あれば」
「うん」
「やろうかなみたいな感じなんすか」
「あーそれはちょっと思ってる。特に今作ってるサービスとか結構一本道で進んでくツールなんで」
「うん」
「先読み、リソースの先読みめっちゃ効きそうだなってちょっと思っている」

「なるほど。じゃあちょっとそのときはぜひ、はい、聞かせてください」
「うん。URL送りつけるわ」
「ツール使ってみろと」
「うん。だからチップ送れるよっつって」
「はい。ありがとうございます」
「って感じですね。ありがとうございます。はい。じゃあ締めますか」
「はい」
「はい」

「はい」
「えーこの番組では皆様からの感想であったりとかをSNS、Xで募集しております。ハッシュタグ、ひまじんプログラマー、ひまじんがひらがなでカタカナがプログラマー、違いますね。ひまじんがひらがなでプログラマーがカタカナで、えーぜひ投稿してください」
「お願いします」
「はい。また、えーもし我々にですね、質問したいこととか、えーもしくはなんか感想とか、えーこっそり言いたいこととかがあったら、えー番組の説明欄にGoogleのフォームがございますので、そちらからお送りいただけたら、えー丁寧に丁寧に丁寧に読ませていただきます」
「うーん」
「そして」
「なんかほんとはもう二つぐらい多かった気がする」
「もうなんか七回ぐらい言ってなかった?」

「七回か、六回とかだった気がする、はい」
「なんか想像の二回多いっていうイメージなんだよね」
「分かる」
「うん」
「なん、なんでこんな言えたんだろうっていうなんか」
「そう」
「普通の人間はもう少しキリのいいところで終わりそうなのにみたいな」
「そうね」

「回数でしたよね」
「そう。でもあれが逆にこう印象を残したからね」
「うん、そう」
「うん。センスですね、あれはね」
「僕も丁寧に丁寧に、丁寧に丁寧にやっていこうと思います」
「はい、お願いします」
「はい」
「また、えーオンラインコミュニティ、オンラインSlackコミュニティ、ひまプロ談話室というのを運営しております。こちらではエンジニア友達集めたい人とか、えーまあもしくは、えーなんか刺激を受けたいよって人が集まって刺激を受けたり受けられたりしている、えー軍団でございます」

「うん」
「えー興味ある方はこちらもですね、番組の、あーこちら番組の説明欄のところに、えー申し込み用のフォーム付いてますんで。そちらからお申し込みいただければ、まあ一週間以内を目処に、えー招待をお送り差し上げるので、そこから、えー招待から参加差し上げてください」
「難しい日本語」
「はい」
「はい、差し上げてください」
「差し上げてください」
「お願いします」
「またこの番組は各種プラットフォーム、えー間違いましたね。えーこの番組は、えー各種ポッドキャストプラットフォームで配信中ですので。えー参考になったよとか楽しかったよ、普通だったよって方はぜひとも、あの評価していただけると幸いでございます」

「いいねお願いします」
「はい」
「いいねとかないけど多分ね」
「まあそうだね」
「うん。でもいいねお願いします」
「スター、スター。はい、では、えー以上です。またね、次回。バイバイ」
「バイバイ」
「バイバイ」

「めっちゃフレンドリー」
「初めて触ったMacBook。思い出がいっぱいのチーム開発。再起動したら直った。謎のバグ。僕たち」
「私たちは」
「卒業します」
「駆け出しエンジニアを卒業したあなたへ。ひまじんプログラマーの週末エンジニアリングレッスン、各種ポッドキャストで配信中」