💲

できるだけ無料で作る個人開発のための技術スタックと注意点

に公開

最近思いつきで身内向けにTwitterクローンを開発していて、そこでの知見をゆるく共有したいと思います。技術選定の段階で以下の記事を参考にさせていただいたのですが、この記事の内容を前提として代替案としてこれもいいんじゃない?という話をしたいと思います。

https://zenn.dev/expkit/articles/9d4e2f192646a8

フロントエンド

元々私は個人的にずっとNuxtを使っていたのですが、やはり現状はNext.js (+ Tailwind CSS)が一番良い気がします。一度勉強してみたら全然アリだな、と思いました。

https://nextjs.org/

バックエンド

こちらもNext.jsでフロントエンドと同時に開発できます。Next.jsのServer Actionsはサーバーコンポーネントとクライアントコンポーネントどちらからでも呼び出すことができ、DBにアクセスしたりといったことができます。

Server Actionsの注意点

便利なServer Actionsですが、セキュリティの観点からいくつか注意しなければならない点があります。既に他の方が色々な指摘をされていて、そちらの記事を確認しておくとよいと思います。

https://zenn.dev/hikarucraft/articles/nextjs-first-guide-to-security

一応簡単に話すと、例えば"use server"ディレクティブがあるファイル内でexportされた関数は全て外部から直接実行されうる、という問題(仕様)があります。

DBへの行の挿入、削除などを伴う関数(限られた権限を持つユーザーしか呼び出せない想定の処理)の場合は関数の先頭で認証のチェックをするなど、直接呼び出されたとしても問題が発生しないように対策しておきましょう。

フォームの値のバリデーションなどもフロントエンド、バックエンド両方でやるべきだと思います。

デプロイ先

Cloudflare Pagesが圧倒的に簡単だと思います。@cloudflare/next-on-pagesでフロントエンドもバックエンドもすぐに公開できます。いい時代です。

ただし、PagesにNext.jsのバックエンドをデプロイする際にはEdge Runtimeを使う設定にする必要があります。これに伴い、Edge RuntimeでサポートされていないNode.js RuntimeのAPIを使う一部のライブラリは使えないという制約を受けます。

https://nextjs.org/docs/14/app/building-your-application/rendering/edge-and-nodejs-runtimes

Edge Runtimeの制約

実際に開発をしていて詰まった点を共有します。

まず自分の作っているサービスではストレージにCloudflare R2を使用しており、R2との通信にはAWS SDK for JavaScriptを使うつもりでした。しかしこのライブラリは内部でnode:streamを使用しているらしく、このモジュールはEdge Runtimeでサポートされていないためこの環境では動きません。

代替案として、aws4fetchというfetchベースの軽量なAWSクライアントがあります。こちらのライブラリであれば、Edge Runtimeでも動作します。

以上のように、場合によってはEdge Runtimeで動く別のライブラリを探さないといけないときがあります。

他の例では、高機能な画像編集機能を提供するsharpもNode.jsの機能に依存しているためEdge Runtime上では動作しません。現状自分は@cf-wasm/photonという別のライブラリを使用して対応しています。(ただwebp出力がlossless webpしか対応してなくて辛い)

追記:
結局Edge Runtime上で重めの計算が走らせるのは不安定っぽかったので、画像の変換部分はLambdaの関数として切り出し、Server Actionsからこれを呼び出すことで運用しています。やはりPillowなど慣れてる環境で画像を加工する方がやりやすいです……

データベース

Cloudflare D1がいいらしいですが、自分はDBへの接続の仕方が分からなかった(え?)ので、NeonというサーバーレスでPostgreSQLを使うことができるDBaaSを利用しています。

https://neon.tech/

無料で10プロジェクトまで作成でき、データは全プロジェクト合計で毎月500MBまで、かつ約190 compute hours/monthの制約があります。この約190時間という制約でも24/7でDBを動作させるのに十分、と公式で言われているので多分個人開発レベルであれば問題になることはないのかな?と思っています。データ転送についても毎月5GBの制約がありますが、小規模のプロジェクトであればまず超えることはないでしょう。

一応注意点として、現在日本の近くで使用可能なリージョンが無く、最も近いものでシンガポール(その次にオレゴン?)になります。

色々こだわりたくなったら大人しくどこかでサーバーを借りてPostgreSQLのコンテナを運用するとかにしたらいいと思います。

追記:もしアップグレードするなら…

一応長期でサービスを運用するとした場合、データベースをどこに引っ越そうかと考えてみました。AWSにRDSというサービスがあり、Lambda使ってるしまとめられたら楽だな、と思って料金を見てみたら月の最小コストが3000円近くになり、ちょっと個人で使うには考えられない選択肢でした。具体的にはPostgreSQL, db.t4g.micro (2 vCPU, メモリ1 GiB), ストレージ15GBで3000円くらいになります。microでこれか……😓

https://instances.vantage.sh/rds/?region=ap-northeast-1&cost_duration=monthly

NeonについてもFreeプランの次はLaunchプラン(月19ドル←⁉️)になってしまい、ストレージのサービスとかと比べるとDBって安く使い始めるみたいな選択肢があまり無いんでしょうか……。本質的にはEC2のインスタンス借りるのとほとんど変わらない行為なのでそうなってしまうのは頭では理解できるものの、ちょっと辛いところがあります。ここらへんの知見募集中です。

さらに追記:
サーバーレスDB調べてたら、Xataってところを知りました。

https://xata.io/

Free tierでもストレージが15GBも使えるらしく、謎が深いのですが新規でサービス作りたい人はこれでいいかもしれません。無料なのに一時停止とかコールドスタート無しのようで、どうなっているんでしょうか?

ORM

Drizzle ORMが丸いと思います。

https://orm.drizzle.team/

ユーザーの認証など

ユーザーの認証のためだけにSupabaseを使うのは微妙なのでは?という気がしたので自分のサービスではAuth.jsというライブラリを使っています。(名前の検索性が低い気がする)
元々next-authという名前だったやつです。

https://authjs.dev/

v4以前はEdge Runtimeでは動作しなかったのですが、v5からEdge Runtimeに対応しました。

ただこの記事で紹介している環境だとNeonのRLSの使い方がよく分からなくて放置しています……誰か教えてほしい。

ストレージ

SNSなどのサービスになるとメディアを保存しておく場所が必要になるかと思いますが、Cloudflare R2がオススメです。
無料で10GBまで使うことができ、ファイルの転送にお金がかかりません!

ストレージの節約のために、ファイルをアップロードする前に画像ならリサイズ、webp形式にして圧縮するなどしておきましょう。動画や他のファイルになるとそういうのはちょっと難しいですが。

サービスの規模が大きくなるようであれば、Cloudflare Imagesで画像を配信するのも考えていいと思います。

Discussion