Currently the app has 2 entry points for the JS and CSS files in the blade layout file:
{{-- layout.blade.php --}}
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ $title ?? config('app.name') }}</title>
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
But, I have many other JS and CSS files inside /resources/js and /resources/css.
How am I supposed to deal with it?
Let's say I have another blade view that uses the above layout:
{{-- my_view.blade.php --}}
@extends('layouts.app')
@section('content')
@endsection
And I want to use some JS scripts and CSS files only for this page, what is the way to do it alongside Vite? Because currently the layout takes only the 2 main entry points.
What I did was to use glob to add all the css files and js files:
// app.js
import.meta.glob('../css/*.css', { eager: true });
import.meta.glob('../js/*.js', { eager: true });
But that's clearly not how I am supposed to work with Vite, because right now, every Blade view that uses this layout loads all the CSS and all the JS files
So how am I supposed to let's say, add only myscript.js and mystyle.css to my_view.blade.php while using Vite best practices?
You can specify any number of sources for the laravel-vite-plugin:
vite.config.js
export default defineConfig({
plugins: [
laravel([
'resources/css/welcome.css',
'resources/js/welcome.js',
'resources/css/app.css',
'resources/js/app.js',
'resources/css/admin.css',
'resources/js/admin.js',
]),
],
});
Finally, you use in each view only the ones you actually need.
resources/views/welcome.blade.php
<!DOCTYPE html>
<head>
{{-- ... --}}
@vite(['resources/css/welcome.css', 'resources/js/welcome.js'])
</head>
resources/views/app.blade.php
<!DOCTYPE html>
<head>
{{-- ... --}}
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
resources/views/admin.blade.php
<!DOCTYPE html>
<head>
{{-- ... --}}
@vite(['resources/css/admin.css', 'resources/js/admin.js'])
</head>
As you mentioned in the question, it's possible that you already have a separate <head>. In this case, most modern browsers will handle a secondary correctly, but you can pass variables from outside to layout.blade.php and then use them in @vite. (Reference: How to pass variable to @extends blade and Can HTML contain two HEAD tags)
resources/views/layout.blade.php
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ $title ?? config('app.name') }}</title>
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
@if(isset($sources))
@vite($sources)
@else
@vite(['resources/js/app.css', 'resources/js/app.js'])
@endif
</head>
resources/views/admin.blade.php
@extends('layout', ['sources' => ['resources/js/admin.css', 'resources/css/admin.js']])
@section('content')
<h1>Hello World</h1>
@endsection
Of course, you can also assemble the array passed to the plugin automatically. If your structure is known, you can read the file system accordingly and automatically collect the file paths.
For example, if you assume that every file in the js and css folders should be a separate source, but I ignore the subfolders, I would do something like this (when building the source, for instance, files used from the js/utils subfolder are bundled into the source by Vite, so you don't need to worry about that):
vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import fs from 'fs';
import path from 'path';
function getFilesFromDir(dir) {
return fs.readdirSync(dir)
.filter(file => {
const ext = path.extname(file);
return (!ignoreFiles.includes(file) && (exts.length === 0 || exts.includes(ext)));
})
.map(file => path.join(dir, file).replace(/\\/g, '/'));
}
const cssFiles = getFilesFromDir('resources/css', ['.css']);
const jsFiles = getFilesFromDir('resources/js', ['.js']);
export default defineConfig({
plugins: [
laravel([
...cssFiles,
...jsFiles,
]),
],
});
Note: It's just a quick illustrative example; there might be a better alternative.