ウェブサイトを公開するまでの全工程

18分で読めます注目

toniolab.comのデプロイ作業を通して、Cloudflare Workers、GitHub Actions、D1データベース、DNS設定、バンドルサイズ制限まで、ウェブサイト公開に必要なインフラ知識を体系的に解説。

English Conversation

Takumi
So I just went through this whole deployment thing for toniolab.com and I feel like I need to write everything down before I forget it all.
1 / 391.0x
1
Takumi
So I just went through this whole deployment thing for toniolab.com and I feel like I need to write everything down before I forget it all.
2
Anya
Oh yeah? How bad was it?
3
Takumi
Two days. Two full days just to get a website live. And the app was already built. This was just the 'put it on the internet' part.
4
Anya
That seems... excessive. Can't you just push to GitHub and it deploys automatically?
5
Takumi
That's Vercel. Vercel is like magic -- push and done. But I'm deployin' to Cloudflare this time, and Cloudflare is a whole different beast.
6
Anya
Why Cloudflare then?
7
Takumi
D1 database. It's this edge database that sits right next to the worker. Both sites share the same database so it made sense.
8
Anya
OK start from the beginning. What even is deploying?
9
Takumi
Right, so when you're coding, everything runs on localhost -- your own machine. Nobody else can see it. Deploying means putting your app on a server somewhere on the internet so anyone with the URL can access it.
10
Anya
You need three things right? The code, a server, and a domain?
11
Takumi
Exactly. And connecting those three is where all the pain happens. Especially on Cloudflare.
12
Anya
What's the difference between Cloudflare Workers and Pages? I keep hearin' both.
13
Takumi
OK so Pages is like a bookshelf. You put static files on it and people grab 'em. Workers is like a kitchen -- it actually runs code and generates responses on the fly.
14
Anya
And you need the kitchen 'cause Next.js does server-side rendering?
15
Takumi
Yep. I tried Pages first, big mistake. Pages loaded fine but all the API routes returned 404. No server-side processing at all. You can't order food from a bookshelf.
16
Anya
Ha. OK so Workers it is. What about the CI/CD stuff?
17
Takumi
GitHub Actions. You make a YAML file that describes what happens when you push. Install Node, build the app, deploy to Cloudflare. GitHub runs it all on Linux servers.
18
Anya
And that matters 'cause your machine is Windows?
19
Takumi
Exactly! The Cloudflare build tools don't even work on Windows. So GitHub Actions solves a platform problem too. I write code on Windows, it builds and deploys on Linux. Super useful.
20
Anya
What about secrets? Like API tokens and stuff?
21
Takumi
Two kinds. GitHub Secrets for the CI/CD pipeline -- they get injected as environment variables during the build. And Worker Secrets for runtime -- available to your code when it's actually handling requests.
22
Anya
And you messed those up?
23
Takumi
Twice. First I forgot to set the Worker secret. Everything deployed fine but the API returned empty data. Then my token had Workers permission but not D1 permission. Got 'account not authorized.' Had to make a whole new token.
24
Anya
You can't just add permissions to an existing token?
25
Takumi
Nope. Gotta make a new one. Learned that the hard way.
26
Anya
What about the size limit thing? That sounded brutal.
27
Takumi
Dude. Free plan is 3 MiB after gzip. My app was 3.4 MiB. Just barely over. 'Cause when Next.js gets bundled for Cloudflare, ALL your pages go into one file.
28
Anya
So you had to start cuttin' stuff?
29
Takumi
Yeah. Deleted 200 files. World maps with huge JSON data, business components, old prototypes. Got it from 3,471 KB down to 2,966 KB. Barely under the limit.
30
Anya
That's tight. What happens if you add more pages later?
31
Takumi
Either delete somethin' else or upgrade to the paid plan. Five bucks a month gets you 10 MiB. Which is honestly pretty reasonable.
32
Anya
And the domain setup?
33
Takumi
That was actually the easiest part. Workers settings, Custom Domains, type in toniolab.com, done. Two clicks. SSL certificate auto-generated. Kinda anticlimactic after everything else.
34
Anya
So the whole flow is: push code, GitHub Actions builds it, deploys to Cloudflare Worker, DNS points the domain to it?
35
Takumi
That's it. And every single one of those steps can break independently. That's why you need to understand all of 'em.
36
Anya
Worth the two days?
37
Takumi
Honestly? Yeah. On Vercel everything's magic. But when somethin' breaks you're helpless. Now I know exactly what happens between git push and a live website. Next time somethin' breaks, I'll know where to look.
38
Anya
Two days to learn it, but only the first time.
39
Takumi
Exactly. Only the first time.

Japanese Conversation

39 lines

toniolab.comのデプロイ作業を全部やったから、忘れる前に書いておきたくて。

そんなに大変だった?

