Master production-grade asset management in Laravel. Learn to implement file hashing for versioning and configure Vite to scale your frontend performance via CDN.
Previously in this course, we explored Zero-Downtime Deployment Pipelines: Atomic Symlink Switching to ensure our SaaS remains available during updates. In this lesson, we shift our focus to the frontend: how we deliver those updates to the user. We will implement robust asset versioning and configure Vite to leverage CDN caching for high-traffic production environments.
In a high-traffic SaaS, you want browsers to cache your CSS and JavaScript files for as long as possible to minimize load times. However, if you deploy a bug fix and the user’s browser continues to serve the stale version of your app.js from its local cache, your application will break.
The solution is cache busting via content hashing. By appending a unique hash of the file content to the filename (e.g., app-f4a2b9.js), we force the browser to treat the file as a new resource whenever the code changes.
Laravel’s default integration with Vite handles this automatically during the build process. When you run npm run build, Vite generates a manifest.json file in your public/build directory. This manifest maps your source files to their hashed production counterparts.
To ensure this works in production, you must ensure your vite.config.js is optimized for output consistency:
JAVASCRIPT// vite.config.js import { defineConfig } from CE9178">'vite'; import laravel from CE9178">'laravel-vite-plugin'; export default defineConfig({ plugins: [ laravel({ input: [CE9178">'resources/css/app.css', CE9178">'resources/js/app.js'], refresh: true, }), ], build: { // Ensure consistent hashing across build environments rollupOptions: { output: { manualChunks: { vendor: [CE9178">'axios', CE9178">'lodash'], // Example: Split heavy libs } } } } });
When you use the @vite directive in your Blade templates, Laravel automatically reads the manifest.json and injects the correct, hashed URL.
Serving static assets directly from your web server under heavy load is an anti-pattern. Every request for an image, font, or script consumes PHP-FPM workers or web server threads that should be reserved for dynamic requests.
To optimize, we offload these to a CDN (CloudFront, Cloudflare, etc.). The strategy is simple:
public/build directory to your S3 bucket.In your .env file, define your CDN base:
ASSET_URL=https://cdn.yoursaas.com
Laravel’s asset() helper and the @vite directive will automatically prepend this URL to your generated paths.
In your CI pipeline (e.g., GitHub Actions), you should execute:
Bashnpm install npm run build # Sync to S3 aws s3 sync public/build s3://your-bucket-name/build --delete --cache-control "max-age=31536000, public"
The --cache-control flag is critical. Since your files are hashed (e.g., app-f4a2b9.js), they are immutable. You can safely set a "forever" cache (one year) on the CDN side.
| Strategy | Performance | Complexity | Cache Busting |
|---|---|---|---|
| Local /public | Low | Low | Manual |
| CDN + Hashing | High | Medium | Automatic |
| Version Query String | Medium | Low | Unreliable |
vite.config.js to split your vendor dependencies into a separate chunk using the manualChunks configuration shown above.npm run build and inspect the public/build/assets directory. Identify the new hashed filenames..env file with a mock ASSET_URL and verify that running php artisan view:clear results in your @vite directive outputting the full CDN path.npm run build or fail to sync the manifest.json to the production server, Laravel will throw a ManifestNotFoundException. Always ensure your CI pipeline fails if the build fails.docker-compose setup or nvm to lock your build environment.index.html: While you want to cache your JS/CSS forever, never cache the Blade template or the server-side entry point that links to these assets. If the server-side HTML is cached, the browser will never see the new hash.By combining consistent content hashing with aggressive CDN caching, you ensure that your high-traffic SaaS platform remains performant and bug-free during every deployment. You’ve moved from basic file serving to a production-grade asset pipeline.
Up next: We will dive into Database Query Caching Layers, exploring how to cache complex Eloquent result sets to further reduce database pressure.
Learn to implement atomic deployments using symlink switches in your CI/CD pipeline, ensuring your Laravel SaaS remains available during every release.
Read moreLearn how to use Vite to compile your frontend assets for production. Master the build process and ensure your Laravel app serves optimized, linked assets.
Optimizing Asset Pipelines
Custom Middleware Development
Database Connection Pooling
Handling Large Data Exports
Security Header Configuration
Database Sharding Concepts
Real-time Data Synchronization
Database Deadlock Prevention
Managing Third-Party API Integrations