Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SSG is a compiler

33ef4c1ebe619115b552db9a9f9a3509?s=47 sadnessOjisan
November 27, 2021

SSG is a compiler

33ef4c1ebe619115b552db9a9f9a3509?s=128

sadnessOjisan

November 27, 2021
Tweet

More Decks by sadnessOjisan

Other Decks in Technology

Transcript

  1. SSG is compiler Yuta Ide (@sadnessOjisan) JSConfJP2021

  2. SSG is like a magic

  3. None
  4. None
  5. None
  6. None
  7. SSG is your friend

  8. Agenda 1. SSG is useful 2. Inside SSG 3. Look

    back SSR
  9. Is SSG only for Blog / LP / Q&A ?

  10. 言葉の定義
 - SST
 - CSR
 - SSR
 - SSG 


    
 
 n番煎じな話なので詳細には立ち入りません。 
 それぞれのパフォーマンス上の特性は @takepepe さんの 「より速いWebを目指す Next.js」にまとまっており、こちらを参照してください。 
 また、これらは完全に分離できるものでもないことを断っておきます。 
 ex) template に react を CDN 経由で読み込んだものはどれ? https://speakerdeck.com/takefumiyoshii/nextjs-make-the-web-faster
  11. SST: Server Side Templating
 - Server で HTML Template に値を埋め込み、HTML

    を生成してクライアントへ返す
 - 素直な構成だと TTFB の遅さが問題になりがち
 - 一方で後述するCSRと比較し、通信の往復は減る

  12. CSR: Client Side Rendering
 - サーバーから取得したデータを元に、コンテンツの 描画をクライアントサイドで完結させる
 - TTFB は速いが、LCP

    を悪化させる要因を含む
 - コンテンツ描画のためにはクライアントでのデータ取得が 必要
 - HTML / Styling を生成する仕事はクライアントが担う 
 - コンテンツのアップデートにはHTMLを取得しなくて いいため SST より効率的になる

  13. SSR: Server Side Rendering
 - サーバーからテンプレートに値が埋め込まれた HTMLを受け取る
 - クライアントでそのHTMLは hydration

    される
 - hydration 後は CSR できる
 - SST における TTFB 周りのデメリットは引き継 ぐが、CSRの良いところを享受できる

  14. (re)hydration
 - dehydration
 - JS世界にあるVDOM を HTML に変換する処理 
 -

    SSR サーバーがクライアントにHTMLを返す 
 
 - (re)hydration
 - HTML を JS の世界で使えるように戻す処理 
 - Client ライブラリが実行する 

  15. SSG: Static Site Generation
 - サーバーはリクエストに対してHTMLを返すだ け
 - HTMLをリクエストより前に生成しておく
 -

    ビルド時の静的コンテンツとして固定されるデメ リットはある
 - しかしツールによっては hydration して dynamic な性質を取り込み、そのデメリットを回 避する 

  16. SSG: Static Site Generation
 - 歴史は長い
 - 2000年前半 Database Driven

    な Site への対 抗として SSG が注目される
 - props: DBアクセスの削減 / TTFB の削減 
 - cons: ページ数に応じたビルドコスト 
 - これまでに多くのツールが開発されている
 - 興味がある人は jamstack.org にあるまとめサイトを チェック 
 https://jamstack.org/generators/ 

  17. SSG: Static Site Generation
 現代的なSSG
 伝統的なSSG
 コンテンツから HTML を作る SSG

    したものを hydration する

  18. 伝統的なSSG
 - テンプレートからHTMLファイルを生成するツール
 - Markdown ドキュメント、画像などのアセットを元にコンテンツページを作り出せ る
 - 任意の言語が利用できる


  19. 現代的なSSG
 - SSR FW や JS ツールチェインの上に作られる
 - hydration +

    CSR の要素がある
 JS ツールチェインの上に作られることで、transpiler, bundler, compressor などの恩恵が受けられる 
 ex) Next, Gatsby, Nuxt, … 

  20. hydration ≠ JS FW
 - wasm によって任意の言語で SSR + hydration

    が可能
 - 技術的には hydration 付きの SSG も可能である

  21. SSG に対する批判
 全てが静的に決まらないと使えない
 Twitter を SSG で作れますか? 
 現代的なSSGでCSRすれば対処できるケースも多い
 EC

    の商品ページを静的生成、在庫はCSRで取得 

  22. Headless Comerce
 https://www.gatsbyjs.com/solutions/shopify

  23. SSG に対する批判
 全てが静的に決まらないと使えない
 Twitter を SSG で作れますか? 
 現代的なSSGでCSRすれば対処できるケースも多い
 EC

    の商品ページを静的生成、在庫はCSRで取得 
 要件によってはCSRでも難しい
 C to C のECでページ作成が頻繁、通報された商品はページごとは消したい 

  24. Look back SSR later

  25. Agenda 1. SSG is useful 2. Inside SSG 3. Look

    back SSR
  26. SSG is meta-compiler
 - Web performance 101
 - 2017年の Gatsby

    作者のブログ 
 - Gatsby is meta-compiler 
 - Gatsby は普通のサイトを速いサ イトへと変換する
 - Gatsby は webpack の設定ファイ ルを生成している
 https://www.gatsbyjs.com/blog/2017-09-13-why-is-gatsby-so-fast/
  27. Let's dive into SSG

  28. Chunk
 - SPA の問題の一つに bundle した JS が巨大過ぎるという問題
 - 必要なページに必要なパーツさえあればいいよね


    → chunk という単位でJSを分割する

  29. 大量の script は chunk が理由
 - 必要なページで、必要なchunk だけを使う
 - chunk

    は bundler の設定で作 る

  30. 複雑な名前はchunkの規則
 - ${key}-${hash}
 - app-44f67102fd3fe7d6ed63.js 
 - component---src-pages-inde x-jsx-b3759d3c0476f9883dba. js


    - commons-fa6c875ea4a0d1a31 7de.js
 - styles.80e97039b81d20471ead .css
 - hash があるとビルドごとに キャッシュを破棄できる

  31. chunk の作り方 (webpack の場合)
 - chunk 名に対して条件を書く
 - 条件設定の指針
 -

    ページごとに分ける 
 - 共通ライブラリをくくり出す 
 - 詳しくは @mizchi さんの「webpack chunk 最適 テク ニック」
 https://qiita.com/mizchi/items/418be9abee5f785696f0
  32. Gatsbyはどのような chunk か
 - `framework-${hash}`
 - React などの明らかにどのコンポーネントからも使うライブラリを共通の chunk にまとめる


  33. Gatsbyはどのような chunk か
 - `lib-${hash}`
 - module が 160kb を超えると別

    chunk

  34. Gatsbyはどのような chunk か
 - ページごとに chunk
 - 共通モジュールは chunk
 -

    重いライブラリは chunk
 - スタイリング系もchunk
 Improved Next.js and Gatsby page load performance with granular chunking
 https://web.dev/granular-chunking-nextjs/
  35. None
  36. navigate
 - 現代的な SSG では CSR として遷移できる
 - <a />

    ではなく <Link /> 
 - ex) @gatsby/reach-router 
 - 遷移先の chunk が必要

  37. prefetch
 - resource の先読み
 - A から B に遷移する前に B

    の chunk があれば即座に遷移可能
 - Gatsby の場合、<Link /> に hover したら chunk を取ってこれる

  38. Image optimaization
 - ビルド時に画像とHTMLを最適化
 - Size, Resolution
 - Tag: picture,

    source, lazy load 
 - Traced SVG: 小サイズのSVG placeholder を生成、画 像ロード時に差し替え 
 - JSConfJP の Speaker が分かりやすい
 - https://jsconf.jp/2021/speakers/ 

  39. Zero Runtime CSS in JS
 - VDOMからのスタイル生成はクライアントで行わ れる
 - React

    の style
 - CSS in JS lib: (ex) styled-component, emotion, 
 - LCP に影響あり
 - とはいえほとんどの場合は大丈夫 
 - ビルド時にCSSをHTMLに埋め込む
 - zero runtime xxx が流行 “静的に埋め込めるものは事 前に埋め込んでしまおう” 
 - ex) linaria, vanila-extract 

  40. Gatsby での Zero Runtime CSS in JS の実現
 - ビルド時に勝手に

    HTML に埋め込んでくれる (便利)
 - ただしランタイムでCSSを書き換える時は、CSS in JS ライブラリ環境下では対応するプラグイン が必要
 - gatsby-plugin-emotion など 

  41. How about Performance

  42. 手書きHTMLが最速?
 - 個人的な誤解: React / Next / Gatsby を使えば早くなる
 -

    They say “diffing”, “blazing fast”, … 
 - 駆け出しエンジニア時代、SPA はすごいことをしているという誤解をする 
 - 【翻訳】 2016年にJavaScriptを学んでどう感じたか ← これめちゃくちゃ面白い 
 - https://www.fendo181.me/entry/2016/10/26/172404 
 - 冷静に考えると・・・
 - 差分検知なんぞせず、手で直接実DOMを部分更新した方がエコでは? 
 - そもそもランタイムにReactライブラリを含めない方がエコでは? 

  43. Handwritten VS Gatsby

  44. Handwritten must have advantage in simple condition

  45. <p>Hello World</p> だけを比較
 手書きHTML
 Gatsby
 ランタイムのJSが遅れるものの、FCPには影響がない。


  46. 手書きが勝てない理由, FCP に影響がない理由
 - SSG (=静的化)しているのだから HTML に支払うコストは同じになる
 - ランタイムが膨らむと言っても

    chunk へのリンクが挟まれているだけで、それは async load されるのでブロッキングされない
 - Gatsby のビルドは自然と HTML が minify される

  47. Gatsby に嫌がらせをしてみた
 - Gatsby の遷移は CSR としての遷移
 - つまり、遷移を妨害すれば良い
 -

    遷移先の chunk を巨大にする 
 - 嫌がらせ chunk が分離されないように 1page component にベタ書く 
 - 巨大 prefetch 中に遷移する 
 20MB のDOM要素を用意しました <p>heavy_heavy_heavy_…</p>
  48. Gatsby に嫌がらせをしてみた
 手書きHTMLなら、HTMLごと遷移すれ ば先頭の表示はされる 
 Gatsby の場合、固まる 
 
 やったね!


  49. あ
 ほ
 く
 さ


  50. SSGした方が良い?
 - SPA (1HTML しかない CSR) に対してはライブラリの分の容量分のアドバンテー ジがある
 - SSG

    に対しては、SSG 側もライブラリ分の容量を HTML からは削るので差が出 にくい
 - ランタイムで動かしたいJSがあっても(ex カルーセル、モーダル)、別チャンクに 切り出せば HTML を読み込むコストとしての差は出ない
 - 別コンポーネントに分けて、2カ所以上から読み込む 
 SSGした方が良い
  51. Agenda 1. SSG is useful 2. Inside SSG 3. Look

    back SSR
  52. SSR, CSR の弱点、なぜ SSG は速いのか
 - 一番効いてるのは事前生成によるTTFBの削減
 - SSR はここが弱点


    - I/O
 - CPU負荷

  53. SSG の弱点
 大量コンテンツのビルド
 Incremental Build
 コンテンツの追加・削除・編集
 ISR
 DSG
 SSR +

    CDN
 弱点 対策
  54. Incremental Build
 - Gatsby のビルドモードの一つ
 - ビルド時の cache を使って、次回は差分のみをビルド
 -

    Gatsby Cloud でしか使えなかったが v3 でオープンに
 - とはいえ問題が根本的に解消はされない
 - うっかり cache を消した時のリカバリは? 
 - cache 全体に影響があるような変更が入ると? 
 - 運用者目線ではすぐにデプロイし直せる保証が欲しい 
 - DSG (後述)

  55. DSG: Deferred Static Generation
 - Gatsby v4~
 - ビルドタイミングを制御する機能
 -

    静的ビルドするパスを宣言できる 
 - ビルド時に生成しなかったページはユーザーの アクセス時に作られる = SSR 
 - CDNレイヤーにcache
 - アクセスされたページの HTML が static/ フォ ルダに作られるわけではない 
 - Gatsby Cloud を使う必要がある 
 - 使わなくても良い方法があるが、それは後述す る方法と同じやり方
 https://www.gatsbyjs.com/docs/conceptual/rendering-options/
  56. ISR: Incremental Static Regeneration
 - NextJS のモードの一つ
 - SSR と

    SSG のいいところ取り
 - 一度 SSR した HTML をキャッシュし、次回のアクセスからそれを返す 
 - 処理軽減
 - IO削減
 - stale な cache を返しつつ cache を fresh にできる 
 - (基本的には)Vercel 環境でしか動かせない

  57. That’s lock-in

  58. lock-in が嫌われている気がする
 - Vercel や Gatsby が素晴らしい機能を出すたびに lock-in が心配される
 -

    個人的には 「Vercel に乗っかりなよ」とは思うが、lock-in されたくない気持 ちも理解できる
 - よし、内製しよう
 - DSG / ISR のような動作は CDN で担保する 
 - SSR FW を自作すればいい 

  59. SSR + CDN
 - SSR した HTML を CDN に

    cache
 - 一番素直で FW や Hosting 環境にし ばられないやり方
 - cache の制御もしやすい
 - stale-while-revalidate => ISR 
 - vary
 - dynamic cache purging 

  60. FW を使わない SSR -とある実装を参考に- 
 - Best practice component library

    を作っておく
 - ビルド時にクライアントコードの最適化
 - chunk の作成
 - linaria の実行
 - NodeJS サーバーのエンドポイントで リクエストを待ち受ける
 - (p) react をサーバーで実行して HTML を作成
 - cache control header を設定して返す
 意外とシンプル
 preactとfastifyでSSR https://zenn.dev/takurinton/articles/4 c8625a43f024b
  61. FW を使わないメリット
 - ランタイムライブラリの選択が自由
 - 不都合なく preact が使える 
 -

    _app.js, gatsby-browser.js より細かい粒度で共通設定を書ける
 - ビルドチェインの拡張が容易
 - React app 以外のコードをビルド、SSR時に script tag で挟み込むといったことがやりや すい
 - 1 サービスを複数チームで育てる時に管理しやすい 
 - partial hydration
 - とはいえ Astro, Next12 も凄い! 

  62. FW を使わないデメリット、その指摘
 - FW を作ることに消耗したくない、案件を進めたい
 - Next の完コピを目指すと大変だけど、ただのSSRサーバーを作るだけならそこまでコスト はない
 -

    バックエンドの扱いは慣れていない
 - cache hit ratio を上げる 
 ※ と、ここまで偉そうに話しましたがほとんどが知人の実装やおかげです
  63. まとめ
 - 現代的な SSG は dynamic な要件に対応できる
 - SSG が内部でしていることはページの事前生成とパフォーマンスの最適化


    - SSG の辛さへの回答として、SSR で HTML を Generate して CDN で Cache
 - FW や PFM へのロックインが気になるなら自作できる