はじめに
最近少しBlitz.jsを触ってみたので備忘録的に書いてみます。
執筆時点では v0.24.3
/ 0.25.0-canary.2
です。
ドキュメントからの部分抜粋みたいになってしまったので、これからBlitz触ってみようかな、という人向けの記事です。
Blitz.jsのはじまり
https://blitzjs.com/docs/community-history
ざっくりとはBlitz.jsは作者BrandonBayer氏がReactによるRuby on Railsが欲しいなとつぶやいていたものの誰も全然やってくれないからもう自分でやろう、みたいな形でスタートしています。この背景からBlitz.jsはReactを用いたNode.js向けのRuby on Railsのようなフルスタックアプリケーションを作れるフレームワークを目指すという思想で始まっています。
プロジェクトの指針は ここ で説明されています。見出しのみ抜粋。
Fullstack & Monolithic
API Not Required
Convention over Configuration
Loose Opinions
Easy to Start, Easy to Scale
Stability
Community over Code
主要なパッケージと依存
Blitz.jsには下記の主要なパッケージがあります。それぞれを知っていると捗ります(ものによってはそこまで知らなかったのでつらかったです)
Next.js
Blitz.jsは基本的にNext.jsの上に作られています。
React(Concurrent Mode)
https://reactjs.org/docs/concurrent-mode-intro.html
Reactはexperimental-xxx系のパッケージが使用し、Concurrent Modeを有効にしています。これは抜けるかもしれませんが、大変そうだったので頑張っては試していません。
この影響でデフォルトではConcurrent Modeに対応していないUIフレームワーク等は動きません。
例としてAnt Design/antdは動くコンポーネントと動かないコンポーネントがあります。Material-UIは未検証です。
Prisma (2.0)
Prismaは必須ではないようですが、デフォルトでは型付けされたクライアントを生成するためにPrismaが設定されており、blitz db
系のコマンドもほとんどがPrismaのCLIのプロキシです。
Knex.jsを使用するサンプルはこちらにありますが、内容・手順等は未確認です。(起動はできました)
react-query
https://react-query.tanstack.com/
Blitz.jsではreact-queryをラップして作られた関数群(useQueryなど)が提供されており、Blitz.js内で定義されたquery/mutationを使う場合はBlitzのもの、外部APIなどを使う場合はreact-queryのものを使う形になります。
ここの依存度が厳密に必須なのかはわかりませんが、バックエンド・フロントエンドを一本化するためにフロントエンドではquery/mutationがRPC Clientを通してサーバーサイド実装からAPIリクエストに変換されるようですが、この辺りが変換されているかという検証やこの情報を元にしてreact-queryの設定値をよしなにしてくれているので、大人しくreact-queryに乗っかったほうが良さそうです。
この辺りの実装の影響から外部APIにはBlitz.jsのuseQueryではなく、react-queryの素のものを使う、という形になっています。
Blitz.jsの標準機能
https://blitzjs.com/docs/why-blitz
Next.jsに対して大きく下記のような標準機能の追加があります。
Data Layer
https://blitzjs.com/docs/query-usage
You may be wondering how that can work since it's importing server code into your component: At build time, the direct function import is swapped out with a network call. So the query function code is never included in your client code.
https://blitzjs.com/docs/rpc-specification
File: app/products/queries/getProduct.ts
URL: /api/products/queries/getProduct
Blitz.jsではquery/mutationの1定義で、バックエンド/フロントエンドにインポートしてそのまま使用できます。
また、そのコードは上述の通りビルド時にAPIルートとクライアントではAPIリクエストに置き換わり関数のコード隠蔽されます。これが割とBlitzの大きな機能で魔法な所です。
ここはmizchiさんがこの部分の仕組みをコードベースしっかりと追ってる記事を書いているのでこちらがおすすめです。
pagesの分離
https://blitzjs.com/docs/pages
Next.jsでは単一の pages/
フォルダをルーティングとして変換しますが、Blitz.jsでは ルートのapp/
配下にあるpages/
ディレクトリ全てをマージしてルーティングに変換されます。
app/pages/about.tsx
app/projects/pages/projects/index.tsx
app/tasks/pages/projects/[projectId]/tasks/[taskId].tsx
この構成では下記のルートが生成されます。
/pages/about
/pages/projects
/pages/projects/[projectId]/tasks/[taskId]
組み込みの認証とセッション管理
Blitz.jsは標準で認証(Email/Password)とセッション管理の仕組み備えています。
また、この組み込み認証は Passport.jsのadapterを備えており、Passport.jsのStrategyを追加することにより、SNS認証等を簡単に追加できます。サンプルはこちら。
セッション管理はSuperTokensを参考に実装されており、実際にSperTokensのCTOであるRishabh Poddar氏が実装等を監督しているようです。
Code Scaffolding
https://blitzjs.com/docs/cli-generate
Ruby on Rails の rails generate scaffold
と同じようなCLIが提供されており、blitz generate all project name:string
で Model定義、Queryの生成、Mutationの生成、Pageの生成が行われます。
ただ現時点では Model の name
にしか対応してなさそうなコードが生成されます。どうやって作っていくべきか、という雛形としては便利ですが、コマンド一発終了という所まではいけていなさそうです。
Recipeのインストール
https://blitzjs.com/docs/using-recipes
blitz install tailwind
というようなコマンドを打つだけで各種設定が自動的にインストールされます。
現状の公式recipeはこちら
初期設定ファイル群
大体プロジェクトを始める時に最近では eslint / prettier / husky / git hooksなどを設定すると思いますが、それが標準で設定済みです。設定変更が必要であればそれを適用する、という程度で開発をスタートできます。(このセットで足りれば)
その他色々
- デフォルトではデータベースとしてsqliteが入っているのでお試しはそのまま起動すれば動く
- 型指定してquery parameterを取得できる
- https://blitzjs.com/docs/route-params-query
const param = useParam("id", "number")
ただ今は対象がundefinedの時に(12/7)修正されていますNaN
が返ってきたりする
- apiは基本的に
pages/api
ではなく/app/api/
配下を推奨- pages配下もNext.jsとの互換性のために使えはする
- https://blitzjs.com/docs/api-routes
- (api周りでは
/api
配下でなくともqueries
mutations
も予約ディレクトリ名のような形でAPIルートとして変換される)
- react-query関連はラップされている影響で本家とはインターフェースが異なる
blitz c
という rails consoleのようなものが実装されている
ハマりどころ/難しい所
ここ最近のバージョン依存の内容も含みます。
seedが動かない
v0.24.3が現行ですが、他ファイルのimportをしているか、かどうか条件は忘れましたがseedが動かないことがあります。これは0.25.0-canary.0
で修正されていますので blitz@canary
でcanaryのバージョンを使うと動きます。
(12/7) canaryでなくても動くように修正済です。
generator
blitz generate
で生成されるコードの型というか実装コードが型と一致していないため、自分で定義するモデル生成に使用すると型エラーが大量に発生します。このタイミングでコミットしようとするとpre-commit hook
にtsc
が含まれているのでコミットできなくなります。generateの後にコミットしたい方はpre-commit
からpre-push
に移しておいても良い気がします。
また、このgenerator周りでの好みかもしれませんが、
- Model定義を
schema.prisma
で行い、blitz db migrate
- その後
blitz generate crud ModelName
(queries/mutationが生成される)blitz generage pages ModelName
(crudに対するpageが生成される)でひな形を作成して編集
が、良いのかなと思いました。
blitz generate xxxx
で可能なオペレーションはこちらに記載されています。
Prisma Migrate
https://www.prisma.io/docs/concepts/components/prisma-migrate#supported-operations
この機能まだExperimentalなため、一部のオペレーションに対応していないので注意が必要です。
それなりにバグを踏む
まだαであり、コマンドを実行すると
You are using alpha software - if you have any problems, please open an issue here:
https://github.com/blitz-js/blitz/issues/new/choose
と表示されるのですが、そのとおりにちょいちょバグを踏みます。見つけた場合はどんどんissue/PRあげると良さそうです。
作者がフルタイムで参加していることもあり、issue/PRに対するレスポンスはかなり良いです。slackも割とアクティブな気がするので動きを知りたい人は入っておくと良いかもしれません。
PRなど、コード面で参加する場合、コードベースは初期に参加者向けにビデオ会議で説明している動画があるので今は変わっているとこもありますが、大枠は一緒そうなのでこれを見るのも面白いと思います。
Next.js/Prisma/react-queryの知識
正直それぞれの単体をそこまで理解せずに触ってみると結構苦しいというか、何がどこのライブラリと紐付いていて、Blitz.jsがどういう変更を入れているかを理解するのに時間がかかります。なので「あー、これはあそこからの機能ね」という感じで分かるくらいで触ると結構楽しいのではと思いました。とはいえいきなり飛び込んで調べながらやってもつらいですが学びは結構ありました。
おわりに
Reactのexperimentalバージョンの依存だったり、Prismaもv2が7月リリース、migrate機能についてはまだExperimentalだったりと先を行く構成なせいか、対応していない操作だったり、対応していない関連ライブラリがありつつ、Blitzもまだαのため、現状では安定してがんがん開発していける、かはちょっと分かりませんが、触ってさくさく作れるのは楽しい所です。また、型付けがしっかりしているので候補出して使い方分かることも多くて楽です。
今回触れていない部分も大量にあるので興味が出てきた場合は是非公式チュートリアルをやってみたり、ドキュメント を読んでみてください!
なんかドキュメントを全体的に抜粋した感じになってしまった…。空き時間にちまちま一週間触ってみた程度ですので間違いや指摘があれば是非ご指摘頂ければ幸いです。