Think ! FrontEnd by DMM #5 の登壇資料です。 https://dmm.connpass.com/event/291641/
Next.js×Prisma×GraphQL×Supabase(+WASM)でブログを⾃作した話⼤坂 友
View Slide
© DMM自己紹介• 大坂 友• 2023年4月新卒入社• 所属:動画配信開発部プレミアムグループブラウザチーム• 出身:北海道• 趣味:映画鑑賞・旅行・アニメ・趣味開発 etc2
© DMM今日お話すること・しないことお話すること• なぜ自作したのか• 使用技術の紹介⭕フロントエンド、BFF、WASM❌マークダウンパーサーの仕組みについて3
© DMM作ったもの4
© DMMブログの機能〜inspired Zenn〜5できること⭕キーワード検索⭕タグ検索⭕記事の投稿⭕GitHubログイン(自分のみ)⭕記事の削除⭕ダークモードできないこと❌アイキャッチの設定❌記事の公開予約❌画像のアップロード
© DMM6つくったものyud0uhu.work
© DMM使用技術7
© DMM使用技術8JSフレームワーク / 言語Next.js / Type Script状態管理ライブラリApollo ClientCSSライブラリstyled-componentsemotionmantineDBSupabase / Vercel postgressデプロイ先Vercel認証・認可NextAuthドメイン取得Cloudflare Registrar
© DMMなぜ自作したのか?9 車輪の再開発が好き• フレームワークは中身がブラックボックスになりがち• 自作すれば、仕組みを理解しながらものづくりができる• 自作はロマンがある• Rustでマークダウンパーサーを自作して、WASM+Nuxt3+Viteで動かしてみた• Rustで作るリアルタイムOS
© DMMライブラリ選定について10コードファースト• 言語固有のコードでSDL(schema.prisma)を書いて、スキーマ定義ファイル(graphql.schema)を生成する方法スキーマファースト• スキーマ定義ファイル(graphql.schema)からSDL(schema.prisma)を生成する方法
© DMMライブラリ選定について11コードファースト• 言語固有のコードでSDL(schema.prisma)を書いて、スキーマ定義ファイル(graphql.schema)を生成する方法スキーマファースト• スキーマ定義ファイル(graphql.schema)からSDL(schema.prisma)を生成する方法
© DMMGraphQLのN+1問題12• サーバ実装で発生しがちなパフォーマンス上の課題• GraphQLの強みは、クライアントが必要なデータのみをリクエストし、一度に取得できること• この特性が原因で、N+1問題が発生する
© DMMGraphQLのN+1問題13以下のようなスキーマについて考える
© DMMGraphQLのN+1問題14以下のようなスキーマについて考える
© DMMGraphQLのN+1問題15以下のようなSQLクエリが発行される
© DMMGraphQLのN+1問題16• 1回のリクエストで、全ての作者を取得するクエリ(authors)が実行される(1回のリクエスト)• 各作者ごとに、その作者が投稿した記事を取得するために個別のクエリpostsが発行される(5回のリクエスト)計6回のリクエストが行われる(N+1)
© DMMGraphQLのN+1問題17• スケジューラでクエリのバッチ処理を効率化する• キャッシュを活用してデータの再取得を最小限にする• N+1問題を考慮したORMを用いて解決するetc
© DMMGraphQLのN+1問題18• スケジューラでクエリのバッチ処理を効率化する• キャッシュを活用してデータの再取得を最小限にする• N+1問題を考慮したORMを用いて解決するetc
© DMMPrismaについて19• Graphqlと高い親和性を持つORM
© DMMPrismaについて20• Prismaでは、モデル間のリレーションシップを簡単に定義できる仕組みが提供されている• Nested reads• Eager Loading• 一度のクエリで、全ての作者とそれぞれの作者が投稿した記事の情報を取得できる• リレーションのネスト構造が深すぎたり、大量のバッチ処理が必要となった場合は、N+1問題を完全に解決することが難しい
© DMMPothos(ポトス)について21• コードファーストにGraphQLサーバーの開発を行うためのライブラリ• 元の名前はGiraphQL• 視認性・検索性の問題から改名された• Prismaと互換性があり、N+1問題の対策を強化することができる
© DMMsupabaseについて22• Firebase代替として注目されているOSSのBaaS• 以下の機能を提供している• Database• PostgreSQLベースのRDB• Authentication• Storage• Edge Functions
© DMMsupabaseについて23• Free Plan(従量課金なし)• APIリクエストは無制限• 500MBまでのデータベース、1GBのファイルストレージが利用可能• 最大5GBの帯域幅• 月間アクティブユーザーは最大50,000人まで• 同時リアルタイム接続の上限は200• リアルタイムメッセージの上限は最大2,000,000件• 7日間未利用の場合、サーバの一時停止• 作成できるプロジェクト数は2つまで
© DMMsupabaseについて24• Vercel Postgres(hobbby plan)との比較supabse free plan vercel postgres1ヶ月のAPIリクエスト数 無制限 30,0001ヶ月のストレージ容量 1GB 256 MB1ヶ月のデータ転送量 5GB 256 MB作成できるデータベース数 1 2
© DMMsupabaseについて25schema.prismaSchemaVisualizer
© DMMprisma+supabase所見26• 一つの共通言語(SDL)からGraphQLのスキーマ・DBのテーブルが一気に生成できて、ER図のビジュアル化ができるため開発体験が良かった• NoSQLのFirerestoreに対して、supabaseはPostgreSQLベースなのがうれしい• supabaseはFree planでも、個人開発の素振りに使う分にはほどよい
© DMMWASMをVercelでビルドする27• ビルドツールはwasm-pack を採用• 静的アセットを生成するバンドラー• RustのコードからTypeScriptの型定義コードまでを吐き出してくれる• 内部でwasm-bindgenを利用して、JavaScriptからRust APIを呼び出すことができる
© DMMWASMをVercelでビルドする28WASMとPrismaのビルドの設定を行う手順1. npx prisma generateを行うビルドスクリプトを書く2. vercel.jsonでそれを実行するように設定する
© DMMWASMをVercelでビルドする29WASMとPrismaのビルドの設定を行う手順1. npx prisma generateを行うビルドスクリプトを書く2. vercel.jsonでそれを実行するように設定する
© DMMWASMをVercelでビルドする303. Vercelでビルドする
© DMMAppendix31
© DMMアクセシビリティ対策32• Next.jsのHTMLタグに動的にlangを設定する
© DMMアクセシビリティ対策33• Next.jsのpagesコンポーネントは、デフォルトでタグとタグを定義してくれる• そのため、_document.jsを作成し、デフォルトのDocumentをオーバーライドしてカスタマイズする
© DMMアクセシビリティ対策34• 今回はEmotionとstyled-componentsを使用しているため、以下のドキュメントを参考にrenderPageのカスタマイズを行う• Routing: Custom Document | Next.js
© DMMアクセシビリティ対策35スコアが改善された🎉
© DMMハイドレーションエラー対策36
© DMMハイドレーションエラー対策37ハイドレーションエラーはなぜ起こるのか• サーバーから事前にレンダリングされたReactツリーと、ブラウザーでの最初のレンダリング (Hydration/ハイドレーション) 中にレンダリングされたReactツリーの間に違いが生じたため• 今回のケースだと、classNameの不一致参考記事• hydrateRoot – React
© DMMハイドレーションエラー対策38ハイドレーションとは• サーバから受け取った「乾いたHTML」に、クライアントサイドのインタラクティブな機能を注ぎ込むことハイドレーションエラーとは• 「サーバから受け取った初期HTML」と「クライアントサイドJSが予期するHTML」が一致しない場合に起こるエラー参考記事• 7歳娘「パパ、ReactのHydration Errorってなんで起こるの?」 -Qiita
© DMMハイドレーションエラー対策39対策:Pre-rendering and Data Fetching | Learn Next.js を参考に、フックを使用してレンダリングのタイミングを意図的に制御
© DMM40まとめ今後やりたいこと• LightHouseのスコア改善• アプローチ→FirebaseやGoogle Analytics、New Relicなどでモニタリング&改善の試作• 目標→スコアオール100点• 機能拡張• プロフィールページの作成など
© DMMご静聴ありがとうございました🎉