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

選ばれたのは Next.jsでした - Next.jsによるServer Side OGP ⽣成 / Next.js was chosen - Server Side OGP generation with Next.js

選ばれたのは Next.jsでした - Next.jsによるServer Side OGP ⽣成 / Next.js was chosen - Server Side OGP generation with Next.js

isoken26 (LINE株式会社)
UIT meetup vol.11『フロントエンド紅白LT合戦』での発表資料です
https://uit.connpass.com/event/197740/

53850955f15249a1a9dc49df6113e400?s=128

LINE Developers
PRO

December 18, 2020
Tweet

Transcript

  1. 選ばれたのは Next.jsでした Isomura Kenjiro 2020.12.18 UIT meetup vol.11 「フロントエンド紅⽩LT合戦」 〜

    Next.jsによるServer Side OGP ⽣成 〜
  2. ࣗݾ঺հ

  3. ۀ຿ ࣾ಺޻਺؅ཧγεςϜ  ϑϩϯτΤϯυ։ൃ  +4ϓϩδΣΫτͷ54Խ  &&ςετ؀ڥͷߏங 会社:LINE Growth

    Technology 株式会社 所属:開発室 / UITチーム(GT) -*/&%&7&-01&3%":  ϑϩϯτΤϯυ։ൃ 役職:フロントエンドエンジニア 名前:Isomura Kenjiro 好きな技術:TypeScript, React @isoken26
  4. -*/&%&7&-01&3%":ͱ͸ • LINEが11⽉25⽇〜27⽇の3⽇間に渡って開催したオンライン技術カンファレンス • 9900+ Registered • 150+Sessions • 200+Speakers

  5. -*/&%&7%":Ͱ͸ηογϣϯຖʹ0(1ͷੜ੒Λߦ͍ͬͯͨ

  6. 150+セッション x (ja + en) 300+パーターン対応 -*/&%&7%":Ͱ͸ηογϣϯຖʹ0(1ͷੜ੒Λߦ͍ͬͯͨ

  7. 0(1Λಈతʹੜ੒͍ͯͨ͠ なぜこれほど多くのパターンに対応できたか

  8. 0(1ͷಈతੜ੒ͱ͸ 0(1ͷಈతੜ੒ • OGPの画像とかをページ毎に切り替えたい • OGP画像の動的⾃動⽣成

  9. 0(1ͷಈతੜ੒ͱ͸ 0(1ͷಈతੜ੒ • OGPの画像とかをページ毎に切り替える https://example.com/items/1 https:// example.com/items/2 https ://example.com https://example.com

    EXAMPLE SHOP EXAMPLE EXAMPLE EXAMPLE EXAMPLE EXAMPLE EXAMPLE EXAMPLE EXAMPLE EXAMPLE SHOP EXAMPLE EXAMPLE EXAMPLE EXAMPLE EXAMPLE EXAMPLE EXAMPLE EXAMPLE
  10. Ͳ͏΍ͬͯ΍Δͷ͔ 0(1ͷಈతੜ੒

  11. /FYUKTͷ443 ʢ͋Εɺ44(͸ɻɻɻʣ 0(1ͷಈతੜ੒

  12. https://expamle.com/item/3 https://expamle.com/item/2 https://expamle.com/item/1 0(1ͷදࣔͷ࢓૊Έ͓͞Β͍ • サーバ側へリクエストが⾏った時にOGP⽤の<meta>タグを含む htmlが⽣成されている状態 0(1ͷಈతੜ੒ OGP対応しているアプリ ②URLクロール

    ③response https://expamle.com/item/3 https ://example.com EXAMPLE SHOP EXAMPLE EXAMPLE EXAMPLE EXAMPLE https://expamle.com/item/2 https ://example.com EXAMPLE SHOP EXAMPLE EXAMPLE EXAMPLE EXAMPLE https://expamle.com/item/1 https ://example.com EXAMPLE SHOP EXAMPLE EXAMPLE EXAMPLE EXAMPLE ①URLが⼊⼒される ④OGPカードの⽣成
  13. ಈత0(1ͷੜ੒ /FYUKTʹ͓͚Δ44( 443ͷ࣮૷

  14. /FYUKTʹ͓͚Δ44( 443 ಈత0(1ͷੜ੒ • Next.jsではFile-System Routing • pagesディクトリ配下の構成(file名など)に基づいてroutingが構成 前提知識として •

    各ページのdefault exportされているReactコンポネントがページコンポネントとして renderingされる // pages/users/index.tsx const Users = () => { return ( <div>Users</div> ) } export default Users
  15. 44(͢Δʹ͸ ಈత0(1ͷੜ੒ そのままでいい

  16. 44(͢Δʹ͸ ಈత0(1ͷੜ੒ Next.jsはデフォルトでpages配下のページコンポネントをSSGによってpre-renderingします。

  17. // pages/users/index.tsx export default function Users({ users }) { return

    ( <ul> {users.map((user) => ( <li>{user.name}</li> ))} </ul> ) } // SSG with Data export const getStaticProps = async () => { const res = await fetch('/users’) const users = await res.json() return { props: { users, }, } } σʔλ෇͖ͷ44( ಈత0(1ͷੜ੒ • getStaticPropsという⾮同期関数をexportすること でデータをpropsに紐づけてbuildすることも • getStaticPropsはサーバーサイドでのみ実⾏され • getStaticPropsはブラウザからアクセスできない • getStaticPropsはビルド時のみ実⾏される
  18. 44(ͷܽ఺ ಈత0(1ͷੜ੒ • ビルド時のみにデータの取得を⾏うため、頻繁に変化のある データには向かない SSRという選択肢 LINE DEV DAYもデータが頻繁に更新される可能性があったため SSGは要件に合わなかった。。

  19. 443͢Δʹ͸ ಈత0(1ͷੜ੒ getStaticProps getServerSideProps リクエストごとに実⾏される ビルド時に実⾏される // pages/users/index.tsx export default

    function Users({ users }) { return ( <ul> {users.map((user) => ( <li>{user.name}</li> ))} </ul> ) } // export const getStaticProps = async () => { export const getServerSideProps = async () => { const res = await fetch('/users’) const users = await res.json() return { props: { users, }, } }
  20. 0QUJPOBMͳ࿩ ಈత0(1ͷੜ੒ getStaticPropsとgetServerSidePropsが宣⾔的に定義できる Next.jsではpage毎にCode Splittingが⾏われている 要件やシチュエーションによってSSG, SSRを完全に使い分ける事ができる Hybridなアプリケーションの構築が可能

  21. 443Ͱ0(1Λಈతʹੜ੒͢Δ ಈత0(1ͷੜ੒

  22. 443Ͱ0(1Λಈతʹੜ੒͢Δ ಈత0(1ͷੜ੒ セッション詳細画⾯のrouting pages/sessions/[id].tsx /pages/sessions/0000 /pages/sessions/2222 /pages/sessions/1111 [id].tsx 以下のようなroutingが可能になる (Dynamic

    Routes)
  23. 443Ͱ0(1Λಈతʹੜ੒͢Δ ಈత0(1ͷੜ੒ getServerSidePropsの実装 export async const getServerSideProps = (context) =>

    { // id === "0000" const { id } = context.query const res = await fetch(`/sessions/${id}`) const session = await res.json() return { props: { session }} } ①context.queryから[id]にあたるidを取得 ②idを元にセッションの詳細情報を取得 ②取得したセッション詳細情報をページコンポネントにpropsとして渡す
  24. 443Ͱ0(1Λಈతʹੜ੒͢Δ ಈత0(1ͷੜ੒ ページコンポネントSessionの実装 ①渡されたsession詳細データからogpImageUrlを`og:imageにセットする` ②渡されたsession詳細データからogpUrlを`og:url`にセットする ②データが紐付いたらDOMをrenderingする // pages/sessions/[id].tsx cosnt Session

    = ({ session }) => ( 〜 <meta property="og:title" content="..." /> <meta property="twitter:card" content="..." /> <meta property=“og:image” content={session.ogpImageUrl} /> <meta property="og:url" content={session.ogpUrl} /> 〜 ) ApplicationLayoutというラッパーコ ンポネントを省略している
  25. 443Ͱ0(1Λಈతʹੜ੒͢Δ ಈత0(1ͷੜ੒ // pages/sessions/[id].tsx cosnt Session = ({ session })

    => ( 〜 <meta property="og:title" content="..." /> <meta property="twitter:card" content="..." /> <meta property="og:image” content={session.ogpImageUrl} /> <meta property="og:url" content={session.ogpUrl} /> 〜 ) export async const getServerSideProps = (context) => { // id === "0000" const { id } = context.query const res = await fetch(`/sessions/${id}`) const session = await res.json() return { props: { session }} } export default Session; 全体
  26. ·ͱΊ Next.jsではSSGやSSRをとても簡単に実装できるためOGPの動 的⽣成も簡単にできる なんでもかんでもSSGすればいいのではなくてシチュエーショ ン、要件によってSSR,SSGを使い分けると良さそう ISR(Incremental Static Regeneration)など今回は触れなかった Next.jsの魅⼒的な機能がまだまだあるので今までNext.jsやっ たことない⼈の興味を持つきっかけになれたら嬉しいです。

  27. THANK YOU