サマーインターン前につよつよになっちゃおうの会でWebフロントエンドのパフォーマンスについてLTした際の資料です
Web FrontendPerformance TuningShinobu Hayashi(@Shinyaigeek)@サマーインターン前にツヨツヨになっちゃおうの会
View Slide
About meShinobu Hayashi(林 仁)- Twitter & GitHub: @Shinyaigeek- Blog: https://shinyaigeek.dev しにゃいの学習帳 - 東大工学部三年- Web Developer - 就活中
AgendaWeb Frontend Performance tuning- 計測- 実践- やらかし- チューニング- 技術選定- 何故パフォーマンスに気を配るか♂ サーバーサイドのチューニング♂ モバイルのチューニング
計測
計測Core Web Vitals : Web で優れたUXを提供するために共通する重要な指標- Largest Contentful Paint: viewportにおいて, 最も大きな画像, テキスト(=主要なコンテンツ)のレンダリングに要する時間- First Input Delay: ユーザーの入力に対してどれくらい早く反応できるか- Cumulative Layout Shift: コンテンツを表示して, どれくらいがくってなるかcheck: https://www.youtube.com/playlist?list=PLNYkxOF6rcIDC0-BiwSL52yQ0n9rNozaF
計測ツール達- Web Vitals (Chrome 拡張): Web Vitalsを測ってくれる- LightHouse: Perfやアクセシビリティを測れる. 開発環境でも使いやすい- LightHouse CI: CI上でLightHouseを実行できる. metaタグの有無のチェックとかもやってくれる- CrUX: フィールドデータを取ってこれる etc…基本的にはフィールドデータ, ラボデータ見つつ, ローカル環境でチューニングしてLightHouse CIでregressionを防止する感じで進めていく※LightHouse等のスコアを過信しすぎるのも良くないかなと思います.ただチューニングの足がかりとして強い.
実践「よっしゃ, 計測方法はわかった. スコアの意味もわかった. でも具体的にどう改善していけばええんや??」-> ということで, このLTで実際にやっていきましょうこのアプリを早くします : https://22-si-demo.vercel.app/見てもらえればわかるのですが , 中身はごく普通のブログです構成はReact, WebpackでのSPAです施策については, LTではその意味について触れるだけにするので , 実装とかはGitHubのPRみてください
Runtime Cost, I/O Cost その前に...- Runtime Cost: ユーザー操作, setInterval等を受けての処理のコスト, あるいはレンダリングのコストcf: Runtime : Node.js, deno, browser(chrome, safari…), electron…v8, spider monkeyはengineRuntime Costが高いとなんかカクカク, もっさりしたアプリケーションになる- ⚡ I/O Cost: Input/Output処理のコスト. この場合サーバーとのReq/Resのやり取りのコストI/O Costが高いと, なかなか遷移しなかったり, ユーザー操作を受け取れるようになるまで(TTI)時間がかかったりするアプリケーションになる
個人的にはパフォチューではRuntime CostとI/O Costの二つを改善していくことを念頭に置けばやりやすいと思います- Runtime Cost DOMが大きくなりすぎないように (React, Vueなど仮想DOMを扱うライブラリを用いている時 ) 不要なre-renderは減らす 非同期処理はちゃんと扱う(あとjsのファイルサイズを減らせば parse, compile, execの内parse, compileというlong taskにかかる時間が減るため Runtime Costが減るという見方もあったりします )- I/O Cost⚡ file sizeを減らす⚡ 配信するコンテンツの優先順位をつける (preload, lazy load)⚡ fileを圧縮する(gzip, Brotli)⚡ Cache !! Cache!! Cache!!
実践
実践 < よし! https://22-si-demo.vercel.app/を計測だ!(Lighthouse ポチ
実践 < とりあえず I/O 見るぞ. chromeのdevtoolの Network tabポチ!!! < main.jsが10MB..デカすぎんだろ...よし!とりあえずJSのbuild sizeを減らすぞ!
実践(チューニング以前のやらかしを潰す) そもそもproduction buildしてなかった (これをしていないとminifyされなかったり,様々な最適化がなされなかったりする) 画像ファイルがbase64エンコードされてjsファイルに入ってる(webpackだとurl-loaderとかでやりがち) route-basedなcode splittingすらしてなかった(これをしてないと例えば /profile にアクセスした時レンダリングには不要な / のコンテンツまでロードしないとレンダリングされない)これらはチューニング以前のやらかし※ ちなみにここで書いたやらかしは実際に僕がやってしまったものです
実践 < 94点まで伸びた!!!!やらかしを失くすだけでちゃんとする場合も結構ある今回のような, ブログという小規模なアプリを意図的に重くしたようなケースは少ないと思うので, ここまで劇的に伸びるわけではないですが
実践 < よっしゃ!いよいよチューニングや! そもそも全てのブラウザに対してES5にtranspileしたコードを配信しなくて良くない??(differential serving) リソースの一部って読み込みの優先順位上げ下げして良くない?- - img preload attr
補足(differential serving)jsのコードはレガシーな環境でも動くようにbabel等でtranspileされるtranspileでコード量は増えるわけだけど, 全てのブラウザでtranspileしなきゃなの-> そうでもない, これを聞いているような人はchromeのconsoleでclass文など普通に実行できると思います
補足(differential serving)90%以上のブラウザがES6で書かれたコードを実行可能(https://caniuse.com/#feat=es6-module)-> モダンな環境にはモダンなJSを, レガシーな環境にはレガシーなJSを配信したいどうやんの ?- module-nomodule pattern- Feature Detection- User-Agent Sniffingin detail: https://philipwalton.com/articles/deploying-es2015-code-in-production-today/, https://nodaguti.hatenablog.com/entry/2020/04/18/184251
補足(Skeleton)Skeleton ? -> リソースがまだloadされてない間表示しておくもの身近なSkeleton YoutubeGitHub
実践 < よし!改善できた気がするから計測や!Lighthouse ビターン!!! < 表示は早なったけどまだもっさりしてる気もする
実践何故か空のでいっぱい!! (こういったのははわざと生み出した通常有り得ない例ですが)DOMはデカくなりすぎないように気を配りましょう- 表示するコンテンツが有限でいいとき : Pagination- 表示するコンテンツがユーザーインプットを受けて無限である時 (無限スクロール): virtualized(library: react-virtualizedhttps://github.com/bvaughn/react-virtualized)
実践(Reactで) 不要なre-renderingを避けるchrome extensionsの “React Developer Tools”を入れる -> devtoolを開く -> Profilerを開く -> ⚙をクリックして✅Highlihgt update when componentrenderにチェックをつけると componentがmount,re-renderされたタイミングでハイライトすることが出来る無駄なre-renderingを避けるためには- React memo- key props- stateを正しく運用する
他にもチューニングはいっぱい。。!- inline require- cache- img(webp, resize)- prefetch- idle- file comporession- HTML Streamingetc...
そもそもの話このアプリはSSRもSSGもClientSideでfetchとかもしてなくて, jsのなかに記事が全部埋め込まれている形式-> ブログならSSR, SSGすれば良いのでは??-> そもそもクライアントサイドにReactを持ち込む必要はあった??(JSXが欲しいだけなら, react-dom/serverでhtml生成するだけでもよい, あるいはPreactとかでやればjsのsize小さくなるのでは??)-> あるいはSvelte, lit-html, solid等の選択肢もある後で直したり移行したりはしんどかったりする-> ♂安易に決めちゃダメ
技術選定について
正直技術選定めんどくさいんじゃが。。 < そもそもフロントエンドは専門じゃないしできればこの辺お手軽にやりたいんじゃが。。個人的にはブログとかポートフォリオサイトならNext.js, Nuxt.jsはシステムに乗っかりやすいFWで, なおかつきちんと乗っかって利用していれば大げさにやらかすことも少ないのでオススメです記事の管理は外部のCMSに任せるJamStack Architectureはオススメです. Next.jsとかだったらボイラープレートとなるexampleを指定できて, それで結構簡単に作れます
何故パフォーマンスに気を配るの
なぜパフォーマンスに気を配るの「いいものを作れば売れるというナイーブな考えは捨てろ」-> (面白い | 役に立つ) (もの | サービス) だからと言って売れるとは限らないいいものをユーザーに届けるために- 広告- 有無を言わせぬデザイン- アクセシビリティへの配慮- パフォーマンス等々のアプローチも求められる動くことは前提としてそれを届けるために「動いたらいいや」のその先に行こう!!!!
興味がある人はとりあえず「超速!Webページ速度改善ガイド」, 通称超速本を読んでください ✍
ご静聴ありがとうございました