tl; dr
- Next.js 13 でフルスタックアプリを作った
- Supabase と Vercel はインフラを任せてしまおう
- DB, 認証, デプロイをボタンポチポチで完結
- Supabase, Next.js用の helper ライブラリ が すっっごい便利
- Next.js (RSC)は 少し昔の Rails になる
- フロントからバックエンドまでこれ一個で完結する
作ったもの
- ひとり用のSlack, Twitterのように、作業ログを時系列に記録できるアプリが欲しかったので作った。
- slackで分報 xx_times をやってる人におすすめ。
- マークダウン記法に対応,
code
やリストでメモれる。 - ハッシュタグで関心ごとで分離
- Google アカウントでログイン
- 投稿前に、1つ以上タグを作る必要があります。(TODO fix)
ソースコード
- コード公開します
- リファクタリングのアドバイスなどがあればぜひissue投げて欲しいです。アプリ使ってみた報告でも!
主なstack
- Next.js 13
- App directory
- useSWR
- data fetch & cache for client component
- tailwind css
- react-markdown
- typescript
- supabase: DB, 認証, 認可(RLS)
- vercel: deploy
開発のポイント
Next.js
ディレクトリ管理
今回切り分ける軸は,DBモデル とpathの2つがあった。画面に関するものは,pathを基点にcomponentsを分けた。データ操作に近いものに関しては、モデルごとに分けていいかも。
src
├── actions
│ ├── hashtagActions.ts
│ └── postActions.ts
├── app
│ ├── (index)
│ │ ├── components
│ │ │ ├── Landing.tsx
│ │ │ └── screenTop.webp
│ │ └── page.tsx
│ ├── api
│ │ └── posts
│ │ └── route.ts
│ ├── auth
│ │ ├── callback
│ │ │ └── route.ts
│ │ └── logout
│ │ └── route.ts
│ ├── favicon.ico
│ ├── layout.tsx
│ └── logs
│ ├── components
│ │ ├── HashTags.tsx
│ │ ├── PostContainer.tsx
│ │ ├── PostForm.tsx
│ │ └── PostList.tsx
│ └── page.tsx
├── db.ts
├── middleware.ts
└── styles
├── gfm.css
└── globals.css
App Directory
- Next.js 13 App Directory の Server Componentでは,
await
でデータフェッチ後に, 静的なページレンダリングを行うことができる。
const ShowPage = () => {
const data = await fetchData();
return <>{data}</>;
};
- Client Component (昔からのブラウザランタイムで動くコンポーネント) を使う際は
'use client'
と明示する。 - 公式Docが分かりやすいので一通り仕組みを理解する。
Server Actions
- jsを使わないフォーム送信ができる
- actionをコンポーネントから呼び出すと, 自動でAPIエンドポイントを作り,
formData
を受け取る処理してくれる。- 必要に応じて actionの中でデータ再検証(revalidate)ができる。
- 利用例: 新データ作成後に、データ一覧の更新を反映する
- 必要に応じて actionの中でデータ再検証(revalidate)ができる。
-
Experimental
ではあるが、remix でも同じような仕組みを採用していたので、標準になるはず。
Supabase
ログイン
supabasesignInWith
をクライアントで認証, callbackでcookieでsession保存。
ログイン判定, 認可には, サーバー側でセッションを取得, 全てライブラリに任せられる。
このページをよく読む。
Supabase ライブラリの注意点
Next.js で supabase ライブラリを使う場合, 以下の2つインストールすることになるが,
npm install @supabase/auth-helpers-nextjs @supabase/supabase-js
supabase-js
は直接importして使わないこと。認証情報を引き継げず、RLS Policyを適切に設定したのにデータが見れなくて困った。以下の方法で読み込んではいけない。
// auth-helpers-nextjsがある場合このコードはダメ
import { createClient } from '@supabase/supabase-js'
const supabase = createClient('https://my-custom-domain.com', 'public-anon-key')
その代わりにauth-helpers-nextjs
から Supabase Clientを作成する。以下のenvを宣言しておけば、勝手にenv読み込んでくれる。
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key
Supabase clientを作るには、5種類の方法があるので、それぞれ読み込むモジュールの中で最適なものを選ぶ。
Client Components —
createClientComponentClient
in Client Components
Server Components —createServerComponentClient
in Server Components
Server Actions —createServerActionClient
in Server Actions
Route Handlers —createRouteHandlerClient
in Route Handlers
Middleware —createMiddlewareClient
in Middleware
DB
Supabase管理画面内でポチポチ設定できる。認証設定も同様。ローカル環境も作れる。初期は全て管理画面でテーブルを作り、リリース後は、MigrationでDBのスキーマ管理をしていくのが良い。Postgresなので、アプリが大きくなったらGCP,AWSマネージドSQLなどに移行、という戦略も取れる。
RLS
Row Level Security (RLS)Policyを設定すれば、Supabase DB側で認可を管理できる。ユーザーが、本人のデータのみを閲覧、編集可能にできる。アプリケーションコードで制御する必要がない。
こちらも管理画面ポチポチで設定できる。
useSWR 無限スクロール
無限スクロールを実装するには、動的にデータを取得する必要があった。Client Component でのデータフェッチにはuseSWRを使った。useSWRInfinite
で簡単にデータ管理とページネーションが実現できる。
vercel supabase 連携
vercel から supabase を連携することで、supabaseの環境変数を取ってきてくれる。Vercel画面内で環境変数を設定する必要がない。
真にgithubのrepositoryを選ぶだけで、デプロイできるようになった!
その他 問題解決したこと
- supabase 本番とローカルで, google ログインした時の redirect 先 が一緒になってしまう問題
- https://github.com/supabase/supabase/issues/1895#issuecomment-864503163
- siteUrl をvercel, local に redirectToと同じURLを入れて完了。
-
*/page.ts
でcookies
を読み込もうとすると, 本番サーバーbuild時にエラーが。- https://github.com/vercel/next.js/issues/49373
-
export const dynamic = 'force-dynamic'
を設定する必要がある。
Next.jsは次のRailsになるのか
少し昔は Rails のerb と少しのajaxで画面作成は完結していた。Webアプリがリッチ化していくなかで、サーバーがAPI化, フロントがSPA と分離された。フロントでの状態管理やjwt認証などやることが増えた。SSRやMPAへのゆり戻しに。
今の JS Fullstack FW like Next.js, remix, は リッチなUI表現、UIの書き心地はそのままに、エンジニアが考えることを少なくする。(reinvented php とも言われている。)
デプロイもボタン一発でできるPaaSがある。インフラはプロに任せられる。すると、よりビジネスロジック, UIUXに集中できる。
RailsチュートリアルをやればWebアプリを作れた時代に戻れるのかもしれない。
関連記事
おわり
業務委託でのお仕事募集中です!フロント, バックエンド, GCPできます。