⚡️Blitz.js - React on Rails

2020/09/20に公開

image.png

みなさん、Blitz.js をご存知ですか?

⚡️Blitz.js - Rails にインスパイアされて作られたフルスタック React フレームワーク!

React エンジニアが WEB サイトを構築するまでには、いくつも考えること、導入するツールがあります!
「使いやすい Form ライブラリはどれだ」「ORM はどれだ」「ディレクトリ構成はどれだ」「linter 設定」などを決めなくてはいけません!

やだ大変!🤮

Rails や Laravel のようにパワフルなフレームワークのおかげですぐに本質的な作業に入りたいそこのあなた!

⚡️Blitz.jsをご存知ですか?

https://github.com/blitz-js/blitz

Introduction

なにはともあれ、サイトを立ち上げてみましょう!

blitz CLI を global install します。

$ yarn global add blitz # npm i -g blitz
$ blitz new myAppName

image.png

React Final FormReact Hook Formどちらを使用するか聞かれます。お好きな方をどうぞ。

選ぶとプロジェクトが generate されます。

image.png

generate されると

Your new Blitz app is ready! Next steps:

   1. cd myApp
   2. blitz db migrate (when asked, you can name the migration anything)
   3. blitz start
$ cd myAppName
$ blitz db migrate

blitz db migrateすると、マイグレーションが実行されます。

2020-08-28 00.13.19.gif

次のファイルが生成されます。

image.png

細かい説明は後回しにしますが、ユーザーテーブルの生成を行ってくれます。

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

datasource db {
  provider = ["sqlite", "postgres"]
  url = "***"
}

generator client {
  provider = "prisma-client-js"
}

// --------------------------------------

model User {
  id             Int       @default(autoincrement()) @id
  createdAt      DateTime  @default(now())
  updatedAt      DateTime  @updatedAt
  name           String?
  email          String    @unique
  hashedPassword String?
  role           String    @default("user")
  sessions       Session[]
}

model Session {
  id                 Int       @default(autoincrement()) @id
  createdAt          DateTime  @default(now())
  updatedAt          DateTime  @updatedAt
  expiresAt          DateTime?
  handle             String    @unique
  user               User?     @relation(fields: [userId], references: [id])
  userId             Int?
  hashedSessionToken String?
  antiCSRFToken      String?
  publicData         String?
  privateData        String?
}

初期設定では sqlite に接続されますので、このままアプリケーションだけ起動してもデータが保存されます。

さあ、blitz startしましょう。

$ blitz start

すると http://localhost:3000/ にサイトが展開されます。

image.png

おや、Sign UpボタンとLoginボタンがありますね?
既に会員登録とログイン機能が実装されています。

Sign Up
2020-08-28 00.23.33.gif

Login
2020-08-28 00.24.04.gif

はじめからバリデーションもされてますね。

パワフルな CLI

起動画面に表示されたコマンドを実行してみましょう。

$ blitz generate all project name:string

すると

$ blitz generate all project name:string

You are using alpha software - if you have any problems, please open an issue here:
    https://github.com/blitz-js/blitz/issues/new/choose

✔ Model for 'project' created successfully:

> model Project {
>   id        Int      @default(autoincrement()) @id
>   createdAt DateTime @default(now())
>   updatedAt DateTime @updatedAt
>   name      String
> }

Now run blitz db migrate to add this model to your database

CREATE    app/projects/pages/projects/[projectId]/edit.tsx
CREATE    app/projects/pages/projects/[projectId].tsx
CREATE    app/projects/pages/projects/index.tsx
CREATE    app/projects/pages/projects/new.tsx
CREATE    app/projects/components/ProjectForm.tsx
CREATE    app/projects/queries/getProject.ts
CREATE    app/projects/queries/getProjects.ts
CREATE    app/projects/mutations/createProject.ts
CREATE    app/projects/mutations/deleteProject.ts
CREATE    app/projects/mutations/updateProject.ts

table の生成だけでなく、ページも含めて1機能の CRUD が生成されました。

  • Page(app/project/pages/*)
  • Form(app/project/components/*)
  • Query(app/project/query/*)
  • Mutations(app/project/mutations/*)

忘れずに migrate しましょう

$ blitz db migrate

http://localhost:3000/projectsへ行くとと CRUD が実装されているのがわかります。

2020-08-28 00.37.07.gif

優れた DataBase Viewer

blitz db studioと入力してみてください。

$ blitz db studio

Generating Prisma Client ... done
Studio started at http://localhost:5555

すると http://localhost:5555 に次の画面が立ち上がります。

この快適な画面で、データの閲覧や、作成がサクッとできます!

2020-08-28 00.41.10.gif

ゼロ API

さて、先程生成されたファイルの中身の話です。(getProject.ts)

app/projects/queries/getProject.ts
import { NotFoundError, SessionContext } from "blitz"
import db, { FindOneProjectArgs } from "db"

type GetProjectInput = {
  where: FindOneProjectArgs["where"]
  // Only available if a model relationship exists
  // include?: FindOneProjectArgs['include']
}

export default async function getProject(
  { where /* include */ }: GetProjectInput,
  ctx: { session?: SessionContext } = {}
) {
  ctx.session!.authorize()

  const project = await db.project.findOne({ where })

  if (!project) throw new NotFoundError()

  return project
}

引数でwhereを取るような形になっており、

app/projects/pages/projects/[projectId].tsx
...
import { Head, Link, useRouter, useQuery, useParam, BlitzPage } from "blitz"
import getProject from "app/projects/queries/getProject"
...

export const Project = () => {
  const projectId = useParam("projectId", "number")
  const [project] = useQuery(getProject, { where: { id: projectId } })
...

useQuerygetProjectを呼び出してアクセスします。これだけ!
GraphQL を内部的に使用しているようですが、うまくラップされていて GraphQL のような code 生成をしなくてもデータアクセスができます!

React の実験的な機能を導入

また、React の Concurrent モード(並列モード) が導入されており、SuspenseErrorBoundaryが使えます。(generate されたソースに使用されています)

blitz console

orm の repl です!Blitz.js では mutation も叩けます!

2020-08-28 01.30.40.gif

mutation も叩ける!すごい!
(なのですが、auth 認証が入っているのでgetProjectで叩くにはちょっとキツイかも、、、)

2020-08-28 01.32.16.gif

Blitz.js on Next.js

Blitz.js は Next.js の上に構成されているので、Next でできることは手厚いサポートがされています。

Blitz では Recipe として、blitz install <recipe>できます。

例えば、tailwind の導入は、

$ blitz install tailwind

これで、必要なパッケージのインストールや、設計ファイルの変更をやってくれます。
CLI 上でインタラクティブに確認が入るので、Enter を押していけばどんどんやってくれます!

image.png

終わればあとは tailwind でスタイリングするだけ!

...
    <ul className="bg-blue-500">
...

image.png

https://blitzjs.com/docs/using-recipes

Recipe に対応しているものは、Github を見れば確認できます。

https://github.com/blitz-js/blitz/tree/canary/recipes

image.png

現在は、chakra、emotion、material-ui、render、tailwind に対応しているようですね。


blitzjs、めっちゃパワフルで素敵ですね!

ぜひ触ってみてください!

Reference

正直この Brandon の動画を記事に起こしただけなのですが、これをみるだけで Blitz の生産性を感じられると思います!

Discussion