cockpit-nuxt-vuetify Nuxt 4 移行計画
背景
Herokuで運用中のcockpit-nuxt-vuetify(月額$7)をCloudflareに移行したいが、Nuxt 2 SSRをそのままCloudflare Pagesで運用するのは現実的でない。Nuxt 2自体のサポートは2024年6月30日に終了(公式LTS)しており、2026-02-15時点の最新安定版はNuxt 4.3.1。Nuxt 4への移行が必要。
現在のHeroku構成

| 項目 | 値 |
|---|---|
| アプリ名 | warm-plains-36011 |
| GitHub | keikomatsu/cockpit-nuxt-vuetify |
| Dyno | Basic ($7/月) |
| 起動コマンド | npm run start |
| デプロイ回数 | 199回 |
なぜ Cloudflare Pages に移行するか
- コスト削減: Heroku Basic Dyno $7/月 → Cloudflare Pages 無料
- パフォーマンス: Cloudflareのグローバルエッジネットワーク
- 簡単なデプロイ: GitHubとの自動連携
- 無料SSL: 自動でHTTPS化
移行方針: 新規プロジェクト立ち上げ
既存コードを書き換えるのではなく、新規Nuxt 4プロジェクトをゼロから作成し、必要な機能だけを移植する。
この方式のメリット
- 799ページ全部を移行しなくて良い - 必要なものだけ選んで移植
- UIを刷新できる - Vuetify 3のデザインをフル活用
- 技術的負債を持ち込まない - リファクタリングしながら進められる
- 段階的に切り替え可能 - 移行完了したページから順次公開
現状のトップページ構造
トップページ(pages/index.vue)には以下のコンテンツカードがある:
外部リンク(移行が簡単)
| カテゴリ | 内容 | 移行難易度 |
|---|---|---|
| Udemy動画講座 | 8講座へのリンク | 簡単 |
| Kindle本 | 2冊へのリンク | 簡単 |
Udemy講座一覧:
- 日商簿記3級編
- 会計・簿記入門編
- Excelショートカット編
- 財務3表編
- Excel基礎編
- Excelで財務三表編
- Excelでキャッシュフロー精算表
- Excelで連結会計入門
内部コンテンツ(静的ページ)
| コンテンツ | URL | 移行難易度 |
|---|---|---|
| 会計・簿記入門編 | /lessons/intro-to-accounting/ | 中 |
| 日商簿記3級_講義テキスト | /lessons/bookkeeping/chapter*/ | 中 |
| 日商簿記3級_スライド | /lessons/bookkeeping/slides/ | 中 |
| Excelショートカット編 | /lessons/excel-shortcuts/ | 中 |
| 財務3表編 | /lessons/financial-statements/ | 中 |
動的コンテンツ(問題集・テスト)
| コンテンツ | URL | 移行難易度 |
|---|---|---|
| 仕訳問題_分野別 | /sampleTest/boki3SampleTestByField | 中 |
| 日商簿記3級問題編 | /workbook/boki3 | 中 |
| 帳簿問題 | /workbook/continuousQuestions | 中 |
注: Firebase認証のコードは存在するが、ルートレベルの保護がなく実質的に未使用。未認証でもページにアクセス可能(空白表示になるだけ)。移行時に認証機能を実装するかは要検討。
旧プロジェクト規模(参考)
| 項目 | 数量 | 備考 |
|---|---|---|
| ページ数 | 799 | 全部は移行しない |
| コンポーネント数 | 219 | 必要なものだけ移植 |
| Vuexストア | 23ファイル | Piniaで再設計 |
| Vuetifyグリッド使用 | 9,394箇所 | 新規で書き直し |
移行戦略: 段階的リリース
Phase 1: 基盤構築 + トップページ
目的: 新Nuxt 4プロジェクトをCloudflareにデプロイ、トップページを公開
- 新規リポジトリ作成(
C:\Users\numbe\Git_repo\eurekapu-nuxt4) - Nuxt 4プロジェクト作成(
npx nuxi@latest init) - Vuetify 3セットアップ(vuetify-nuxt-module v0.19+)
- Cloudflare Pagesデプロイ設定
- トップページ作成(Udemy/Kindleリンクカード)
- 基本レイアウト・ナビゲーション
技術スタック:
Nuxt 4.x
├── Vuetify 3(vuetify-nuxt-module v0.19+)
├── Pinia(状態管理)
└── Cloudflare Pages(ホスティング)
Nuxt 4のディレクトリ構造:
Nuxt 4ではアプリケーションコードが app/ ディレクトリに格納される。
eurekapu-nuxt4/
├── app/
│ ├── assets/
│ ├── components/
│ ├── composables/
│ ├── layouts/
│ ├── middleware/
│ ├── pages/
│ ├── plugins/
│ └── utils/
├── server/
├── public/
├── nuxt.config.ts
└── package.json
nuxt.config.ts:
export default defineNuxtConfig({
compatibilityDate: '2025-01-01',
nitro: {
preset: 'cloudflare_pages'
},
modules: [
'vuetify-nuxt-module',
'@pinia/nuxt'
],
routeRules: {
// 移植済みページを明示的にSSGプリレンダリング
'/': { prerender: true },
'/lessons/bookkeeping/**': { prerender: true },
'/lessons/excel-shortcuts/**': { prerender: true },
'/lessons/financial-statements/**': { prerender: true },
'/lessons/intro-to-accounting/**': { prerender: true },
// 問題集など動的コンテンツはCSR(サーバー不要)
'/workbook/**': { ssr: false },
'/sampleTest/**': { ssr: false },
}
})
Phase 2: 静的コンテンツ移植
目的: 主要な講義テキストを移植
優先順位:
/lessons/bookkeeping/- 日商簿記3級(最もアクセスが多いはず)/lessons/excel-shortcuts/- Excelショートカット/lessons/financial-statements/- 財務3表/lessons/intro-to-accounting/- 会計・簿記入門
移植方法:
- 既存の.vueファイルからコンテンツ(データ)を抽出
- 新しいコンポーネント構造で再実装
- UIはVuetify 3で刷新
Phase 3: 問題集・テスト機能
目的: 復習アプリ・問題集機能を移植
-
/sampleTest/- サンプルテスト -
/workbook/boki3- 仕訳問題
認証について: Firebase認証は廃止。現状のFirebase認証はルート保護すらされておらず実質未使用。新規プロジェクトには移植しない。将来的にアプリ内ユーザー認証が必要になれば別途設計する(Cloudflare Accessはサイト入口の制御であり、アプリ内認証の代替ではない点に注意)。
URL戦略
方針: 主要URLは維持、細かいのは整理
# 維持するURL
/lessons/bookkeeping/... → そのまま
/lessons/excel-shortcuts/ → そのまま
# 整理するURL(リダイレクト設定)
/lessons/bookkeeping/chapter01/00-bspl → /boki3/1/bspl(短縮案)
SEO対応
- 旧→新URL対応表を作成(アクセス上位ページ分)
-
public/_redirectsに301リダイレクトを設定 - 各ページに
canonicalタグを設定 - 新サイトのサイトマップを生成・Search Consoleに送信
Cloudflareリダイレクト設定
public/_redirects:
# 旧URL → 新URL(URL構造を変更した場合のみ)
/old-path /new-path 301
旧サイトからの切り替え
Step 1: 新サイトを別ドメインで公開
新: cockpit.pages.dev(Cloudflare)
旧: app.eurekapu.com(Heroku)← まだ稼働
Step 2: 動作確認
- 移植済みページのURLスモークテスト(200応答確認)
- 旧→新URLの301リダイレクト検証
- Search Consoleでサイトマップ送信・インデックス状況確認
Step 3: ドメイン切り替え
新: app.eurekapu.com(Cloudflare)
旧: 停止
DNS TTL: 切り替え前にTTLを短く(300秒程度)設定し、問題発生時に即戻せるようにする。
Step 4: ロールバック条件
切り替え後に以下の状況が発生した場合、Cloudflare Pagesのロールバック機能またはDNSをHerokuに戻す:
- 主要ページで404/500エラーが多発
- Search Consoleでインデックス激減
Step 5: Heroku削除
切り替え後1-2週間の安定運用を確認した後、Herokuを停止。月額$7の節約完了。
費用比較
| 項目 | Heroku | Cloudflare Pages (Free) |
|---|---|---|
| 月額費用 | $7 (Basic Dyno) | $0(静的配信のみ) |
| 帯域幅 | 制限なし | 無制限 |
| ビルド回数 | - | 500回/月 |
| 同時ビルド | 1 | 1 |
注: SSG(静的生成)のみであればFunctions課金は発生しない。SSR/Functionsを使う場合はWorkers課金枠(Free: 日10万リクエスト上限)に入るため、本プロジェクトはSSG前提で$0を維持する。
トラブルシューティング
ビルドエラー: Node.js バージョン
Cloudflare Pages Build Image v3のデフォルトはNode.js 22系。再現性のため .node-version または NODE_VERSION 環境変数でバージョンを固定する:
NODE_VERSION=22
404エラー
SSGの場合、原因を以下の順で切り分ける:
- 静的配信: ビルド出力(
.output/public/)に該当HTMLが生成されているか確認 - routeRules:
nuxt.config.tsのrouteRulesでプリレンダリング対象に含まれているか確認 - リダイレクト:
public/_redirectsのルールが意図通りか確認
※ _routes.json はPages Functions(SSR)の呼び出し制御用。SSGのみの場合は関係しない。
API呼び出しのCORSエラー
Cloudflareのドメインからのリクエストを許可するよう、APIサーバー側のCORS設定を更新。
工数見積もり(Claude Code実装前提)
Claude Codeが旧プロジェクトの.vueファイルを読み取り、Nuxt 4 + Vuetify 3形式に変換する。アクセス解析で確認済みの高トラフィックページのみを対象とする。
| フェーズ | 期間 | 備考 |
|---|---|---|
| Phase 1: 基盤 + トップページ | 1日 | nuxi init + Vuetify設定 + Cloudflareデプロイ |
| Phase 2: コンテンツ移植 | 1-2日/セクション | 旧.vueから自動変換、アクセス上位のみ |
| Phase 3: 問題集・テスト | 1-2日 | 認証なし、CSRで実装 |
※ Firebase認証は廃止。移行対象外。
移植しないもの(廃止候補)
調査で見つかった、おそらく不要なコンテンツ:
pages/testPage/- テスト用components/test/- テスト用コンポーネントstore/testtest.js,store/hoge-module.js- 未使用ストアpages/tbd/,pages/tbd02/- 未完成コンテンツ
リポジトリ構成
C:\Users\numbe\Git_repo\
├── cockpit-nuxt-vuetify/ ← 旧プロジェクト(Nuxt 2、Heroku)※移行完了後に廃止
├── mdx-playground/ ← ブログ・コンテンツ管理(現プロジェクト)
└── eurekapu-nuxt4/ ← 新規作成(独立リポジトリ)
- 新規の独立Gitリポジトリとして
eurekapu-nuxt4を作成 - mdx-playgroundとは別管理。デプロイ・CI/CDも独立
- GitHub: 新規リポジトリを作成し、Cloudflare Pagesと連携
次のアクション
-
C:\Users\numbe\Git_repo\eurekapu-nuxt4に新規リポジトリ作成 -
npx nuxi@latest initでNuxt 4プロジェクト初期化 - Vuetify 3 + Pinia セットアップ
- Cloudflare Pagesデプロイ確認
- トップページ(Udemy/Kindleリンクカード)実装
- アクセス上位の講義ページから移植開始
CSSフレームワークの検討: Vuetify vs Tailwind
結論: Vuetify 3 を採用
Tailwind CSS への移行も検討したが、Vuetify 3 を採用することに決定。
比較検討
| 項目 | Vuetify 3 | Tailwind CSS |
|---|---|---|
| 性質 | コンポーネントライブラリ | CSSユーティリティ |
| フォーム | <v-text-field> で完結 | 自作 or ライブラリ追加 |
| ダイアログ | <v-dialog> | Headless UI等が必要 |
| テーブル | <v-data-table> | 自作 |
| カード | <v-card> | div + Tailwindクラス |
Vuetify 3 を選んだ理由
- 問題集・テスト機能との相性
- フォーム入力、バリデーション、正誤判定のUIが必要
- Vuetifyならコンポーネントが揃っている
- 新規プロジェクト方式のメリット
- Vuetify 2→3 の互換性問題は既存コードを引きずらないので軽微
- 旧プロジェクトの構造を参考にしつつ、クリーンに実装可能
- 開発効率
- UIコンポーネントを自作する必要がない
- 定型的なコードで速く書ける
Tailwind が向いているケース(参考)
- マーケティングサイト、LP(見た目重視、機能少なめ)
- デザイナーがいて独自デザインを追求したい
- 軽量さが最優先
このプロジェクトは「学習コンテンツ + 問題集」という機能系UIが多いため、Vuetifyの方が適している。
レビュー・意思決定ログ(2026-02-15)
確定事項
| 項目 | 決定 | 理由 |
|---|---|---|
| レンダリング | SSG前提(ハイブリッド) | 教育コンテンツは更新頻度低。問題集のみCSR |
| Firebase認証 | 廃止 | ルート保護なし、実質未使用。移植しない |
| コンテンツ形式 | .vueファイル維持 | インタラクティブな要素が多く、Markdown化は困難 |
| 移行スコープ | アクセス上位ページのみ | GA/Search Console確認済み。限定的に移行 |
| 実装主体 | Claude Code | 旧.vueファイルの自動変換で高速に移植 |