⚡️Blitz.js - React on Rails

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/bdc82b0b-a86f-23a7-7d60-21998fcbb407.png)

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

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

やだ大変！🤮

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

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

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


## Introduction

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

`blitz` CLIをglobal installします。

```bash
$ yarn global add blitz # npm i -g blitz
```


```bash
$ blitz new myAppName
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/b9bba01b-c597-c575-0b4b-8ac0b36fd37c.png)


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

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/a009cf23-2550-6787-ea32-c93a4651ad3f.png)

generateされると

```bash
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
```

```bash
$ cd myAppName
$ blitz db migrate
```

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

![2020-08-28 00.13.19.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/c1294e76-6509-0f10-79ee-ab539f59b9e6.gif)

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/89403512-afc9-7332-375f-de8feb8c6810.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`しましょう。

```bash
$ blitz start
```

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/b0e21dd4-d8ea-d695-380b-4480df57c735.png)

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

**Sign Up**
![2020-08-28 00.23.33.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/a200eb56-aaee-a49b-13f7-511e7d7c2eb7.gif)


**Login**
![2020-08-28 00.24.04.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/a2ffc43e-1aa1-d249-c780-35e1ae733d79.gif)

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

## パワフルなCLI

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

```bash
$ blitz generate all project name:string
```

すると

```bash
$ 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の生成だけでなく、ページも含めて１機能のCRUDが生成されました。

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

忘れずにmigrateしましょう

```bash
$ blitz db migrate
```

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

![2020-08-28 00.37.07.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/0fc6ad78-fd18-7ae4-d532-602efa47dfdc.gif)

## 優れた DataBase Viewer

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

```bash
$ blitz db studio

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

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

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

![2020-08-28 00.41.10.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/b4d6d482-0a95-a622-a986-797c0e59f34e.gif)

## ゼロAPI

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

```tsx: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`を取るような形になっており、

```tsx: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 } })
...
```
`useQuery`で`getProject`を呼び出してアクセスします。これだけ！
GraphQLのようなcode生成をしなくてもデータアクセスができます！

## React の実験的な機能を導入

また、Reactの [Concurrentモード（並列モード）](https://ja.reactjs.org/docs/concurrent-mode-intro.html) が導入されており、`Suspense`や`ErrorBoundary`が使えます。（generateされたソースに使用されています）


## blitz console

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

![2020-08-28 01.30.40.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/68fc2102-fab5-d789-d2e3-370912d4dd56.gif)

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

![2020-08-28 01.32.16.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/18cd0fe5-594e-601b-db54-7a99f40a7108.gif)


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

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

例えば、tailwindの導入は、

```bash
$ blitz install tailwind
```

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/a0a1df74-8f18-b5fb-47c6-a480d5b3b10a.png)

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

```tsx
...
    <ul className="bg-blue-500">
...
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/f5f44174-835d-980a-5475-d92faae3cbd4.png)

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

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

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/55df4363-9db9-a636-0f2c-b162b27eb0fb.png)

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


---

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

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


## 参考
- https://www.youtube.com/watch?v=H93WAFrlCkQ