Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

© DMM 作ったもの 4

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

© DMM 使用技術 7

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

© DMM Pothos(ポトス)について 21 • コードファーストにGraphQLサーバーの開発を行うためのライブラ リ • 元の名前はGiraphQL • 視認性・検索性の問題から改名された • Prismaと互換性があり、N+1問題の対策を強化することができる

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

© 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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

© DMM Appendix 31

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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