丸2日かかった。アプリはもう出来てたのに。インターネットに出すだけの作業で2日。

それは...かかりすぎじゃない?GitHubにプッシュしたら自動でデプロイされないの?

#インフラ#デプロイ#技術解説Cloudflare WorkersGitHub ActionsD1CI/CDDNSNext.js

はじめに -- この記事の目的

toniolab.comを公開した。
「コードを書いて、ネットで見れるようにする」
たったこれだけのことに丸2日かかった。
なぜか。コードを書くネットで見れるようにする は、全く別のスキルだから。
プログラミングの解説は無限にある。でも「書いたコードをどうやってインターネットに出すのか」を体系的に解説してる記事は意外と少ない。
この記事は、toniolab.comのデプロイ作業を通じて学んだことを、初心者向けに整理したもの。自分のための勉強ノートでもある。

第1章 -- デプロイとは何か

「ローカル」と「本番」

コードを書いているとき、ブラウザで http://localhost:3000 にアクセスして動作確認する。これはローカル環境。自分のPCの中だけで動いている。
この状態では他の誰もアクセスできない。
デプロイとは、このローカルで動いているアプリケーションを、インターネット上のサーバーに配置して、世界中の誰でもアクセスできるようにすること。

デプロイに必要な3つの要素

  1. コード -- 動くアプリケーション(Next.js、React等)
  2. サーバー -- コードを実行する場所(Vercel、Cloudflare、AWS等)
  3. ドメイン -- アクセスするためのURL(toniolab.com等)
この3つを繋ぐ作業がデプロイ。

第2章 -- サーバーの選択肢

Vercel -- 最も簡単

iwasaki-naisou.comはVercelで動いている。
Vercelの特徴:
  • GitHubにプッシュするだけで自動デプロイ
  • Next.jsの開発元なので相性が完璧
  • 設定ほぼゼロ
  • 無料枠が大きい
欠点: Cloudflare D1のようなエッジデータベースとの統合が面倒。

Cloudflare -- 速いが複雑

toniolab.comはCloudflareで動いている。
Cloudflareの特徴:
  • 世界300以上のエッジロケーション
  • D1データベースがネイティブに使える
  • Workerとして動くのでレスポンスが速い
欠点: 設定が多い。Next.jsを動かすのに変換ツールが必要。

重要な違い

Vercelは「そのまま動く」。Cloudflareは「変換して動かす」。
Next.jsはもともとNode.jsサーバーで動くように作られている。Cloudflare Workersは独自のランタイム(V8 isolate)で動く。環境が違う
だから @opennextjs/cloudflare という変換ツールが必要。これがNext.jsのコードをCloudflare Workerで動く形に変換する。

第3章 -- Cloudflare Workers vs Pages

Cloudflareには2つのデプロイ方式がある。初見では違いがわからない。

Pages -- 静的ファイル配信

HTMLやCSS、JavaScriptの静的ファイルを配信する。SPAやSSG(Static Site Generation)向け。
イメージ: ファイルを置く棚。置いたものがそのまま配られる。

Workers -- サーバーサイド実行

コードがリクエストごとに実行される。SSR(Server-Side Rendering)やAPI処理ができる。
イメージ: 注文を受けて料理を作る厨房。リクエストに応じて動的にレスポンスを生成する。

toniolab.comがWorkersを使う理由

Next.jsはSSRが必要。ページの表示時にサーバーでHTMLを組み立てる処理がある。API(/api/user-phrases等)もサーバーで実行される。
Pagesでは静的ファイルしか配信できないので、SSRやAPIが動かない。
最初はPagesでデプロイしようとして失敗した。 ページは表示されたがAPIが404を返した。WorkersにSSRワーカーがいなかったから。

wrangler.toml -- Workers設定ファイル

name = "toniolab" main = ".open-next/worker.js" compatibility_date = "2024-11-27" compatibility_flags = ["nodejs_compat"] [assets] directory = ".open-next/assets" [[d1_databases]] binding = "DB" database_name = "iwasaki-phrases" database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
各行の意味:
  • name: Worker名。Cloudflareダッシュボードに表示される
  • main: 実行されるJavaScriptファイル。opennextjsが生成する
  • compatibility_flags: Node.jsのAPIを使えるようにするフラグ
  • [assets]: 静的ファイル(CSS、画像等)の置き場所
  • [[d1_databases]]: D1データベースの接続設定

第4章 -- CI/CD -- 自動デプロイの仕組み

CI/CDとは

CI = Continuous Integration(継続的インテグレーション) CD = Continuous Deployment(継続的デプロイ)
簡単に言うと: コードをプッシュしたら自動でビルドしてデプロイする仕組み
手動でやるとこうなる:
  1. コードを書く
  2. npm run build でビルド
  3. ビルド結果をサーバーにアップロード
  4. サーバーを再起動
