ViteとhonoでCloudflare WorkersでWebページとAPIを作成する

ViteとhonoでCloudflare WorkersでWebページとAPIを作成する

Cloudflare PagesからWorkersへの移行を検討していたので、ViteでReactのWebアプリをCloudflare Workers上で動かすまでの初期セットアップ手順を試してみました。
2026.07.17

こんばんは、情報システム室の夏目です。

個人的にWebアプリを作成する際、Cloudflare Pagesを使っていました。
久しぶりに作成しようとしたところ去年の4月に「新規開発はWorkersから始めるべき」という方針が出されていたことを知りました。

https://blog.cloudflare.com/ja-jp/full-stack-development-on-cloudflare-workers/

今回はCloudflate PagesとFunctionsの代わりにWorkersを使ってViteでReactのWebアプリの初期セットアップをしようと思います。

1. create-viteでプロジェクトの作成

$ npm create vite@latest

> npx
> "create-vite"


  Project name:
  trial-cloudflare-worker

  Select a framework:
  React

  Select a variant:
  TypeScript + React Compiler

  Which linter to use?
  Oxlint

  Install with npm and start now?
  No

  Scaffolding project in /xxxxx/trial-cloudflare-worker...

  Done. Now run:

  cd trial-cloudflare-worker
  npm install
  npm run dev

$ cd trial-cloudflare-worker
$ npm install

ViteでReactのプロジェクトを作成して、依存ライブラリのインストールを行います。

$ eza -T
.
├── index.html
├── package.json
├── public
   ├── favicon.svg
   └── icons.svg
├── README.md
├── src
   ├── App.css
   ├── App.tsx
   ├── assets
   ├── hero.png
   ├── react.svg
   └── vite.svg
   ├── index.css
   └── main.tsx
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts

今のファイル構成はこんな感じです。

2. Cloudflare Workers用の依存関係の追加

$ npm install -D wrangler @cloudflare/vite-plugin

Cloudflare Workers用の依存関係を追加します。
@cloudflare/vite-plugin を使うことでCloudflare Workersに近い環境でローカル実行されるようになったり、Worker用のコードも vite buildでビルドしてくれるようになります。

これにより wrangler deployvite build の出力を認識し、追加のバンドル処理なしでデプロイできるようになります。

3. vite.config.ts にCloudflare pluginを追加

vite.config.ts
import { defineConfig } from 'vite'
import react, { reactCompilerPreset } from '@vitejs/plugin-react'
import babel from '@rolldown/plugin-babel'
import { cloudflare } from '@cloudflare/vite-plugin'

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    react(),
    babel({ presets: [reactCompilerPreset()] }),
    cloudflare(),
  ],
})

pluginsに cloudflare() を追加するだけです。

4. Cloudflare Workersの設定ファイルを作成する

wrangler.jsonc
{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "name": "trial-cloudflare-worker",
  // Set this to today's date
  "compatibility_date": "2026-07-16",
  "assets": {
    "not_found_handling": "single-page-application"
  }
}

"not_found_handling": "single-page-application" を設定することでファイルが見つからないリクエストはすべてindex.htmlにルーティングされるようになります。
@cloudflare/vite-plugin を使用しているとViteのデフォルトの動作の代わりに使用され、ルーティング設定が開発時と本番環境の両方で同じように動作します。

ここまで設定すれば、静的ファイルだけで構成されるSPAならデプロイ可能です。
Githubのリポジトリを繋げたり、wranglerコマンドを使用してデプロイすればSPAとして公開されます。

今回はCloudflare Pages Functions部分もWorkersでやりたいので、Workerの設定を進めていきます。

5. Workerの最小構成を作る

5-1. package.jsonのscriptsに追記

package.json
{
  "scripts": {
    "cf-typegen": "wrangler types",
    "typecheck": "npm run cf-typegen && tsc -b",
    "build": "npm run typecheck && vite build",
    "deploy": "npm run build && wrangler deploy"
  }
}

