Back to Blog
Lesson 40 of the Advanced Laravel: Architecture, Scaling & Performance course
LaravelJune 28, 20264 min read

Optimizing Asset Pipelines: Versioning and CDN Caching with Vite

Master production-grade asset management in Laravel. Learn to implement file hashing for versioning and configure Vite to scale your frontend performance via CDN.

LaravelVitePerformanceAssetsDevOpsphpbackend

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.

The Problem: Why Browser Caching Breaks Deployments

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.

Implementing Asset Versioning with Vite

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.

Leveraging CDN Caching for Assets

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:

  1. Build assets locally or in CI.
  2. Sync the public/build directory to your S3 bucket.
  3. Configure your CDN to point to that bucket.
  4. Tell Laravel to prefix asset URLs with the CDN domain.

Step 1: Updating the Asset URL

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.

Step 2: The Build Process

In your CI pipeline (e.g., GitHub Actions), you should execute:

Bash
npm 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.

Comparison: Deployment Strategies

StrategyPerformanceComplexityCache Busting
Local /publicLowLowManual
CDN + HashingHighMediumAutomatic
Version Query StringMediumLowUnreliable

Hands-on Exercise

  1. Modify your vite.config.js to split your vendor dependencies into a separate chunk using the manualChunks configuration shown above.
  2. Run npm run build and inspect the public/build/assets directory. Identify the new hashed filenames.
  3. Update your .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.

Common Pitfalls

  • Missing Manifest: If you deploy your code but forget to run 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.
  • Inconsistent Build Environments: Using different versions of Node.js or Vite plugins in CI versus local development can lead to different hashes for the exact same source code. Use a docker-compose setup or nvm to lock your build environment.
  • Over-caching 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.

Similar Posts