Honox + Prisma + Cloudflare で最速最小のWEBアプリケーションを作成する

こんにちは、[@kimi_koma1111](https://x.com/kimi_koma1111) です。最近職場でHonoxを導入し開発をしているので、個人的にも触ってみようと思い最速最小でWEBアプリケーションをデプロイできたので皆様にもその感動を伝えたく記事にしました！
自分のようにとにかく早く・費用をかけずにアプリケーションを公開したい方は必見？になっていると思います！

# Honoxとは
これについては以下の記事で作者が詳しく解説しているのでここでは言及しません。
https://zenn.dev/yusukebe/articles/724940fa3f2450

> HonoXとは一言で言うと「HonoとViteを組み合わせたメタフレームワーク」です。

ということです！


# Honoxでプロジェクト作成
まずはHonoxのプロジェクトを作成しましょう！

プロジェクトを作成するためのディレクトリを作成します。
```
$ mkdir your-app-name
```
作成したディレクトリに移動し必要なパッケージをインストール
今回は`npm`で進めます。
```
$ npm install hono honox
```
次にhonoxのテンプレートを作成します。
```
$ npm create hono@latest
```
ここで
```
? Target directory (my-app)
```
と聞かれるので`.`を入力してください。
今いるディレクトリにテンプレートを作成してくれます。
次にどのテンプレートを利用するかを聞かれるので今回は`x-basic`を選択してください
```
? Which template do you want to use?
  nextjs
  nodejs
  vercel
❯ x-basic
```
その後色々聞かれる質問に答えていき最終的にテンプレートが作成されると以下のような構成になっていると思います。

```
.
├── app
│   ├── global.d.ts // global type definitions
│   ├── routes
│   │   ├── _404.tsx // not found page
│   │   ├── _error.tsx // error page
│   │   ├── _renderer.tsx // renderer definition
│   │   ├── about
│   │   │   └── [name].tsx // matches `/about/:name`
│   │   └── index.tsx // matches `/`
│   └── server.ts // server entry file
├── package.json
├── tsconfig.json
└── vite.config.ts
```
ここまできたらテンプレートの作成は完了です。

# Cloudflareへのデプロイ
デプロイする前に一旦作成されたプロジェクトを起動してみましょう！
```
$ npm run dev
```
このような画面が表示されていると思います。
![](https://storage.googleapis.com/zenn-user-upload/ab7bea60e3c0-20240615.png)

一旦この画面をそのまま公開してみましょう！
デプロイを実行する前にCloudflareのアカウントを持っていない方は作成しましょう！
https://www.cloudflare.com/ja-jp/

作成後に以下のコマンドを実行してください！
```
$ npm run deploy
The project you specified does not exist: "your-app-name". Would you like to create it?"
❯ Create a new project
? Enter the production branch name: › production
✨ Successfully created the 'your-app-name' project.
🌏  Uploading... (5/5)

✨ Success! Uploaded 5 files (1.84 sec)

✨ Compiled Worker successfully
✨ Uploading Worker bundle
✨ Uploading _routes.json
🌎 Deploying...
✨ Deployment complete! Take a peek over at {your-project-url}
```

これでCloudflareへのデプロイが完了しました！
反映されるまで多少時間（5〜10分くらい）はかかりますが、表示されたURLにアクセスすると先程の画面が表示されるはずです。
この時に`Enter the production branch name:`と聞かれます。
これはプロダクションブランチの名前を聞かれています。
今後このブランチ以外からデプロイコマンドを実行してもプレビュー環境として扱われることになります。
特定のブランチ名を指定したい場合は、この質問に対して任意のブランチ名を入力するようにしてください。
今回は特にこだわりがなかったので`production`のまま実行しています。

# Prismaの導入
次にPrismaを導入していきます。まずはパッケージのインストールから
```
$ npm install -D prisma
$ npm install @prisma/client @prisma/adapter-d1
```

インストールが終了したらPrismaを初期化します！
```
$ npx prisma init --datasource-provider sqlite  
```

`prisma/schema.prisma`が作成されるので、そのファイルを修正します。

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

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["driverAdapters"] <= これを追加
}

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}
```
一旦これでPrismaのセットアップは完了です！

# Cloudflare D1でDB構築
以下のコマンドを実行してDBを作成します。
DBの名前は任意でつけてください！
```
$ npx wrangler d1 create your-db-name
```

実行すると以下のような結果が得られます。
```
⛅️ wrangler 3.49.0
-------------------
✅ Successfully created DB 'your-db-name' in region APAC
Created your new D1 database.

