# Next.js から HonoX へ。Worker を軽量化するための技術選定

- 公開日: 2026-07-02
- 更新日: 2026-07-24
- URL: https://systemdesignworks.co.jp/news/nextjs-to-honox-cloudflare-workers
- 発行: 株式会社システムデザインワークス

> 小規模な業務アプリに Next.js はやや過剰では——という仮説を確かめるべく、社内の顧客管理アプリを Next.js + Prisma から HonoX + Drizzle + Cloudflare D1 へ移行しました。Worker バンドルは 4.98MB から約 300KB へ。移行の判断軸と、hono/jsx・D1 まわりで得た知見を共有します。

こんにちは！システムデザインワークスの山岸です。

先日公開した [自社サイトを Vercel から Cloudflare Workers へフル移行した記録](./vercel-to-cloudflare-workers-migration) の「業務アプリ版」です。ある住宅会社様向けに社内開発している顧客管理アプリを題材に、**「小規模な業務アプリに Next.js はやや過剰なのではないか」** という仮説を、実際に移行して確かめました。

結論から言うと、Next.js + Prisma で組んでいたアプリを **HonoX + Drizzle + Cloudflare D1** へ移行したところ、Cloudflare Workers にデプロイされるコード（バンドル）が **4.98MB から約 300KB**、およそ 16 分の 1 になりました。本記事では、その判断軸と移行を通じて得た知見を共有します。

## 背景・課題：Worker では「フレームワークの重さ」がそのまま効く

題材は、顧客台帳と定期点検スケジュール（お引渡しから 1 か月〜10 年の 7 段階）を管理する社内向けアプリです。一覧・検索・詳細・CSV 入出力が中心で、機能はさほど複雑ではありません。当初は自社サイトと同じく **Next.js + Prisma**（Prisma はデータベース操作ライブラリ）で構築し、**OpenNext**（Next.js を Workers 向けに変換するアダプタ）経由で Cloudflare Workers 上に載せていました。

ここで引っかかりがありました。Workers はリクエストごとにコードを起動するエッジ（世界中に分散したサーバー網）の実行環境のため、**デプロイするコードが大きいほど起動が重くなり、コールドスタート（間隔が空いた後の初回起動）の体感に響きます**。コンテンツ表示や画像最適化など Next.js の機能を活かす自社サイトなら見合いますが、今回のアプリは突き詰めれば「DB を読み書きして HTML を返す」だけ。多機能さは明らかにオーバースペックでした。そこで弊社のスタイル——**まず自分たちで試してから提案する**——に沿い、軽いスタックへ寄せれば Worker の性能を引き出せるかを検証することにしました。

## 取り組みの概要：Workers のために設計された道具に揃える

ゴールは「Worker 上で動くコードを可能な限り小さくする」こと。フレームワーク・ORM・データベースをまとめて見直しました。

- **フレームワーク**: Next.js → **HonoX**。Hono（エッジ環境向けの軽量 Web フレームワーク）に、Vite やファイルベースのルーティング、操作が必要な部品だけをブラウザで動かす仕組み（後述）を備えたもの
- **UI**: React → **hono/jsx**。書き味は React に近く、ランタイムははるかに軽量。ページの大半はサーバーで HTML を生成し JavaScript をほぼ送りません
- **ORM**: Prisma → **Drizzle ORM**。SQL に近い薄い記述で、バンドルが劇的に軽くなります
- **DB**: **Cloudflare D1**（SQLite ベースのマネージド DB）を継続利用

方針は「無理に動かす」のではなく「最初から Workers 向けの道具に揃える」こと。自社サイト移行で得た学びの延長線上にある判断です。

```mermaid
flowchart LR
  subgraph Before["移行前（Next.js）"]
    A1[Next.js + React] --> A2[OpenNext 変換]
    A2 --> A3[Prisma + WASM エンジン]
    A3 --> A4[(Cloudflare D1)]
  end
  subgraph After["移行後（HonoX）"]
    B1[HonoX + hono/jsx] --> B2[Drizzle ORM]
    B2 --> B3[(Cloudflare D1)]
  end
```

## 実装・検証の要点：移行で得た 3 つの知見

「軽くする」という目的のもと、各レイヤーで Workers 流の作法に合わせていきました。その過程で得た、特に再現性の高い 3 つの知見を紹介します。

