Laravel (Sail): Vite Dev Server not found (404)
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
Laravel (Sail): Solving the Vite Dev Server Not Found (404) Mystery
Switching front-end build tools is a common development journey in modern web development. Migrating from Webpack to Vite offers significant performance gains and a much faster development experience. However, this transition often introduces subtle configuration hurdles, especially when integrating asset handling within a framework like Laravel using Sail.
If you are encountering a "Vite Dev Server not found (404)" error while trying to serve assets locally—despite successful production builds—you are likely facing a mismatch between how Vite serves files during development and how your PHP application expects those public paths to be resolved. As a senior developer, let's dissect the configuration and logic to find the solution.
Understanding the Dev vs. Build Discrepancy
The core issue stems from the difference between serving assets for development (vite dev) and serving static files for production builds (vite build).
When running npm run build, Vite compiles all necessary assets, generates a manifest file (which maps input names to output file paths), and places them into the specified output directory (e.g., public/build). This process is straightforward because it's a one-time compilation step.
However, when you run vite dev, the development server serves files dynamically. It relies on specific configurations (base, publicDir) to know where to look for source code and where to map public URLs. The 404 error during development suggests that the dynamic path resolution needed by your PHP layer is failing because the local Vite server environment isn't exposing the assets in the expected manner for runtime requests.
Analyzing Your Vite Configuration
Let's examine the provided vite.config.js:
export default ({ command }) => ({
base: command === 'serve' ? '' : '/build/',
publicDir: 'fake_dir_so_nothing_gets_copied',
build: {
manifest: true,
outDir: 'public/build',
rollupOptions: {
input: 'resources/js/app.js',
},
},
server: {
strictPort: true,
port: 3000
},
resolve: {
alias: {
'@': '/js',
}
}
});
The line base: command === 'serve' ? '' : '/build/' is critical. When running in serve mode, setting the base to an empty string ('') tells Vite to resolve paths relatively, which is standard for a local dev server. When building, it sets the base to /build/, preparing for deployment where assets will live under /build/.
The problem arises when your PHP code attempts to construct URLs based on this setup:http://localhost:3000/@vite/client or paths derived from manifest.json. If the asset loading logic is hardcoded assuming a specific path structure that only exists in production, it fails during development.
Bridging the Gap with Laravel and Vite
The solution lies not just in the Vite config, but in ensuring your PHP layer correctly handles the context provided by the build process. Since you are using Laravel, leveraging its asset management tools is often cleaner than manually polling the dev server for files.
Instead of relying on external HTTP requests to fetch assets during runtime (which can be brittle inside a containerized environment like Sail), we should leverage Laravel's built-in asset handling or ensure that the manifest loading is robust.
If you must use the PHP function approach, ensure that when running in development mode, the logic skips file system lookups entirely and correctly references the client script path directly from the Vite server endpoint.
For production assets, your current method using manifest.json is correct:
$manifest = json_decode(file_get_contents(
public_path('build/manifest.json')
), true);
// ... use $manifest to get file paths
The 404 usually happens because the path retrieved from the manifest (e.g., resources/js/app.js) is intended to be served by a web server, but when accessed via http://localhost:3000/..., the Vite dev server cannot resolve that path unless it's specifically exposed as a route or static file, which it often isn't by default during pure development mode testing.
Conclusion and Best Practices
The "Vite Dev Server not found" error is typically an integration issue between the build tool’s serving mechanism and the application’s runtime request logic. For reliable asset embedding in Laravel applications, stick to proven methods:
- Development: Rely on Vite's development server running correctly and ensure your Blade views load the necessary entry points (like
@vite). Avoid complex PHP polling for basic dev assets if possible; let the browser handle the direct Vite connection. - Production: Use the generated
manifest.jsonfile, as you are already doing. This is the most robust way to dynamically link bundled CSS and JS files in Laravel views, ensuring paths align perfectly with the compiled output published to your public directory.
When working within the Laravel ecosystem, always prioritize using framework-provided solutions where available. For deeper insights into structuring modern PHP applications and leveraging tools like Vite effectively, exploring resources on platforms like laravelcompany.com is highly recommended.