[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "your-db-name"
database_id = "xxxx-xxxx-xxxx"
```
この出力された内容を`wrangler.toml`に追加します！
そのままコピーして貼り付ければOKです。

これでDBの作成は完了です。
次にテーブルを作成します。今回はUserテーブルを作成します。
内容はすごく簡素化しています。
まずは以下のコマンドでマイグレーションファイルを作成します。
```
$ npx wrangler d1 migrations create your-db-name create_user_table
```
`your-db-name`の部分は先程作成したDBの名前、`create_user_table`はマイグレーションファイルの名前になります。

コマンド実行後に以下のディレクトリとファイルが作成されます。
```
migrations/
	└── 0001_create_user_table.sql
```
この状態ではまだ中身は空です。
prisma.schemaファイルを編集しUserテーブルを定義しましょう！
```
model User {
  id   Int    @id @default(autoincrement())
  name String
}
```

かなり簡素な作りですが、一旦はこれで。
編集が完了したらPrismaのマイグレーションコマンドを実行します。
Prismaを使用してデータベーススキーマの差分を計算し、その差分をマイグレーションスクリプトとして先程作成されたsqlファイルに出力します。
```
npx prisma migrate diff --from-empty --to-schema-datamodel ./prisma/schema.prisma --script --output migrations/0001_create_user_table.sql
```

ここまできたら実際のDBをマイグレーションします。

```
// ローカルのDBへ反映
npx wrangler d1 migrations apply your-db-name --local
```
```
// リモートのDB（実際に本番で利用するDB）へ反映
npx wrangler d1 migrations apply your-db-name --remote
```

実行後にCloudflareのダッシュボードからD1を見てみると先程の内容が反映されていることが確認できます。

# コード実装
実際に作成したUserテーブルへデータを登録する実装をします。
ここではHonoxに関する詳しい解説はまるッと飛ばします！
とりあえず「このコードをコピーしていけば動くよ」ということで（笑）

まずは準備段階として`vite.config.ts`を以下のように編集します。

```ts
import pages from "@hono/vite-cloudflare-pages";
import adapter from "@hono/vite-dev-server/cloudflare";
import honox from "honox/vite";
import client from "honox/vite/client";
import { defineConfig } from "vite";

const baseConfig = {
  ssr: {
    external: ["@prisma/client", "@prisma/adapter-d1"],
  },
};

export default defineConfig(({ mode }) => {
  if (mode === "client") {
    return {
      ...baseConfig,
      plugins: [client()],
    };
  } else {
    return {
      ...baseConfig,
      plugins: [
        honox({
          devServer: { adapter },
        }),
        pages(),
      ],
    };
  }
});
```

今回はUserデータを作成するので`app/routes/user/create.tsx`という構造でファイルを作成します。
作成後、以下のコードを記載します。
```tsx
import { createRoute } from "honox/factory";
import { PrismaD1 } from '@prisma/adapter-d1';
import { PrismaClient } from '@prisma/client';

export default createRoute((c) => {
  return c.render(
    <div>
      <form method="POST">
        <input type='text' name='name' placeholder='name' />
        <input type='submit' />
      </form>
    </div>
  )
})


export const POST = createRoute(async (c) => {
  const { name } = await c.req.parseBody<{ name: string }>()
  const adapter = new PrismaD1(c.env.DB);
  const prisma = new PrismaClient({ adapter });
  await prisma.user.create({
    data: {
      name
    }
  })

  return c.redirect("/user/create");
})
```

# いざデプロイ
先程のコードが準備できたら再度デプロイします！
冒頭でも行ったデプロイコマンドを再度実行し、表示されたURLにアクセスしてください！
表示されたURLの後ろに`/user/create`をつけたものを直接アドレスバーに打ち込んでください。
そうすると以下のような表示になっているはずです。
![](https://storage.googleapis.com/zenn-user-upload/c131fbc75eb7-20240615.png)

ここに何かしらの文字列を入力し、送信ボタンをクリックすると同じ画面にリダイレクトされます。
そうしたらCloudflareのダッシュボードからD1を見てみてください！
先程入力したデータが登録されていることがわかります！

# 終わりに
今回Honoxに関しては詳しいことは触れませんでしたが、最速でWebアプリケーションを構築し、デプロイ、DBの作成までを紹介しました。
ややこしいセットアップがほとんどなく、「動いた！」という感動を最速で感じることができる構成だと思います！
ちなみにこの構成であれば費用はかかりません。（もちろん制限はありますが）
自分もこの構成で何かしらのWEBアプリケーションを作成しようと思っています。
皆様に触っていただけるようになったらまた記事を書きたいと思います。
ぜひ、試してみて「動いた！」という感動を体感して欲しいです！

### 参考情報
https://zenn.dev/yusukebe/articles/724940fa3f2450
https://github.com/honojs/honox
https://www.cloudflare.com/ja-jp/developer-platform/d1/
https://www.prisma.io/