Add ViteHelper fallback for missing frontend assets
This commit is contained in:
14
README.md
14
README.md
@@ -208,6 +208,20 @@ If you prefer manual control:
|
||||
| `make setup-laravel` | Configure auth, API, middleware |
|
||||
| `make setup-all` | Run both setup scripts |
|
||||
|
||||
### Frontend Assets (Vite)
|
||||
|
||||
Build frontend CSS/JS assets:
|
||||
|
||||
```bash
|
||||
# Build assets for production
|
||||
docker-compose run --rm node npm run build
|
||||
|
||||
# Or run Vite dev server (hot reload)
|
||||
docker-compose --profile frontend up -d
|
||||
```
|
||||
|
||||
> **Note:** The template includes a resilient fallback - if assets aren't built, basic styling is provided and a development warning is shown. This prevents the `ViteManifestNotFoundException` error from breaking the app.
|
||||
|
||||
## Laravel Setup (Auth, API, Middleware)
|
||||
|
||||
After installing Laravel, run the interactive setup:
|
||||
|
||||
@@ -38,6 +38,11 @@ RUN pecl install redis && docker-php-ext-enable redis
|
||||
# Install Composer
|
||||
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||
|
||||
# Install Node.js for asset building
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
||||
&& apt-get install -y nodejs \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Create system user to run Composer and Artisan commands
|
||||
RUN useradd -G www-data,root -u 1000 -d /home/devuser devuser
|
||||
RUN mkdir -p /home/devuser/.composer && \
|
||||
@@ -61,6 +66,13 @@ RUN chown -R devuser:www-data /var/www/html \
|
||||
&& chmod -R 775 /var/www/html/storage 2>/dev/null || true \
|
||||
&& chmod -R 775 /var/www/html/bootstrap/cache 2>/dev/null || true
|
||||
|
||||
# Build frontend assets (if package.json exists)
|
||||
RUN if [ -f "package.json" ]; then \
|
||||
npm ci --ignore-scripts && \
|
||||
npm run build && \
|
||||
rm -rf node_modules; \
|
||||
fi
|
||||
|
||||
# Run post-install scripts
|
||||
USER devuser
|
||||
RUN composer run-script post-autoload-dump 2>/dev/null || true
|
||||
|
||||
88
src/app/Helpers/ViteHelper.php
Normal file
88
src/app/Helpers/ViteHelper.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
class ViteHelper
|
||||
{
|
||||
/**
|
||||
* Check if the Vite manifest exists (assets have been built).
|
||||
*/
|
||||
public static function manifestExists(): bool
|
||||
{
|
||||
return file_exists(public_path('build/manifest.json'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fallback CSS for when Vite assets are not built.
|
||||
* This provides basic styling so the app remains usable.
|
||||
*/
|
||||
public static function fallbackStyles(): string
|
||||
{
|
||||
return <<<'CSS'
|
||||
<style>
|
||||
/* Fallback styles when Vite assets are not built */
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
body {
|
||||
font-family: ui-sans-serif, system-ui, sans-serif;
|
||||
margin: 0;
|
||||
background: #f3f4f6;
|
||||
color: #111827;
|
||||
}
|
||||
.dark body { background: #111827; color: #f9fafb; }
|
||||
.min-h-screen { min-height: 100vh; }
|
||||
.bg-gray-100 { background: #f3f4f6; }
|
||||
.bg-white { background: #fff; }
|
||||
.shadow { box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
|
||||
.max-w-7xl { max-width: 80rem; margin: 0 auto; }
|
||||
.px-4 { padding-left: 1rem; padding-right: 1rem; }
|
||||
.py-6 { padding-top: 1.5rem; padding-bottom: 1.5rem; }
|
||||
.font-semibold { font-weight: 600; }
|
||||
.text-xl { font-size: 1.25rem; }
|
||||
.text-gray-800 { color: #1f2937; }
|
||||
a { color: #3b82f6; text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
.hidden { display: none; }
|
||||
.flex { display: flex; }
|
||||
.items-center { align-items: center; }
|
||||
.justify-between { justify-content: space-between; }
|
||||
.space-x-4 > * + * { margin-left: 1rem; }
|
||||
nav { background: #fff; border-bottom: 1px solid #e5e7eb; padding: 1rem; }
|
||||
.container { max-width: 80rem; margin: 0 auto; padding: 0 1rem; }
|
||||
button, .btn {
|
||||
padding: 0.5rem 1rem;
|
||||
background: #3b82f6;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 0.375rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
button:hover, .btn:hover { background: #2563eb; }
|
||||
input, select, textarea {
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.5rem 0.75rem;
|
||||
width: 100%;
|
||||
}
|
||||
.alert { padding: 1rem; border-radius: 0.375rem; margin-bottom: 1rem; }
|
||||
.alert-warning { background: #fef3c7; border: 1px solid #f59e0b; color: #92400e; }
|
||||
</style>
|
||||
CSS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a warning banner HTML for development.
|
||||
*/
|
||||
public static function devWarningBanner(): string
|
||||
{
|
||||
if (app()->environment('production')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return <<<'HTML'
|
||||
<div class="alert alert-warning" style="margin:1rem;padding:1rem;background:#fef3c7;border:1px solid #f59e0b;border-radius:0.5rem;color:#92400e;">
|
||||
<strong>⚠️ Development Notice:</strong> Vite assets are not built.
|
||||
Run <code style="background:#fde68a;padding:0.125rem 0.25rem;border-radius:0.25rem;">docker-compose run --rm node npm run build</code> to build assets.
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
2
src/package-lock.json
generated
2
src/package-lock.json
generated
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "app",
|
||||
"name": "html",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -21,9 +21,16 @@
|
||||
</style>
|
||||
|
||||
<!-- Scripts -->
|
||||
@if(\App\Helpers\ViteHelper::manifestExists())
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
@else
|
||||
{!! \App\Helpers\ViteHelper::fallbackStyles() !!}
|
||||
@endif
|
||||
</head>
|
||||
<body class="font-sans antialiased">
|
||||
@if(!\App\Helpers\ViteHelper::manifestExists())
|
||||
{!! \App\Helpers\ViteHelper::devWarningBanner() !!}
|
||||
@endif
|
||||
<div class="min-h-screen bg-gray-100 dark:bg-gray-900">
|
||||
@include('layouts.navigation')
|
||||
|
||||
|
||||
@@ -21,9 +21,16 @@
|
||||
</style>
|
||||
|
||||
<!-- Scripts -->
|
||||
@if(\App\Helpers\ViteHelper::manifestExists())
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
@else
|
||||
{!! \App\Helpers\ViteHelper::fallbackStyles() !!}
|
||||
@endif
|
||||
</head>
|
||||
<body class="font-sans text-gray-900 antialiased">
|
||||
@if(!\App\Helpers\ViteHelper::manifestExists())
|
||||
{!! \App\Helpers\ViteHelper::devWarningBanner() !!}
|
||||
@endif
|
||||
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100 dark:bg-gray-900">
|
||||
<div>
|
||||
<a href="/">
|
||||
|
||||
Reference in New Issue
Block a user