こんにちは。開発環境の設計を愛してやまないアーキテクトです。
フロントエンド開発において、Viteはもはや標準と言っても過言ではない高速ビルドツールですが、ローカル環境で動いていたはずのビルドが、CI(GitHub Actions)上で突然沈黙する……そんな経験はありませんか?
「なぜローカルでは動くのか?」「このエラーメッセージは何を言っているのか?」という問いに対し、表面的な解決策ではなく、CI/CDの深層に流れる「アーキテクチャの真理」を紐解いていきましょう。
—
1. Viteビルドにおける「環境変数の密約」を理解する
ローカルの `.env` ファイルに書いた変数が、GitHub Actionsで読み込まれないという悩みは、フロントエンド開発の「通過儀礼」です。
根本的な仕組み
Viteはビルド時に `import.meta.env` を通じて環境変数を静的に置き換えます。つまり、ビルドする瞬間にその環境変数が存在していなければ、コードに埋め込まれないのです。
GitHub Actionsでは、`env` キーで定義した変数を確実に渡す必要があります。
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: npm run build
env:
# ここで明示的に渡す必要がある。
# GitHub Secretsから読み込むのがベストプラクティス。
VITE_API_BASE_URL: ${{ secrets.API_BASE_URL }}
アーキテクトからの助言:
`.env` ファイルをGit管理に含めるのはセキュリティ上NGですが、CI用に `.env.production` を隠蔽して管理するような脆弱な設計は避けましょう。GitHub Actionsの `env` キーを使うことで、ビルドプロセスに「注入」するアーキテクチャこそが、堅牢なパイプラインの第一歩です。
—
2. キャッシュ戦略:パッケージマネージャとの「静かなる闘争」
「ビルドが遅いからキャッシュしたい」と考え、安易に `node_modules` をキャッシュしていませんか?それは危険な賭けです。
最適なキャッシュ戦略
`npm ci` や `yarn install` は、ロックファイル(`package-lock.json`)のハッシュ値と、Node.jsのバージョン、そしてOSの組み合わせを厳密にチェックしています。
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
# ここでキャッシュを管理。キーにロックファイルを指定するのが鍵。
cache: ‘npm’
- name: Install Dependencies
run: npm ci # npm install ではなく npm ci を使うこと!
なぜ `npm ci` なのか?
`npm install` は `package.json` を見て動的にパッケージを更新しようとしますが、CI環境でこれをやると、「昨日は動いたのに今日は壊れた」という再現不可能なバグを生みます。`npm ci` はロックファイルのみを信頼し、クリーンな環境を構築する。これがCIにおける唯一の正解です。
—
3. Node.jsバージョン指定の「罠」
CI上でNode.jsのバージョンを省略、あるいは `latest` にしていませんか?これは「明日、突然ビルドが失敗する」という爆弾を抱えることと同義です。
バージョンの固定がもたらす安心感
Viteやそのプラグインは、Node.jsの特定のAPIに依存していることがあります。`setup-node` アクションでは、必ず `.nvmrc` を参照するか、固定値を使うべきです。
- uses: actions/setup-node@v4
with:
# 常にプロジェクトがサポートする最低限のLTSバージョンを指定する
node-version-file: ‘.nvmrc’
もしローカルとCIで挙動が違うなら、まずはこの「Node.jsのバージョン」と「npmのバージョン」が一致しているかを確認してください。
—
4. 現場で使える「最強のデバッグ用」HelloWorld
CIでビルド失敗が起きたとき、ログが少なすぎて絶望したことはありませんか?
以下のテンプレートを導入して、CIの可視性を極限まで高めましょう。
name: Robust Frontend Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Debug Environment
run: |
echo “Node version: $(node -v)”
echo “NPM version: $(npm -v)”
# ビルド時に環境変数が正しく渡されているか確認するダンプ
echo “Is VITE_API_BASE_URL set? ${{ secrets.API_BASE_URL != ” }}”
- name: Install
run: npm ci
- name: Build
run: npm run build
env:
VITE_API_BASE_URL: ${{ secrets.API_BASE_URL }}
—
アーキテクトとしての結び
CI/CDを自動化するということは、単に「手間を省く」ことではありません。「自分以外の誰か(あるいは未来の自分)が同じ環境を再現できるように、知識をコードという形に定着させること」です。
Viteのビルド失敗の多くは、環境変数の注入漏れ、あるいはロックファイルと実際の環境の不一致から生まれます。今日紹介した「`npm ci` の徹底」「環境変数の明示的注入」「バージョンファイルの正当な管理」という3本柱を意識すれば、あなたのフロントエンド・パイプラインは、どんな嵐の中でも揺るがない岩盤のような安定性を手に入れるはずです。
さあ、恐れずにパイプラインを回しましょう。失敗から学ぶことこそ、最高のエクスペリエンスなのですから。