0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Cloudflare Pagesでアカウントを作ってから5分でReact(Vite)の空のアプリをデプロイするまでにやった事

0
Posted at

初めに

Cloudflare Pagesを使って、React (Vite) のアプリをデプロイするまでの手順を備忘録としてまとめました。
ローカル環境にはDockerを使用し、GitHub経由で自動デプロイする構成です!

Gemini_Generated_Image_jfppfzjfppfzjfpp.png

1. ローカル開発環境の準備(Docker × React × Vite)

my-page-test
├── README.md
├── docker-compose.yml
├── dockerfile
├── index.html
├── node_modules
├── package.json
├── src
│   ├── App.tsx
│   ├── index.css
│   └── main.tsx
└── vite.config.ts

今回は手元の環境を汚さないためにDockerを使います。

dockerfile

FROM node:20-slim

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 5173

CMD ["npm", "run", "dev", "--", "--host"]

doker-compose.yml

version: '3.8'

services:
  web:
    build: .
    ports:
      - "5173:5173"
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development

Dockerfile の罠(exit code: 254)

Alpine Linux(node:20-alpineなど)を使うと、npm install 時に謎の exit code: 254 エラーで落ちることがありました。これは、package.jsonが存在しないと発生する模様。

package.json の準備(Viteのバージョンに注意!)

ReactとViteの環境を作りますが、ここで大きな注意点があります。
Cloudflare Pagesの現在の仕様(2026年時点)では、Viteのバージョンが 6.0.0 以上でないとデプロイ時にエラーで弾かれます!今回は8.0.0にしました!

{
  "name": "my-cloudflare-react-app",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  },
  "devDependencies": {
    "@types/react": "^18.3.3",
    "@types/react-dom": "^18.3.5",
    "@vitejs/plugin-react": "^4.3.1",
    "typescript": "^5.6.2",
    "vite": "^8.0.0"
  }
}

vite.config.ts

Dockerコンテナ内からホスト側(手元のブラウザ)へ画面を表示し、ホットリロードを効かせるための設定を追加します。

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    host: true,         // コンテナ外からのアクセスを許可
    port: 5173,         // ポートを5173に固定
    watch: {
      usePolling: true  // Docker環境でも確実にファイル変更を検知させる
    }
  }
})

そのほか

画面を表示するための最低限のコード(index.html, src/main.tsx, src/App.tsx)を用意します。

ローカルのコンテナで実行してみる

$ docker-compose up 

http://localhost:5173/ 等でアクセスできることを確認。

2. GitHubへプッシュ

GitHubのリポジトリにプッシュします。ブランチはmainで構わないです。

3. アカウント作成と「サブドメイン」の変更(超重要!)

Cloudflareのアカウントを作成してPagesを始めると、デフォルトで https://[プロジェクト名].[アカウントのサブドメイン].pages.dev というURLが割り当てられます。

実はこの [アカウントのサブドメイン] 部分に、登録したメールアドレスの@より前の部分などが自動で設定されてしまうことがあります。そのまま公開するとアドレスがバレてしまうので、最初に必ず変更しておきましょう。

  • 手順:
    1. Cloudflareダッシュボードの左メニュー「Workers and Pages」を開く。
    2. 画面右側(または下部)にある「Account Details」の「subdomain」を探す。
    3. 「変更」ボタンを押し、メールアドレスとは関係のない好きな文字列(例: my-sandbox-xyz など)に変更する。

これだけで、安全なURLで公開できるようになります。

4. Cloudflare Pages へのデプロイ

いよいよCloudflare側でGitHubと連携させます。

ダッシュボードから「Workers と Pages」→「作成」→「Pages」タブを選択。

「Gitプロバイダーに接続」をクリックし、先ほどプッシュしたリポジトリとブランチ(my-page-test)を選択します。

image.png

ビルドコマンドは下記
image.png

npm error Missing script: "build"が出る場合:

以下のようなメッセージが出ていないか確かめる。

Detected the following tools from environment: bun@1.2.15, nodejs@22.16.0

Cloudflare Pagesのビルド環境には最新の Bun が最初から入っているようです。そのため、package-lock.json がリポジトリに存在しないと、Cloudflareが気を利かせて勝手に bun install を実行してしまいます。

その結果、ビルドコマンドが npm run build のままだと「スクリプトが見つからない(Missing script: "build")」とエラーになります。

解決策は以下のどちらかです:

  • Bunに任せる: 郷に入っては郷に従えで、Cloudflare側のビルドコマンドを bun run build に書き換える。(※今回はこちらで対応しました!)

  • npmを強制する: ローカルで npm install を実行して package-lock.json を生成し、Gitに一緒にプッシュする(これでCloudflareも npm モードになります)。

おわりに

ドメイン周りの仕様や、自動検知によるビルドエラーで少し遠回りしましたが、無事に爆速デプロイ環境を作ることができました!
これからCloudflare Pages + Dockerで環境構築する方の参考になれば幸いです。

おまけ

  • index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My Vite React App</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>
  • main.ts
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
)

  • app.tsx
import { useState } from 'react'

function App() {
  const [count, setCount] = useState(0)

  return (
    <div className="app">
      <h1>Welcome to Vite + React</h1>
      <p>Edit <code>src/App.tsx</code> and save to test HMR.</p>
      <button onClick={() => setCount((count) => count + 1)}>
        count is {count}
      </button>
    </div>
  )
}

export default App
  • index.css
body {
  margin: 0;
  font-family: system-ui, sans-serif;
  background: #f5f5f5;
  color: #111827;
}

.app {
  max-width: 720px;
  margin: 4rem auto;
  padding: 2rem;
  background: white;
  border-radius: 16px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
  text-align: center;
}

button {
  border: none;
  padding: 0.9rem 1.5rem;
  border-radius: 999px;
  background: #4f46e5;
  color: white;
  cursor: pointer;
  transition: background 0.2s ease;
}

button:hover {
  background: #4338ca;
}

code {
  background: rgba(15, 23, 42, 0.08);
  padding: 0.15rem 0.4rem;
  border-radius: 6px;
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?