CI/CDがあると:
  1. コードを書く
  2. git push する
  3. 以上。あとは自動。

GitHub Actions

GitHubが提供するCI/CDサービス。リポジトリに .github/workflows/ ディレクトリを作り、YAMLファイルを置くだけで使える。
name: Deploy to Cloudflare on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: npm - run: npm ci - run: npx @opennextjs/cloudflare build - run: npx @opennextjs/cloudflare deploy env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
上から順に読む:
  1. on: push: branches: [main] -- mainブランチにプッシュされたら実行
  2. runs-on: ubuntu-latest -- GitHubのLinuxサーバーで実行
  3. actions/checkout@v4 -- リポジトリのコードをダウンロード
  4. actions/setup-node@v4 -- Node.js 22をインストール
  5. npm ci -- パッケージをインストール
  6. opennextjs/cloudflare build -- Next.jsをCloudflare用にビルド
  7. opennextjs/cloudflare deploy -- Cloudflareにデプロイ
env にある secrets.CLOUDFLARE_API_TOKEN は、GitHub Settingsで設定する秘密の値。コードに直接書くとセキュリティリスクになるため。

なぜWindowsではなくGitHub Actionsか

opennextjs-cloudflareのビルドツールはLinux前提で作られている。Windowsでは動かない。
GitHub Actionsは ubuntu-latest(Linux)で動くので、Windowsの開発マシンからでもLinux上でビルド・デプロイできる。
これがCI/CDの大きなメリットの一つ: 開発環境とデプロイ環境の違いを吸収できる。

第5章 -- D1データベース

D1とは

CloudflareのエッジSQLデータベース。SQLiteベースで、Workerから直接アクセスできる。
普通のWebアプリ: アプリ → インターネット → データベースサーバー CloudflareのD1: アプリ(Worker) → 同じエッジロケーションのD1
データベースが物理的に近い場所にあるのでレスポンスが速い。

アクセス方法: バインディング vs REST API

バインディング(直接接続): WorkerのコードからD1に直接アクセス。最速。ただしWorker内部からしか使えない。
REST API(HTTP経由): どこからでもHTTPリクエストでD1にアクセス。APIトークンが必要。
toniolab.comはREST APIを使っている。理由: 元々Vercel(iwasaki-naisou.com)からもアクセスする設計だったため。

Worker Secrets -- 秘密情報の管理

データベースにアクセスするにはAPIトークンが必要。これをコードに直接書いてはいけない。GitHubに公開されてしまう。
Worker Secret: Workerの環境変数として安全に保存する仕組み。
echo "YOUR_TOKEN" | npx wrangler secret put CLOUDFLARE_API_TOKEN
コード内では process.env.CLOUDFLARE_API_TOKEN で参照する。

APIトークンの権限

Cloudflare APIトークンには細かい権限設定がある。
今回の失敗: 最初に作ったトークンに Workers の権限しかなく、D1 の権限がなかった。
結果: Workerは動くがデータベースにアクセスできない。APIが「account not authorized」エラーを返す。
教訓: トークン作成時に必要な権限を全て付与する。足りない権限は後から追加できない。新しいトークンを作り直す必要がある。

第6章 -- Workerサイズ制限

無料プランの壁: 3 MiB

Cloudflare Workersの無料プランでは、Workerの圧縮後サイズが 3 MiB(約3.07 MB) に制限されている。
有料プラン($5/月)では 10 MiB まで。

なぜサイズが大きくなるのか

Next.jsアプリをWorkerにすると、全ページのSSRコードが1つの handler.mjs ファイルにバンドルされる。
ページが多い = バンドルが大きい = 制限に引っかかる。
最初のデプロイ: gzip 3,471 KiB → 制限超え 不要ファイル削除後: gzip 3,160 KiB → まだ超え さらに削除後: gzip 2,966 KiB → 制限内

何を削ったか

  1. 世界地図ページ6個: 大きなTopoJSONデータ(739KB)を含む
  2. 業務用コンポーネント170個: 請求書、工程表、顧客管理等。英語学習に不要
  3. 未使用データファイル40個: 料理日記、健康ジャーナル等
  4. プロトタイプページ13個: 古いダッシュボード、レビュー機能等
削除の判断基準: ページから import されていないコンポーネント・データは全てバンドルから除外できる。grepで依存関係を確認してから削除する。

重要な教訓

サイズ制限は無料プランの宿命。対策:
  1. 不要なコードを入れない: 使わないページ・コンポーネントは削除
  2. 大きなデータファイルに注意: JSONの地図データ等は特に重い
  3. 有料プランの検討: $5/月で10 MiBまで。3 MiBがきつい場合は現実的
  4. バンドル分析: どのファイルが大きいかを確認してから最適化する

第7章 -- DNS とカスタムドメイン