package.jsonのscriptsに上記の4つを追加します。

  • cf-typegen
    • wrangler.jsoncからCloudflare Workers用の型定義ファイル worker-configuration.d.ts というファイルを生成します
    • @cloudflare/workers-types というnpm packageで代替ができますが、Workerに設定しているバインディング(KVとかR2とか)やVariable, Secretも反映したものを生成してくれます
  • typecheck
    • Worker用の型定義ファイルを生成し、TypeScriptの型チェックを行います
  • build
    • vite buildでフロントエンドとワーカー用のビルドを行います
  • deploy
    • Cloudflare Workersにデプロイします
    • 手動デプロイする場合は使用します

5-2. TypeScriptのビルド設定をする

tsconfig.worker.json
{
  "compilerOptions": {
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.worker.tsbuildinfo",
    "target": "ES2022",
    "lib": ["ES2022"],
    "module": "esnext",
    "moduleResolution": "bundler",
    "types": ["./worker-configuration.d.ts"],
    "noEmit": true,
    "strict": true,
    "skipLibCheck": true,
    "isolatedModules": true,
    "verbatimModuleSyntax": true,
    "moduleDetection": "force"
  },
  "include": ["worker", "worker-configuration.d.ts"]
}

Cloudflare Worker用のtsconfigファイルを作成します。
設定値の大部分をtsconfig.node.jsonに頼って最小限だけ書くこともできるのですが、個人的に意図しない設定が含まれていたので新規に書き下ろしました (AIに全力で頼りましたが)。

tsconfig.json
{
  "files": [],
  "references": [
    { "path": "./tsconfig.app.json" },
    { "path": "./tsconfig.node.json" },
    { "path": "./tsconfig.worker.json" }
  ]
}

tsconfig.jsonを編集して、tsconfig.worker.jsonも読み込むように設定します。

5-3. Worker用のtsファイルを書き、wrangler.jsoncを更新する

$ mkdir worker

Worker用のtsファイルを置くディレクトリを作成します。

worker/index.ts
export default {
  async fetch(request, env, ctx): Promise<Response> {
    const url = new URL(request.url);

    if (url.pathname.startsWith("/api/")) {
      return Response.json({
        ok: true,
        path: url.pathname,
      });
    }

    return new Response(null, { status: 404 });
  },
} satisfies ExportedHandler<Env>;

こちらはドキュメントにあったサンプルを参考に書いたものです。

とりあえず、最小構成のコードとしてはこれでいいでしょう。

wrangler.jsonc
{
  "main": "./worker/index.ts",
  "assets": {
    "not_found_handling": "single-page-application",
    "run_worker_first": [
      "/api/*"
    ]
  }
}

wrangler.jsoncに上記内容を追記します。
Worker用のtsファイルを main で明記します。

run_worker_first を設定することで、明示的にWorkerを動かしたいパスを定義できます。

これでWorkerを動かすこともできるようになりました。
デプロイすればWorkerもデプロイされます。

5. honoでWorkerを書く

今の worker/index.ts を見ると、ルーティングを自分で行う必要があるのがわかります。
さすがにそのままでは面倒です。

なので今回はhonoを使ってルーティングを行います。

$ npm install hono

まずhonoをインストールします。

worker/index.ts
import { Hono } from "hono";

type AppEnv = {
  Bindings: Env
};

const app = new Hono<AppEnv>();

app.get("/api/*", (c) => {
  return c.json({
    ok: true,
    path: new URL(c.req.url).pathname,
  });
});

app.notFound((c) => {
  return c.body(null, 404);
});

export default app;

今のコードをhonoで書き直すとこうなります。
ルーティングをhonoに任せられるので、APIを増やす際にも書きやすくなりました。

まとめ

以上、自分がCloudflare PagesからCloudflare Workersに移行する際に行ったことでした。

何かのお役に立てれば幸いです。

この記事をシェアする

関連記事