Vite + Laravel: The Modern Asset Pipeline You Should Being Using

Vite replaced Mix in Laravel 9+ and it's dramatically faster. Learn hot module replacement, asset versioning, multi-page setups, and the @vite directive.

SE

SenpaiDev

Author

| | 4 min read | 2 |
Original article Updated Apr 27, 2026 Editorial standards

If you started with Laravel before version 9, you likely used Laravel Mix. Vite replaced it and the difference in development speed is staggering. Here's everything you need to know to get the most out of the new asset pipeline.

Why Vite Over Mix?

Mix used Webpack under the hood, which bundles everything before serving it. Vite takes a fundamentally different approach: it serves source files directly via native ES modules during development and only bundles for production. The result is a dev server that starts in under a second and Hot Module Replacement (HMR) that reflects changes in under 50ms — compared to 2-5 seconds with Webpack.

The @vite Directive

Laravel's @vite Blade directive is your entry point. It handles both development (injecting Vite's dev server URL) and production (injecting versioned asset hashes):

<!-- In your layout -->
@vite(['resources/css/app.css', 'resources/js/app.js'])

In development, this injects the Vite client and your files via the dev server. In production after npm run build, it references the hashed filenames in public/build/manifest.json. You get cache-busting for free without configuration.

Hot Module Replacement with Livewire

Vite's HMR works seamlessly with Livewire. When you change a CSS file or a JavaScript module, the change appears in the browser instantly without a full page reload. For Livewire components, configure the Livewire Vite plugin to also trigger HMR when Blade files change:

// vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.js'],
            refresh: [
                'resources/views/**',   // Blade files
                'app/Livewire/**',       // Livewire components
                'app/Http/Controllers/**',
            ],
        }),
    ],
});

Handling Multiple Entry Points

For applications with different layouts (admin panel, public site, tools), define multiple entry points:

laravel({
    input: [
        'resources/css/app.css',
        'resources/css/tools.css',
        'resources/js/app.js',
        'resources/js/tools.js',
    ],
})

Then use the @vite directive with the appropriate files in each layout:

{{-- Public layout --}}
@vite(['resources/css/app.css', 'resources/js/app.js'])

{{-- Tools layout --}}
@vite(['resources/css/tools.css', 'resources/js/tools.js'])

Environment Variables in JavaScript

Vite exposes environment variables prefixed with VITE_ to your JavaScript code. Set them in .env:

VITE_APP_NAME="SenpaiDev"
VITE_API_BASE_URL="https://api.senpaidev.com"

Access them in JavaScript with import.meta.env.VITE_APP_NAME. Never expose secrets this way — Vite bakes these values into the built JavaScript, making them visible in the browser.

Production Build Optimisation

Run npm run build to generate optimised assets in public/build/. Vite automatically code-splits dynamic imports, tree-shakes unused code, and minifies CSS and JavaScript. Add public/build/ to your deployment process and it just works — the manifest file tells Laravel exactly which hashed filename to use for each asset.

The migration from Mix to Vite takes about 30 minutes for a typical project. The developer experience improvement — instant startup, near-instant HMR — makes it one of the most impactful upgrades you can make to your workflow.

Laravel field notes

How To Apply This In A Real Laravel App

Use the article as a starting point, then validate the idea against the shape of your application. In Laravel projects, the safest pattern is to make the first version small, measurable, and easy to remove if the tradeoff is wrong.

Implementation approach

Start with one route, one controller or action, and one test that proves the expected behavior. Once the path is stable, extract shared code into a service class or action only if a second caller needs it.

For production work, keep config in environment variables, cache expensive reads, and add clear failure states. A feature that works locally but fails silently in a queue, scheduler, or cached config environment is not ready for users.

Review Checklist

  • Add a feature or regression test before changing shared behavior.
  • Run the route through production-like cache settings with config and route caching enabled.
  • Check authorization, validation, and error responses before exposing the feature publicly.
  • Document any non-obvious tradeoff in the code or article notes so future edits stay honest.
SE

Written by

SenpaiDev

Developer and publisher at SenpaiDev, writing practical notes on Laravel, PHP, browser tools, and shipping better web products.

Comments (0)

Join the conversation

Log in to comment

No comments yet. Be the first to share your thoughts!

Newsletter

Get useful digital tips in your inbox

Get practical guides on files, privacy, productivity, writing, online tools, and web work. No spam, no daily blasts, just useful updates.

No spam, unsubscribe anytime. We respect your privacy.