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

Next.jsで作ったブログ内に リンクカードを実装したときの知見

soso
June 24, 2023

Next.jsで作ったブログ内に リンクカードを実装したときの知見

soso

June 24, 2023
Tweet

More Decks by soso

Other Decks in Programming

Transcript

  1. @sosomuse
    Next.jsで作ったブログ内に

    リンクカードを実装したときの知見

    View full-size slide

  2. 作ったもの
    6 Next.js on Vercel(SG)の個人ブログにリンクカードを実装した

    View full-size slide

  3. 前提
    ™ Next.js v13 以前で作ったブログなので、App Router 対応してません(どこか
    で移行したい。ただし App Router でも Pages Router でもこの資料の内容に
    は特に影響しません。書き方ちょっと変わるぐらいのはず
    ™ このUIの呼び方は色々あり統一されていない(?)ようですが、本資料中で
    はZennに合わせてリンクカードと呼称します。
    ™ https://zenn.dev/zenn/articles/markdown-guide

    View full-size slide

  4. 作ってみた感想
    https://www.sososo.me



    自分のブログで作ったけど思ったより面倒だっY
    Qiita, Zenn, Twitterなどはクオリティ高いなと再認1
    なので実装に手間取った時に得た知見を話します

    View full-size slide

  5. アジェンダ
    2. リンクカードの基本構成
    3. OGPの取得とキャッシュ
    1. 自己紹介

    View full-size slide

  6. 自己紹介
    OSSコントリビュート: Storybook, i18next, ...etc

    最近はAWS CDKとAtCoderにハマってます。
    西村 爽 So Nishimura
    フロントエンド: Next.js

    バックエンド: Go

    インフラ: AWS
    @sosomuse

    View full-size slide

  7. アジェンダ
    2. リンクカードの基本構成
    3. OGPの取得とキャッシュ
    1. 自己紹介

    View full-size slide

  8. リンクカードの基本構成
    これらは で定義されている
    OGP
    サービスによって表示要素は異なるが、基本的に以下の要素で構成
    URL
    Title
    Description
    Image

    View full-size slide

  9. OGP(Open Graph protocol)
    あとはサイトのメタデータから抽出して表示するだけ!
    Title: `og:title`
    Description: `og:description`
    Image: `og:image`
    パラメータ
    https://ogp.me/
    Facebookが開発したメタデータのプロトコル
    大抵のWebサイトはこれに沿って自身のサイト情報を提供してくれている

    View full-size slide

  10. コンポーネント作成
    いい感じにコンポーネントを作る

    View full-size slide

  11. 完成?
    やった!完成だ!... ではない
    OGPの取得場所とキャッシュどうするの?

    View full-size slide

  12. アジェンダ
    2. リンクカードの基本構成
    3. OGPの取得とキャッシュ
    1. 自己紹介

    View full-size slide

  13. OGPの取得
    課題
    解決策
    OGPはHTMLのメタデータに定義されているので、取得するためには当然対象の
    Webサイトにアクセスしなければならない。

    OGP取得速度は対象のWebサイトへの表示速度に依存するので、最悪数秒かかる
    ことも想定される。

    クライアント側で取得するのでは遅すぎるし、APIサーバーで持つにしてもキャッ
    シュしたい。

    (クライアント側だとCORS問題もある)
    クライアント以外で取得してどこかにキャッシュを持つ

    具体的な解決策はいくつかありそうだが、個人ブログなのでコストは掛けたく無
    いしリソースも管理したく無い(APIサーバーとかは用意したくない)

    View full-size slide

  14. 他サービスの実装(1)
    Zenn
    Zennは開発技術がかなり公開されているので、こういった時非常に参考になりま
    す。

    現在も同じ構成かは分かりませんが catnose さんの当時の scrap によれば、
    CloudFunctionsでHTMLを生成して、iframeで表示。一定期間キャッシュしてい
    るとのこと。
    r https://zenn.dev/catnose99/scraps/381b3750099f49

    View full-size slide

  15. 他サービスの実装(2)
    所感
    エッジサーバーで取得・キャッシュしてから返すのが実装としては無難そうだ
    が、ぶっちゃけ個人ブログの1機能ぐらいであればエッジサーバーですら用意した
    くない。

    View full-size slide

  16. 解決策(1)
    最終的な解決
    SGでブログをレンダリングしているので、ビルドフェーズでメタデータを取得して最終
    的なHTMLを生成する。

    メタデータはキャッシュとしてJSONファイルでGitにコミットする。

    View full-size slide

  17. 解決策(2)
    解決策(2)
    解決策詳細(ビルドフェーズで以下の事を行う)
    uG 記事のMarkdownからURLを取得して、HTTPリクエストで対象サイトのメタデータ
    を取r
    ƒG 取得したメタデータをJSONファイルに書き込む(キャッシュ用e
    3G JSONファイルのメタデータを使ってHTML生s
    BG キャッシュ用JSONファイルはコミットする

    View full-size slide

  18. 解決策(2)
    解決策(3)
    ビルドフェーズのコード

    View full-size slide

  19. 解決策(2)
    解決策(4)
    以上でSGで表示できて、キャッシュされるようにもなりました

    View full-size slide

  20. 解決策(2)
    課題 & まとめ
    課題
    残った課題
    この処理だと一度取得したメタデータが一生キャッシュされるので、一定期間でパージするよ
    うな処理を入れないと元サイトのOGPが変わった時に追従されない。

    再生成スクリプトを用意してGitHub Actionsで定期実行するのが妥当かなーとか考えている
    が、やはり個人ブログの1機能のためにそんなリソースを持ちたくない。(まぁ、GitHub
    Actionsぐらいならいいかと思いつつ面倒なので放置してます...)

    OGPが変わる機会もそんなにないので、今はいいかなと思って放置している。

    View full-size slide

  21. 解決策(2)
    課題 & まとめ
    まとめ
    リンクカードの表示はHTTPリクエストが絡むので思ったより手間が掛かる
    SGであればビルドフェーズでリクエストしてしまえば高速に表示できる
    SGできないのであればエッジで処理するのが無難な選択肢

    View full-size slide

  22. ご静聴ありがとうございました

    View full-size slide