Go × Vue3 混在プロジェクトでの“健全なビルド構成”とは
Vue 3 + Vite で SPA を運用していると、「一部ページだけ Go のテンプレートで SSR したい」「複数の HTML を生成して MPA 風に使いたい」といった要望が出てくることがあります。
今回、私もまさにこのパターンにハマり、SPA の制約から逃げようとしてハマり続けた経験をまとめます。
結論から言うと:
Vite のデフォルト構成は完全 SPA 前提なので、素直に MPA 設定をしない限り抜け出せない。
無理に/vue/以下に収めようとすると依存ファイルが解決できず不具合が出る。
という話です。
■ そもそも何が問題だったか?
### 1. index.js をバージョンなし(非ハッシュ)で配置すると2回呼び出される
Vite は通常「ハッシュ付きのファイル名」を生成します。
例:
index-AbCdEf.js
index-Eq6LqhmS.css
しかし私はキャッシュ制御の都合で、ハッシュなしの固定パスで出したかった。
assets/index.js に固定すると、なぜか モジュールが二重に読み込まれる。
原因:
Vite の内部ロジックが「ハッシュ前提」なので、ハッシュなしだと開発・ビルドの両方で同じエントリを2度生成してしまう という挙動が起きてしまう。
2. vue 配下にまとめようとしても結局ドキュメントルートに依存する
base: '/vue/' とすると生成されるファイルは /vue/... を前提に作られる。
しかし Go のテンプレートから直接呼び出す場合は、ドキュメントルート / からのパスでアクセスされるため、中途半端な階層に置いても必ずパス解決で破綻する。
さらに /src/main.js を <script type="module"> で読んでいる限り、Vite のビルド成果物と競合し、結果的に 2 重ロードが発生する。
3. dist を public に上書きするとアプリ全体の public が破壊される
public フォルダにはもともと:
/public
/data
/img
/js
index.html
service-worker.js
のように重要なファイルがある。
しかし emptyOutDir: true のままビルドすると、
Vite が public フォルダを片っ端から削除して再生成してしまう
→ Go サーバー用の静的ファイルも全部吹き飛ぶ。
これを避けるためには:
emptyOutDir: false
にするしかない。
■ 最終的にどう解決したか?
✔ MPA 設定をし、複数の HTML を明示的に指定した
build: {
emptyOutDir: false,
rollupOptions: {
input: {
main: fileURLToPath(new URL('./index.html', import.meta.url)),
setting: fileURLToPath(new URL('./view/test.html', import.meta.url))
}
}
}
こうすることで:
-
Vue SPA の「単一 entry」制約から開放
-
Go テンプレートと共存できる
-
dist を public に置いても破壊されない
という状態を確保できた。
■ 開発環境・本番環境で必要になった運用フロー
1. 開発環境
Vite は SPA として動き続けるが、Go 側で必要な HTML を読み込むために、OS の symlink で dist 等のファイルを接続する必要がある。
しかし、このやり方はNginxの特別な設定が必要
例:
ln -s /app/vue/dist/assets /app/public/vue/assets
ln -s /app/vue/dist/index.html /app/public/vue/index.html
2. デプロイ
デプロイ先では:
-
public/ を破壊しないように outDir を部分同期
-
必要な HTML(index.html, test.html …)だけコピー
-
/vue/配下に置くか/に置くかを明確に決める
という調整が必要。
■ 今回わかったこと(要点)
● Vue + Vite は標準で「完全 SPA」を想定している
無理に「index.html 以外」を作ろうとすると破綻する。
● Vite のハッシュなしビルドは2重ロードの温床
内部キャッシュと競合しやすい。
● outDir を public にするなら emptyOutDir: false が必須
そうしないと public ディレクトリが削除される。
● MPA にするなら rollupOptions.input は必須
これをしないとすべてのページが1つの SPA に吸い込まれる。
■ まとめ
Vite の SPA モードから逃れようとすると相当な抵抗があり、
特に Go のテンプレートと併用する構成だと想像以上のハマりポイントが出てくる。
しかし最終的には:
-
MPA を公式的に設定する
-
出力先の管理を慎重に行う
-
public を削除しない設定にする
-
URI の基準(/vue/ or /)を明確化する
これらを整理することで、Vue と Go の共存運用が安定した。
登録日:
更新日: