← ./articles-ja

Vite buildが成功表示後に落ちる時はdistの鮮度で判定する

Windowsでは、ViteやNode.jsのbuildが成果物を書き出したあとに落ちることがあります。

ログには built in ... と出るのに、プロセスの終了コードは非ゼロ。TauriのpackagingやCIでは、この状態をどう扱うかが問題になります。

ここで一番危ないのは、dist/ が存在するだけで成功扱いすることです。前回の古い dist/ が残っていれば、今回のbuildが失敗していても成功に見えてしまいます。

症状

よくある見え方は次のようなものです。

vite build
✓ built in 4.2s
process exited with code -1073741819

Windowsでは 0xC0000005 のようなaccess violationとして見えることもあります。

このとき、本当にbuildが失敗したのか、成果物を書いたあとにteardownで落ちただけなのかを分ける必要があります。

distがあるだけでは不十分

次の確認は危険です。

vite build
test -f dist/index.html

dist/index.html が前回buildの残骸でも通ってしまうからです。

必要なのは、今回のbuildで新しく生成されたことの確認です。

  • build前に dist/ を消す
  • 今回 index.html が作られたことを確認する
  • index.html が参照するassetが存在する
  • WASMなど必須assetが空ファイルではない

PowerShell wrapperで判定する

Windowsでは、PowerShellを親プロセスにしてbuildを実行すると扱いやすいです。Nodeの子プロセスが落ちても、PowerShell側で結果を判定できます。

$ErrorActionPreference = "Stop"
$Dist = Join-Path (Get-Location) "dist"

if (Test-Path $Dist) {
  Remove-Item $Dist -Recurse -Force
}

npm run typecheck
npm run vite-build

$index = Join-Path $Dist "index.html"
if (-not (Test-Path $index)) {
  throw "dist/index.html was not created"
}

$age = (Get-Date) - (Get-Item $index).LastWriteTime
if ($age.TotalSeconds -gt 10) {
  throw "dist/index.html is stale"
}

本番用には、Viteの終了コードも取り、非ゼロでも成果物が新鮮で完全なら「emit後クラッシュ」として扱う、という分岐にします。

判定ルール

考え方は次の通りです。

exit 0 + fresh output        -> 成功
exit non-zero + fresh output -> emit後クラッシュとして扱える
exit non-zero + stale output -> 失敗、retryまたは停止

非ゼロを全部無視するのは危険です。TypeScriptエラー、importミス、asset欠落は失敗として止めるべきです。

使いどころ

この手順は、次の条件で役に立ちます。

  • buildログでは成功に見える
  • 終了コードだけ非ゼロ
  • Windowsでたまに落ちる
  • Tauriなどのpackaging前にfrontend成果物が必要
  • 古い dist/ を成功扱いしたくない

特にデスクトップアプリのrelease buildでは、frontend buildの失敗を見逃すと、起動しても画面がないexeを作ることがあります。

まとめ

Vite buildが成功表示後に落ちる時、dist/ の存在だけで判断しないでください。

build前に dist/ を消し、今回生成された成果物かどうかを確認します。これで、本当の失敗とemit後クラッシュを分けられます。

参考