**1. Prisma → Drizzle でバンドルが 4.98MB → 約 300KB に。** Prisma は便利な反面、Workers ではクエリエンジンを **WASM**（Workers でも動くバイナリ形式）として同梱する必要があり、これがバンドルを押し上げていました。Drizzle は重いエンジンを持たない薄いライブラリで、移行後は約 300KB まで縮小。スキーマ定義を 1 ファイルに集約し、そこからマイグレーション（DB の変更手順）を生成する運用にしています。

```typescript
// app/db/schema.ts（抜粋）：スキーマを唯一の正本にする
export const customers = sqliteTable("customers", {
  id: integer("id").primaryKey({ autoIncrement: true }),
  customerId: text("customerId").notNull().unique(),
  name: text("name").notNull().default(""),
  assigneeId: integer("assigneeId").references(() => users.id, {
    onDelete: "set null",
  }),
  // ...
});
```

**2. React をやめ、操作が必要な部品だけをブラウザで動かす。** このアプリで操作（クリックでの切り替えなど）が要るのは、点検チェックリストの編集くらいです。HonoX には **islands（アイランド）** という仕組みがあり、ページ全体は静的な HTML として配信しつつ、その中の「操作が必要な部品」だけを海に浮かぶ島のように切り出してブラウザ側で動かせます。一覧や詳細ページは HTML を返すだけにし、チェックリストだけをこの方式にして「楽観的更新」（操作を即座に画面へ反映し、保存は裏で行う）も React なしで実装しました。ページの大半に JavaScript を送らずに済むため、**操作が要る最小限だけを動的にする**——これが軽さと使い勝手を両立させる鍵でした。

**3. D1（SQLite）の「型の現実」に合わせる。** D1 の実体は SQLite で、**日時は文字列、真偽値は 0 と 1 の数値**で保存されます。Postgres の感覚で書くと日付の比較や表示で詰まるため、DB には ISO 形式の文字列で保存し、**アプリの境界で **`Date`** 型と相互変換する**方針に統一しました。

なお「Next.js のまま OpenNext で最適化を頑張る」道も比較しましたが、小規模な CRUD アプリでは多機能さが余分なコードとして乗り続けます。目的が Worker の軽量化である以上、土台ごと替えるほうが筋が良いと判断し、Next.js / OpenNext は完全に撤去しました。

## 結果：仮説どおり、小規模アプリには軽量スタックが効く

当初の仮説「小規模な業務アプリに Next.js はやや過剰」は、このアプリに関しては正しいと確認できました。

| 比較項目 | 移行前（Next.js + Prisma） | 移行後（HonoX + Drizzle） |
| --- | --- | --- |
| Worker バンドルサイズ | 約 4.98MB | **約 300KB** |
| UI ランタイム | React | hono/jsx（島は最小限） |
| ORM | Prisma（WASM エンジン同梱） | Drizzle（薄い SQL ビルダ） |
| Next.js を動かす変換層 | OpenNext が必要 | 不要（撤去） |
| 起動時の重さ（コールドスタート） | バンドルが大きく不利 | 大幅に軽量化 |

※ 2026 年 6 月時点。社内開発アプリでの弊社の検証結果に基づきます。

バンドルが約 16 分の 1 になり、Worker の起動は明確に軽くなりました。ただしこれは **Next.js を否定する話ではありません**。コンテンツ表示やページ再生成が活きる場面では今も有力な選択肢で、論点はあくまで **「アプリの規模・性質に道具が見合っているか」**。今回の小規模業務アプリには軽量スタックが噛み合った、ということです。

## まとめ：移行検証から得た 3 つの学び

1. **フレームワークは「規模」で選ぶ**: 多機能なフレームワークはその機能を使い切る規模でこそ活きる。小さな業務アプリでは軽量スタックが噛み合うことがある
2. **エッジでは「バンドル予算」が性能に直結する**: デプロイするコードの大きさがそのまま起動の重さになる。ORM やライブラリは「サイズ」の観点でも評価したい
3. **プラットフォームの「型の現実」を最初に決める**: D1（SQLite）は日時や真偽値の扱いが Postgres と異なる。境界での変換ルールを最初に統一しておくと、後続のロジックがきれいに書ける

## ご相談お待ちしております。

「既存の業務システムが重い」「Cloudflare Workers で内製したい」「技術スタックが今の規模に見合っているか見直したい」——こうしたお悩みがありましたら、ぜひ一度ご相談ください。

システムデザインワークスでは、自社での実践・検証に基づき、技術選定からアプリの設計・開発・運用改善まで一貫してサポートしております。栃木県でアプリ開発・システム開発の会社をお探しの方は、お気軽にお問い合わせフォームよりご連絡ください。
