ブラウザゲーム開発者の作業環境 2026 — 203個のコンポーネントを支えるツールチェーン
このトピックを深掘りする
ブラウザゲーム開発
ゲームループ・衝突判定・経路探索・迷路生成など、ブラウザゲーム開発の実装パターン集
全7本中 1 本目。
次に読む記事
ブラウザで作るBreakoutゲーム — Canvas APIで反射角とレベルデザインを攻略する
Canvas APIとrequestAnimationFrameでBreakoutゲーム(ブロック崩し)を実装する。パドルの反射角計算、ブロック配置のレベルデザイン、スコア管理の勘所をコンポーネント実装を通じて解説。
迷路生成アルゴリズム比較 — 再帰バックトラッキング・Kruskal・Primが作る迷路の違い
再帰バックトラッキング、Kruskal法、Prim法など複数の迷路生成アルゴリズムの特性と、生成される迷路の構造的な違いを比較する。
探索アルゴリズムを可視化する — A*・BFS・DFSが迷路を解く様子
MazeRunnerコンポーネントで実装したA*、BFS、DFSの探索過程を可視化する技法と、各アルゴリズムの比較を解説する。
シリーズ全体の流れを見ながら、次に読む記事へ進めます。 初めての方はホームへ →
はじめに
このポートフォリオサイトには約200個のインタラクティブコンポーネントがある。流体シミュレーション、ピンボール、迷路生成、ピアノ、セルオートマトン——ブラウザ上で動く小さなデモを次々と追加してきた結果だ。
これだけの数を効率的に開発・メンテナンスするには、ツールチェーンの選定が重要になる。だが自分のモットーは「道具は少なく、各道具を深く使う」だ。新しいツールを導入するたびに認知負荷が増える。設定ファイルが増える。チームメイト(この場合は未来の自分)が覚えることが増える。
この記事では、約200個のコンポーネントを実際に支えているツールチェーンを紹介する。派手な構成ではない。bun、Biome、Vite、Claude Code。この4つが中核で、それぞれを深く使い倒している。
エディタ: ターミナルファースト
Claude Code がメインの開発ツール
エディタは何を使っているかと聞かれると、正直に答えると「ターミナル」だ。具体的には Claude Code (CLI) がメインの開発ツールになっている。
# 新しいコンポーネントを作る
claude "PendulumWaveコンポーネントを作って。src/components/interactions/PendulumWave.tsxに配置"
# バグを直す
claude "FluidSimulationでCanvasサイズが0のとき描画が壊れるバグを直して"
# リファクタする
claude "このファイルのmouseイベントをPointer Eventsに統一して"コードを書く行為の大部分を Claude Code に委ねている。自分がやるのは「何を作るか」の指示と、出力されたコードの確認だ。
VS Code は「見る」ためのツール
VS Code も使っているが、役割が変わった。コードを書くためではなく、ファイルブラウジングと差分確認に使っている。
- ファイルツリーでプロジェクト構造を俯瞰
- Git差分をサイドバイサイドで確認
- 複数ファイルをタブで開いて比較AIがコードを書く時代、エディタは「見る」ためのツールになった。キーバインドのカスタマイズや拡張機能の厳選に時間をかけるより、Claude Code への指示の出し方を磨くほうがリターンが大きい。
パッケージマネージャ: bun
npm → bun 移行の理由
npm から bun に移行したのは単純な理由だ。速い。
# 依存関係のインストール
bun install # npm install の 5-10倍速
# スクリプト実行
bun run dev # 開発サーバー起動
bun run build # プロダクションビルド + tsc
bun run check # Biome lint + format約200個のコンポーネントがあると依存関係も多くなる。bun install の速さは体感で分かるレベルだ。CI で毎回走るのだから、ここの短縮は積み重なる。
bunx でMCPサーバーも起動
npx の代わりに bunx を使っている。MCP (Model Context Protocol) サーバーの起動もこれで統一した。
bunx @anthropic/mcp-server-filesystem /path/to/projectパッケージマネージャを統一すると、「これは npx で動かすんだっけ、bunx だっけ」という判断がなくなる。小さいことだが、判断を1つ減らすことの価値は大きい。
CI/CD でも bun
GitHub Actions でも bun を使っている。
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: bun-\${{ hashFiles('bun.lock') }}oven-sh/setup-bun@v2 でセットアップし、actions/cache@v4 でキャッシュする。ローカルと CI で同じパッケージマネージャを使うことで、「ローカルでは動くのに CI で落ちる」問題を減らせる。
npm に戻る理由がない。
リンター/フォーマッター: Biome
ESLint + Prettier → Biome 一本化
かつては ESLint + Prettier の組み合わせを使っていた。この2つの設定ファイルを管理するのが地味に面倒だった。競合するルール、プラグインのバージョン管理、.eslintrc と .prettierrc の二重管理。
Biome に一本化してから、設定ファイルは biome.json の1つだけになった。
{
"formatter": {
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"semicolons": "asNeeded"
}
}
}single quotes、2 spaces、100 width、semicolons asNeeded。この設定を1つのファイルで完結させている。
開発フロー
# ローカル: lint + format を一発で
bun run check
# CI: 読み取り専用チェック(ファイルを変更しない)
bunx biome ci .bun run check は lint と format を同時に実行する。biome ci は CI 用のコマンドで、問題があればエラーを返すがファイルは変更しない。
設定ファイルが1つになった快適さは想像以上だ。新しいプロジェクトを作るとき、biome.json を1つコピーすれば終わる。ESLint のプラグイン依存地獄から解放された。
ビルド: Vite
HMR が速い
Vite の HMR(Hot Module Replacement)は速い。ファイルを保存してからブラウザに反映されるまで約50ms。約200個のコンポーネントがあるプロジェクトでも、この速度は維持される。
Canvas ベースのコンポーネントを開発していると、パラメータを微調整 → 結果を確認、のサイクルを何十回も繰り返す。流体シミュレーションの粘性係数、パーティクルの減衰率、物理エンジンの重力定数。このサイクルが50msで回るのと2秒かかるのでは、体験が根本的に違う。
プラグイン順序が命
Vite の設定で最も重要なのはプラグインの順序だ。
// vite.config.ts
export default defineConfig({
plugins: [
tailwindcss(), // 1. Tailwind CSS
tsConfigPaths(), // 2. パスエイリアス解決
cloudflare(), // 3. Cloudflare Pages
tanstackStart(), // 4. TanStack Start
react(), // 5. React
],
})この順序を間違えると、ビルドが通らなかったり、デプロイ後に謎のエラーが出る。特に Cloudflare PagesはTanStack Startより前に配置する必要がある。これを見つけるのに半日かかった。
Vite の速さは開発体験を根本的に変える。webpack 時代に戻れないのと同じように、Vite 以前には戻れない。
バージョン管理: Git Worktree
ブランチではなく worktree で分離する
約200個のコンポーネントを開発していると、複数のタスクを並行して進めたくなる。コンポーネントAのバグ修正をしながら、コンポーネントBの新機能を開発し、コンポーネントCのリファクタを走らせる。
Git ブランチだけでこれをやると、git stash と git checkout の嵐になる。作業途中のファイルを stash して、別ブランチに切り替えて、終わったら戻って stash pop——これは事故の元だ。
Git Worktree を使うと、ファイルシステムが物理的に分かれる。
# 独立タスクは cc <name> で別 worktree に Claude を起動
cc fix-fluid-sim # worktree を作成し、そこで Claude Code を起動
cc add-pinball # 別の worktree で別の Claude Code セッション
cc refactor-physics # さらに別の worktree各 worktree は独立したディレクトリだ。ファイルの競合が物理的に起きない。
並列開発の実際
ターミナルを3-4つ開いて、それぞれで Claude Code セッションを走らせる。1ターミナル1タスクの原則だ。
ターミナル1: cc fix-audio-context → AudioContext のバグ修正
ターミナル2: cc add-maze-solver → 迷路ソルバーの新規追加
ターミナル3: cc refactor-canvas → Canvas コンポーネントのリファクタ
ターミナル4: メインの worktree → 差分確認、マージ各タスクが完了したら staging ブランチへ自動マージされる。コンフリクトが起きるのは稀だ。なぜなら、約200個のコンポーネントはそれぞれ独立したファイルだから。FluidSimulation.tsx と MazeGenerator.tsx が同時に変更されても、競合しない。
ブランチではなく worktree で分離する理由は明快だ。ファイルシステムが物理的に分かれるから、「今どのブランチにいるんだっけ」という認知負荷がゼロになる。
CI/CD: GitHub Actions + Blacksmith
Blacksmith runners
CI は GitHub Actions を使い、ランナーは Blacksmith を選んでいる。GitHub のデフォルトランナーより速く、コストも低い。
runs-on: blacksmith-2vcpu-ubuntu-24042ステップのデプロイ
デプロイパイプラインはシンプルだ。
steps:
- run: bun install
- run: bun run build
- run: bunx wrangler pages deploybun run build でプロダクションビルド(TypeScript の型チェック込み)を行い、wrangler で Cloudflare Pages にデプロイする。
不要なビルドのスキップ
dorny/paths-filter を使って、変更されたファイルパスに応じてジョブをスキップしている。
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
src:
- 'src/**'
- 'package.json'
- 'bun.lock'ドキュメントだけの変更でビルドとデプロイが走るのは無駄だ。パスフィルタでこれを防ぐ。
AI開発: Claude Code
CLAUDE.md でプロジェクトコンテキストを与える
Claude Code の最も重要な機能は CLAUDE.md だ。プロジェクトルートに置くマークダウンファイルで、セッション開始時に自動で読み込まれる。
# CLAUDE.md
## Tech Stack
- Framework: TanStack Start v1.x (React 19)
- Styling: Tailwind CSS v4
- Animation: Motion (motion/react) + Canvas API
- Deploy: Cloudflare Pages
## 注意事項
- motion のインポートは motion/react(framer-motion ではない)
- パスエイリアス ~/ → ./src/
- Viteプラグイン順序: tailwindcss → tsConfigPaths → cloudflare → tanstackStart → reactこれを書いておくだけで、Claude Code は「このプロジェクトでは framer-motion ではなく motion/react を使う」「パスエイリアスは ~/ だ」といったことを最初から知っている状態で動く。約200個のコンポーネントすべてで一貫したコードが生成される。
takt ワークフロー
タスクの規模に応じてワークフローを自動選択する仕組みを作っている。
| 規模 | ワークフロー | 例 |
|---|---|---|
| typo修正、1行変更 | そのまま実装 | 変数名の修正 |
| バグ修正、3ファイル以下 | quick-fix | AudioContext のエラーハンドリング |
| 新機能、複数ファイル | plan-implement-review | 新しいゲームコンポーネント |
| 大機能、アーキテクチャ変更 | spec-then-build | 物理エンジンの設計変更 |
小さなタスクにフルのレビュープロセスを適用するのは無駄だし、大きなタスクをレビューなしで進めるのは危険だ。規模に応じた適切なプロセスを自動で選ぶ。
1セッション1タスク
Claude Code を使う上で最も重要な原則がこれだ。
同じ問題で2回失敗 → /clear
無関係なタスク間でも → /clearLLM にはコンテキストウィンドウという制約がある。1つのセッションで複数のタスクを詰め込むと、古い情報が圧縮(実質的には忘却)される。30ファイル目あたりから修正の精度が落ちていく。
だからタスクを分割する。1セッションで1つのことだけをやる。終わったら /clear でリセット。この原則を守るだけで、出力品質が劇的に安定する。
AIは道具の1つだ。だが、最も生産性を変えた道具であることは間違いない。
まとめ:ブラウザゲーム開発環境
自分のツールチェーンを改めて書き出してみると、構成要素は驚くほど少ない。
- パッケージマネージャ: bun
- リンター/フォーマッター: Biome
- ビルド: Vite
- AI開発: Claude Code
- バージョン管理: Git + Worktree
- CI/CD: GitHub Actions + Blacksmith
- デプロイ: Cloudflare Pages
7つだ。しかも bun、Biome、Vite、Claude Code の4つが中核で、残りは周辺ツールに過ぎない。
道具を減らすほど、各道具の使い方が深くなる。bun の lockfile 最適化、Biome のルールカスタマイズ、Vite のプラグイン順序、Claude Code の CLAUDE.md 設計。1つ1つの道具を深く理解しているから、約200個のコンポーネントを効率的に開発・メンテナンスできている。
新しいツールが出るたびに飛びつくのではなく、今使っているツールをもう一段深く使ってみる。その方が、長い目で見て生産性は高い。