Introduction
Vite is a modern frontend build tool that provides an extremely fast development environment and bundles your code for production. When building applications with Laravel, you will typically use Vite to bundle your application's CSS and JavaScript files into production ready assets.
Laravel integrates seamlessly with Vite by providing an official plugin and Blade directive to load your assets for development and production.
Note: Are you running Laravel Mix? Vite has replaced Laravel Mix in new Laravel installations. For Mix documentation, please visit the Laravel Mix website. If you would like to switch to Vite, please see our migration guide.
Choosing Between Vite And Laravel Mix
Before transitioning to Vite, new Laravel applications utilized Mix, which is powered by webpack, when bundling assets. Vite focuses on providing a faster and more productive experience when building rich JavaScript applications. If you are developing a Single Page Application (SPA), including those developed with tools like Inertia, Vite will be the perfect fit.
Vite also works well with traditional server-side rendered applications with JavaScript "sprinkles", including those using Livewire. However, it lacks some features that Laravel Mix supports, such as the ability to copy arbitrary assets into the build that are not referenced directly in your JavaScript application.
Migrating Back To Mix
Have you started a new Laravel application using our Vite scaffolding but need to move back to Laravel Mix and webpack? No problem. Please consult our official guide on migrating from Vite to Mix.
Installation & Setup
Note: The following documentation discusses how to manually install and configure the Laravel Vite plugin. However, Laravel's starter kits already include all of this scaffolding and are the fastest way to get started with Laravel and Vite.
Installing Node
You must ensure that Node.js (16+) and NPM are installed before running Vite and the Laravel plugin:
node -v
npm -v
You can easily install the latest version of Node and NPM using simple graphical installers from the official Node website. Or, if you are using Laravel Sail, you may invoke Node and NPM through Sail:
./vendor/bin/sail node -v
./vendor/bin/sail npm -v
Installing Vite And The Laravel Plugin
Within a fresh installation of Laravel, you will find a
package.json
file in the root of your application's
directory structure. The default package.json
file already
includes everything you need to get started using Vite and the Laravel
plugin. You may install your application's frontend dependencies via
NPM:
npm install
Configuring Vite
Vite is configured via a vite.config.js
file in the root
of your project. You are free to customize this file based on your
needs, and you may also install any other plugins your application
requires, such as @vitejs/plugin-vue
or
@vitejs/plugin-react
.
The Laravel Vite plugin requires you to specify the entry points for your application. These may be JavaScript or CSS files, and include preprocessed languages such as TypeScript, JSX, TSX, and Sass.
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel([
'resources/css/app.css',
'resources/js/app.js',
]),
],
});
If you are building an SPA, including applications built using Inertia, Vite works best without CSS entry points:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel([
'resources/css/app.css', // [tl! remove]
'resources/js/app.js',
]),
],
});
Instead, you should import your CSS via JavaScript. Typically, this
would be done in your application's resources/js/app.js
file:
import './bootstrap';
import '../css/app.css'; // [tl! add]
The Laravel plugin also supports multiple entry points and advanced configuration options such as SSR entry points.
Working With A Secure Development Server
If your development web server is running on HTTPS, including Valet's
secure command, you may run into
issues connecting to the Vite development server. You may configure Vite
to also run on HTTPS by adding the following to your
vite.config.js
configuration file:
export default defineConfig({
// ...
server: { // [tl! add]
https: true, // [tl! add]
host: 'localhost', // [tl! add]
}, // [tl! add]
});
You will also need to accept the certificate warning for Vite's
development server in your browser by following the "Local" link in your
console when running the npm run dev
command.
Loading Your Scripts And Styles
With your Vite entry points configured, you only need reference them
in a @vite()
Blade directive that you add to the
<head>
of your application's root template:
<!doctype html>
<head>
{{-- ... --}}
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
If you're importing your CSS via JavaScript, you only need to include the JavaScript entry point:
<!doctype html>
<head>
{{-- ... --}}
@vite('resources/js/app.js')
</head>
The @vite
directive will automatically detect the Vite
development server and inject the Vite client to enable Hot Module
Replacement. In build mode, the directive will load your compiled and
versioned assets, including any imported CSS.
Running Vite
There are two ways you can run Vite. You may run the development
server via the dev
command, which is useful while
developing locally. The development server will automatically detect
changes to your files and instantly reflect them in any open browser
windows.
Or, running the build
command will version and bundle
your application's assets and get them ready for you to deploy to
production:
# Run the Vite development server...
npm run dev
# Build and version the assets for production...
npm run build
Working With JavaScript
Aliases
By default, The Laravel plugin provides a common alias to help you hit the ground running and conveniently import your application's assets:
{
'@' => '/resources/js'
}
You may overwrite the '@'
alias by adding your own to
the vite.config.js
configuration file:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel(['resources/ts/app.tsx']),
],
resolve: {
alias: {
'@': '/resources/ts',
},
},
});
Vue
There are a few additional options you will need to include in the
vite.config.js
configuration file when using the Vue plugin
with the Laravel plugin:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
laravel(['resources/js/app.js']),
vue({
template: {
transformAssetUrls: {
// The Vue plugin will re-write asset URLs, when referenced
// in Single File Components, to point to the Laravel web
// server. Setting this to `null` allows the Laravel plugin
// to instead re-write asset URLs to point to the Vite
// server instead.
base: null,
// The Vue plugin will parse absolute URLs and treat them
// as absolute paths to files on disk. Setting this to
// `false` will leave absolute URLs un-touched so they can
// reference assets in the public directly as expected.
includeAbsolute: false,
},
},
}),
],
});
Note: Laravel's starter kits already include the proper Laravel, Vue, and Vite configuration. Check out Laravel Breeze for the fastest way to get started with Laravel, Vue, and Vite.
React
When using Vite with React, you will need to ensure that any files
containing JSX have a .jsx
or .tsx
extension,
remembering to update your entry point, if required, as shown above. You will also need to include
the additional @viteReactRefresh
Blade directive alongside
your existing @vite
directive.
@viteReactRefresh
@vite('resources/js/app.jsx')
The @viteReactRefresh
directive must be called before
the @vite
directive.
Note: Laravel's starter kits already include the proper Laravel, React, and Vite configuration. Check out Laravel Breeze for the fastest way to get started with Laravel, React, and Vite.
Inertia
The Laravel Vite plugin provides a convenient
resolvePageComponent
function to help you resolve your
Inertia page components. Below is an example of the helper in use with
Vue 3; however, you may also utilize the function in other frameworks
such as React:
import { createApp, h } from 'vue';
import { createInertiaApp } from '@inertiajs/inertia-vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
createInertiaApp({
resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
setup({ el, App, props, plugin }) {
createApp({ render: () => h(App, props) })
.use(plugin)
.mount(el)
},
});
Note: Laravel's starter kits already include the proper Laravel, Inertia, and Vite configuration. Check out Laravel Breeze for the fastest way to get started with Laravel, Inertia, and Vite.
URL Processing
When using Vite and referencing assets in your application's HTML, CSS, or JS, there are a couple of things to consider. First, if you reference assets with an absolute path, Vite will not include the asset in the build; therefore, you should ensure that the asset is available in your public directory.
When referencing relative asset paths, you should remember that the paths are relative to the file where they are referenced. Any assets referenced via a relative path will be re-written, versioned, and bundled by Vite.
Consider the following project structure:
public/
taylor.png
resources/
js/
Pages/
Welcome.vue
images/
abigail.png
The following example demonstrates how Vite will treat relative and absolute URLs:
<!-- This asset is not handled by Vite and will not be included in the build -->
<img src="/taylor.png">
<!-- This asset will be re-written, versioned, and bundled by Vite -->
<img src="../../images/abigail.png">
Working With Stylesheets
You can learn more about Vite's CSS support within the Vite
documentation. If you are using PostCSS plugins such as Tailwind, you may create a
postcss.config.js
file in the root of your project and Vite
will automatically apply it:
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
Working With Blade & Routes
When your application is built using traditional server-side
rendering with Blade, Vite can improve your development workflow by
automatically refreshing the browser when you make changes to view files
in your application. To get started, you can simply specify the
refresh
option as true
.
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
// ...
refresh: true,
}),
],
});
When the refresh
option is true
, saving
files in resources/views/**
,
app/View/Components/**
, and routes/**
will
trigger the browser to perform a full page refresh while you are running
npm run dev
.
Watching the routes/**
directory is useful if you are
utilizing Ziggy to
generate route links within your application's frontend.
If these default paths do not suit your needs, you can specify your own list of paths to watch:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
// ...
refresh: ['resources/views/**'],
}),
],
});
Under the hood, the Laravel Vite plugin uses the vite-plugin-full-reload
package, which offers some advanced configuration options to fine-tune
this feature's behavior. If you need this level of customization, you
may provide a config
definition:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
// ...
refresh: [{
paths: ['path/to/watch/**'],
config: { delay: 300 }
}],
}),
],
});
Custom Base URLs
If your Vite compiled assets are deployed to a domain separate from
your application, such as via a CDN, you must specify the
ASSET_URL
environment variable within your application's
.env
file:
ASSET_URL=https://cdn.example.com
After configuring the asset URL, all re-written URLs to your assets will be prefixed with the configured value:
https://cdn.example.com/build/assets/app.9dce8d17.js
Remember that absolute URLs are not re-written by Vite, so they will not be prefixed.
Environment Variables
You may inject environment variables into your JavaScript by
prefixing them with VITE_
in your application's
.env
file:
VITE_SENTRY_DSN_PUBLIC=http://example.com
You may access injected environment variables via the
import.meta.env
object:
import.meta.env.VITE_SENTRY_DSN_PUBLIC
Server-Side Rendering (SSR)
The Laravel Vite plugin makes it painless to set up server-side
rendering with Vite. To get started, create an SSR entry point at
resources/js/ssr.js
and specify the entry point by passing
a configuration option to the Laravel plugin:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
input: 'resources/js/app.js',
ssr: 'resources/js/ssr.js',
}),
],
});
To ensure you don't forget to rebuild the SSR entry point, we
recommend augmenting the "build" script in your application's
package.json
to create your SSR build:
"scripts": {
"dev": "vite",
"build": "vite build" // [tl! remove]
"build": "vite build && vite build --ssr" // [tl! add]
}
Then, to build and start the SSR server, you may run the following commands:
npm run build
node bootstrap/ssr/ssr.mjs
Note: Laravel's starter kits already include the proper Laravel, Inertia SSR, and Vite configuration. Check out Laravel Breeze for the fastest way to get started with Laravel, Inertia SSR, and Vite.
Script & Style Tag Attributes
Content Security Policy (CSP) Nonce
If you wish to include a nonce
attribute on your script and style tags as part of your Content
Security Policy, you may generate or specify a nonce using the
useCspNonce
method within a custom middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Vite;
class AddContentSecurityPolicyHeaders
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
Vite::useCspNonce();
return $next($request)->withHeaders([
'Content-Security-Policy' => "script-src 'nonce-".Vite::cspNonce()."'",
]);
}
}
After invoking the useCspNonce
method, Laravel will
automatically include the nonce
attributes on all generated
script and style tags.
If you need to specify the nonce elsewhere, including the Ziggy
@route
directive included with Laravel's starter kits, you may retrieve it using the
cspNonce
method:
@routes(nonce: Vite::cspNonce())
If you already have a nonce that you would like to instruct Laravel
to use, you may pass the nonce to the useCspNonce
method:
Vite::useCspNonce($nonce);
Subresource Integrity (SRI)
If your Vite manifest includes integrity
hashes for your
assets, Laravel will automatically add the integrity
attribute on any script and style tags it generates in order to enforce
Subresource
Integrity. By default, Vite does not include the
integrity
hash in its manifest, but you may enable it by
installing the vite-plugin-manifest-uri
NPM plugin:
npm install -D vite-plugin-manifest-sri
You may then enable this plugin in your vite.config.js
file:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import manifestSRI from 'vite-plugin-manifest-sri';// [tl! add]
export default defineConfig({
plugins: [
laravel({
// ...
}),
manifestSRI(),// [tl! add]
],
});
If required, you may also customize the manifest key where the integrity hash can be found:
use Illuminate\Support\Facades\Vite;
Vite::useIntegrityKey('custom-integrity-key');
If you would like to disable this auto-detection completely, you may
pass false
to the useIntegrityKey
method:
Vite::useIntegrityKey(false);
Arbitrary Attributes
If you need to include additional attributes on your script and style
tags, such as the data-turbo-track
attribute, you may specify them via the
useScriptTagAttributes
and
useStyleTagAttributes
methods. Typically, this methods
should be invoked from a service
provider:
use Illuminate\Support\Facades\Vite;
Vite::useScriptTagAttributes([
'data-turbo-track' => 'reload', // Specify a value for the attribute...
'async' => true, // Specify an attribute without a value...
'integrity' => false, // Exclude an attribute that would otherwise be included...
]);
Vite::useStyleTagAttributes([
'data-turbo-track' => 'reload',
]);
If you need to conditionally add attributes, you may pass a callback that will receive the asset source path, its URL, its manifest chunk, and the entire manifest:
use Illuminate\Support\Facades\Vite;
Vite::useScriptTagAttributes(fn (string $src, string $url, array|null $chunk, array|null $manifest) => [
'data-turbo-track' => $src === 'resources/js/app.js' ? 'reload' : false,
]);
Vite::useStyleTagAttributes(fn (string $src, string $url, array|null $chunk, array|null $manifest) => [
'data-turbo-track' => $chunk && $chunk['isEntry'] ? 'reload' : false,
]);
Warning!! The
$chunk
and$manifest
arguments will benull
while the Vite development server is running.