ドメインとは

toniolab.com はドメイン名。人間が覚えやすいWebサイトの住所。
実際のサーバーはIPアドレス(例: 104.21.23.45)で特定される。ドメイン名をIPアドレスに変換するのが DNS(Domain Name System)。

ドメインの設定手順

  1. ドメイン購入: Cloudflare Registrar等で取得(年$10程度)
  2. DNSレコード設定: ドメインがどのサーバーを指すか設定
  3. Workers側の設定: このドメインのリクエストを受け付けるよう設定
Cloudflareでは、Workers設定画面の「Custom Domains」からドメインを追加する。DNS設定が自動で行われる。

作業の流れ

toniolab.comの場合:
  1. Cloudflare Registrarでドメイン取得済み
  2. Workers設定 → Routes → Custom Domains → toniolab.com を追加
  3. SSL証明書が自動発行
  4. https://toniolab.com でアクセス可能に

第8章 -- トラブルシューティング実録

今回実際に踏んだエラーとその解決策。

エラー1: Pages デプロイで404

症状: ページは表示されるがAPIが404 原因: PagesモードではSSRワーカーがデプロイされない 解決: PagesからWorkersに切り替え

エラー2: GitHub push が拒否される

症状: .github/workflows/ を含むプッシュが rejected 原因: GitHubのPersonal Access Tokenに workflow スコープがない 解決: GitHubの Settings → Developer settings → Personal access tokens で workflow スコープを追加

エラー3: D1が空のデータを返す

症状: APIは200を返すがフレーズ数が0 原因: Worker SecretにCLOUDFLARE_API_TOKENが設定されていない 解決: wrangler secret put で設定

エラー4: D1アクセスが「account not authorized」

症状: APIが認証エラー 原因: APIトークンにD1の権限がない(Workersの権限のみ) 解決: D1 Edit権限付きの新しいトークンを作成

エラー5: Worker サイズ超過

症状: デプロイ時に「exceeded size limit of 3 MiB」 原因: 全ページが1つのバンドルにまとまり、圧縮後3 MiB超え 解決: 不要なページ・コンポーネント・データを削除して2,966 KiBまで圧縮

エラー6: TypeScript型エラーでビルド失敗

症状: declare global の Window 拡張が conflict 原因: 複数ファイルで同じプロパティのoptional修飾子が不一致(YG: vs YG?:解決: next.config.ts に ignoreBuildErrors: true を追加(iwasaki側と同じ設定)

第9章 -- 全体像の整理

デプロイパイプラインの流れ

ローカルでコードを編集
      ↓
git push origin main
      ↓
GitHub Actions が起動(ubuntu-latest)
      ↓
npm ci(パッケージインストール)
      ↓
opennextjs/cloudflare build(Next.js→Worker変換)
      ↓
opennextjs/cloudflare deploy(Cloudflareにアップロード)
      ↓
Worker更新 → toniolab.com に反映

関係する技術の地図

  • Next.js: アプリケーションフレームワーク
  • opennextjs-cloudflare: Next.js→Cloudflare変換ツール
  • Cloudflare Workers: サーバーレス実行環境
  • Cloudflare D1: エッジSQLデータベース
  • GitHub Actions: CI/CDパイプライン
  • GitHub Secrets: 秘密情報の安全な保管
  • Worker Secrets: ランタイムの環境変数
  • DNS: ドメインとサーバーの紐付け
  • wrangler: Cloudflareの管理CLI

覚えておくべき数字

| 項目 | 値 | |------|-----| | Worker無料サイズ上限 | 3 MiB(gzip後) | | Worker有料サイズ上限 | 10 MiB(gzip後) | | Workers有料プラン | $5/月 | | GitHub Actions無料枠 | 2,000分/月 | | D1無料枠 | 5 GB ストレージ | | ビルド時間(目安) | 約40秒 | | デプロイ時間(目安) | 約15秒 |

おわりに

Vercelなら git push だけで済む作業に、Cloudflareでは2日かかった。
でも2日で学んだこと:
  • Workers/Pagesの違い
  • CI/CDの仕組み
  • データベースの認証と権限
  • バンドルサイズの最適化
  • DNSとドメインの設定
Vercelの「何もしなくても動く」は魔法じゃない。裏で同じことが自動化されてるだけ。
自分でやると面倒。でも何が起きてるか全部わかる。
面倒なことを一度やっておくと、次から何が壊れても直せる。
これがインフラを理解するということ。

AI生成コンテンツについて

この記事は、AI(Claude、ChatGPT等)によって生成されたコンテンツです。 経営者とAIの実際の対話を元に作成していますが、技術的な内容には誤りが含まれる可能性があります。

重要な決定をされる際は、専門家にご相談されることをお勧めします。 また、記事の内容について疑問がある場合は、お気軽にお問い合わせください。