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

Next.js×Prisma×GraphQL×Supabase +WASMでブログを自作した話

yud0uhu
September 12, 2023

Next.js×Prisma×GraphQL×Supabase +WASMでブログを自作した話

Think ! FrontEnd by DMM #5 の登壇資料です。
https://dmm.connpass.com/event/291641/

yud0uhu

September 12, 2023
Tweet

Other Decks in Technology

Transcript

  1. Next.js×Prisma×GraphQL×Supabase
    (+WASM)でブログを⾃作した話
    ⼤坂 友

    View Slide

  2. © DMM
    自己紹介
    • 大坂 友
    • 2023年4月新卒入社
    • 所属:動画配信開発部プレミアムグループブラウザチーム
    • 出身:北海道
    • 趣味:映画鑑賞・旅行・アニメ・趣味開発 etc
    2

    View Slide

  3. © DMM
    今日お話すること・しないこと
    お話すること
    • なぜ自作したのか
    • 使用技術の紹介
    ⭕フロントエンド、BFF、WASM
    ❌マークダウンパーサーの仕組みについて
    3

    View Slide

  4. © DMM
    作ったもの
    4

    View Slide

  5. © DMM
    ブログの機能〜inspired Zenn〜
    5
    できること
    ⭕キーワード検索
    ⭕タグ検索
    ⭕記事の投稿
    ⭕GitHubログイン(自分のみ)
    ⭕記事の削除
    ⭕ダークモード
    できないこと
    ❌アイキャッチの設定
    ❌記事の公開予約
    ❌画像のアップロード

    View Slide

  6. © DMM
    6
    つくったもの
    yud0uhu.work

    View Slide

  7. © DMM
    使用技術
    7

    View Slide

  8. © DMM
    使用技術
    8
    JSフレームワーク / 言語
    Next.js / Type Script
    状態管理ライブラリ
    Apollo Client
    CSSライブラリ
    styled-components
    emotion
    mantine
    DB
    Supabase / Vercel postgress
    デプロイ先
    Vercel
    認証・認可
    NextAuth
    ドメイン取得
    Cloudflare Registrar

    View Slide

  9. © DMM
    なぜ自作したのか?
    9
      車輪の再開発が好き
    • フレームワークは中身がブラックボックスになりがち
    • 自作すれば、仕組みを理解しながらものづくりができる
    • 自作はロマンがある
    • Rustでマークダウンパーサーを自作して、
    WASM+Nuxt3+Viteで動かしてみた
    • Rustで作るリアルタイムOS

    View Slide

  10. © DMM
    ライブラリ選定について
    10
    コードファースト
    • 言語固有のコードで
    SDL(schema.prisma)を書いて、
    スキーマ定義ファイル
    (graphql.schema)を生成する方

    スキーマファースト
    • スキーマ定義ファイル
    (graphql.schema)から
    SDL(schema.prisma)を生成す
    る方法

    View Slide

  11. © DMM
    ライブラリ選定について
    11
    コードファースト
    • 言語固有のコードで
    SDL(schema.prisma)を書いて、
    スキーマ定義ファイル
    (graphql.schema)を生成する方

    スキーマファースト
    • スキーマ定義ファイル
    (graphql.schema)から
    SDL(schema.prisma)を生成す
    る方法

    View Slide

  12. © DMM
    GraphQLのN+1問題
    12
    • サーバ実装で発生しがちなパフォーマンス上の課題
    • GraphQLの強みは、クライアントが必要なデータのみをリクエスト
    し、一度に取得できること
    • この特性が原因で、N+1問題が発生する

    View Slide

  13. © DMM
    GraphQLのN+1問題
    13
    以下のようなスキーマについて考える

    View Slide

  14. © DMM
    GraphQLのN+1問題
    14
    以下のようなスキーマについて考える

    View Slide

  15. © DMM
    GraphQLのN+1問題
    15
    以下のようなSQLクエリが発行される

    View Slide

  16. © DMM
    GraphQLのN+1問題
    16
    • 1回のリクエストで、全ての作者を取得するクエリ(authors)が実
    行される(1回のリクエスト)
    • 各作者ごとに、その作者が投稿した記事を取得するために個別のク
    エリpostsが発行される(5回のリクエスト)
    計6回のリクエストが行われる(N+1)

    View Slide

  17. © DMM
    GraphQLのN+1問題
    17
    • スケジューラでクエリのバッチ処理を効率化する
    • キャッシュを活用してデータの再取得を最小限にする
    • N+1問題を考慮したORMを用いて解決する
    etc

    View Slide

  18. © DMM
    GraphQLのN+1問題
    18
    • スケジューラでクエリのバッチ処理を効率化する
    • キャッシュを活用してデータの再取得を最小限にする
    • N+1問題を考慮したORMを用いて解決する
    etc

    View Slide

  19. © DMM
    Prismaについて
    19
    • Graphqlと高い親和性を持つORM

    View Slide

  20. © DMM
    Prismaについて
    20
    • Prismaでは、モデル間のリレーションシップを簡単に定義できる仕
    組みが提供されている
    • Nested reads
    • Eager Loading
    • 一度のクエリで、全ての作者とそれぞれの作者が投稿した記事の情
    報を取得できる
    • リレーションのネスト構造が深すぎたり、大量のバッチ処理が必要
    となった場合は、N+1問題を完全に解決することが難しい

    View Slide

  21. © DMM
    Pothos(ポトス)について
    21
    • コードファーストにGraphQLサーバーの開発を行うためのライブラ

    • 元の名前はGiraphQL
    • 視認性・検索性の問題から改名された
    • Prismaと互換性があり、N+1問題の対策を強化することができる

    View Slide

  22. © DMM
    supabaseについて
    22
    • Firebase代替として注目されているOSSのBaaS
    • 以下の機能を提供している
    • Database
    • PostgreSQLベースのRDB
    • Authentication
    • Storage
    • Edge Functions

    View Slide

  23. © DMM
    supabaseについて
    23
    • Free Plan(従量課金なし)
    • APIリクエストは無制限
    • 500MBまでのデータベース、1GBのファイルストレージが利用
    可能
    • 最大5GBの帯域幅
    • 月間アクティブユーザーは最大50,000人まで
    • 同時リアルタイム接続の上限は200
    • リアルタイムメッセージの上限は最大2,000,000件
    • 7日間未利用の場合、サーバの一時停止
    • 作成できるプロジェクト数は2つまで

    View Slide

  24. © DMM
    supabaseについて
    24
    • Vercel Postgres(hobbby plan)との比較
    supabse free plan vercel postgres
    1ヶ月のAPIリクエスト数 無制限 30,000
    1ヶ月のストレージ容量 1GB 256 MB
    1ヶ月のデータ転送量 5GB 256 MB
    作成できるデータベース数 1 2

    View Slide

  25. © DMM
    supabaseについて
    25
    schema.prisma
    Schema
    Visualizer

    View Slide

  26. © DMM
    prisma+supabase所見
    26
    • 一つの共通言語(SDL)からGraphQLのスキーマ・DBのテーブルが
    一気に生成できて、ER図のビジュアル化ができるため開発体験が良
    かった
    • NoSQLのFirerestoreに対して、supabaseはPostgreSQLベースな
    のがうれしい
    • supabaseはFree planでも、個人開発の素振りに使う分にはほどよ

    View Slide

  27. © DMM
    WASMをVercelでビルドする
    27
    • ビルドツールはwasm-pack を採用
    • 静的アセットを生成するバンドラー
    • RustのコードからTypeScriptの型定義コードまでを吐き出
    してくれる
    • 内部でwasm-bindgenを利用して、JavaScriptからRust APIを
    呼び出すことができる

    View Slide

  28. © DMM
    WASMをVercelでビルドする
    28
    WASMとPrismaのビルドの設定を行う手順
    1. npx prisma generateを行うビルドスクリプトを書く
    2. vercel.jsonでそれを実行するように設定する

    View Slide

  29. © DMM
    WASMをVercelでビルドする
    29
    WASMとPrismaのビルドの設定を行う手順
    1. npx prisma generateを行うビルドスクリプトを書く
    2. vercel.jsonでそれを実行するように設定する

    View Slide

  30. © DMM
    WASMをVercelでビルドする
    30
    3. Vercelでビルドする

    View Slide

  31. © DMM
    Appendix
    31

    View Slide

  32. © DMM
    アクセシビリティ対策
    32
    • Next.jsのHTMLタグに動的にlangを設定する

    View Slide

  33. © DMM
    アクセシビリティ対策
    33
    • Next.jsのpagesコンポーネントは、デフォルトでタグと
    タグを定義してくれる
    • そのため、_document.jsを作成し、デフォルトのDocumentをオー
    バーライドしてカスタマイズする

    View Slide

  34. © DMM
    アクセシビリティ対策
    34
    • 今回はEmotionとstyled-componentsを使用しているため、以下の
    ドキュメントを参考にrenderPageのカスタマイズを行う
    • Routing: Custom Document | Next.js

    View Slide

  35. © DMM
    アクセシビリティ対策
    35
    スコアが改善された🎉

    View Slide

  36. © DMM
    ハイドレーションエラー対策
    36

    View Slide

  37. © DMM
    ハイドレーションエラー対策
    37
    ハイドレーションエラーはなぜ起こるのか
    • サーバーから事前にレンダリングされたReactツリーと、ブラウ
    ザーでの最初のレンダリング (Hydration/ハイドレーション) 中に
    レンダリングされたReactツリーの間に違いが生じたため
    • 今回のケースだと、classNameの不一致
    参考記事
    • hydrateRoot – React

    View Slide

  38. © DMM
    ハイドレーションエラー対策
    38
    ハイドレーションとは
    • サーバから受け取った「乾いたHTML」に、クライアントサイドの
    インタラクティブな機能を注ぎ込むこと
    ハイドレーションエラーとは
    • 「サーバから受け取った初期HTML」と「クライアントサイドJSが
    予期するHTML」が一致しない場合に起こるエラー
    参考記事
    • 7歳娘「パパ、ReactのHydration Errorってなんで起こるの?」 -
    Qiita

    View Slide

  39. © DMM
    ハイドレーションエラー対策
    39
    対策:Pre-rendering and Data Fetching | Learn Next.js を参考に、
    フックを使用してレンダリングのタイミングを意図的に制御

    View Slide

  40. © DMM
    40
    まとめ
    今後やりたいこと
    • LightHouseのスコア改善
    • アプローチ→FirebaseやGoogle Analytics、New Relicなどで
    モニタリング&改善の試作
    • 目標→スコアオール100点
    • 機能拡張
    • プロフィールページの作成など

    View Slide

  41. © DMM
    ご静聴ありがとうございました🎉

    View Slide