-
Versions:
Description:I want to migrate my project from Laravel 8 to the latest version using it with Vite but I am having an issue migrating all the features I did have previously. Currently I am using the Laravel Mix Glob extension on Laravel 8 which gives me the ability to split my CSS & JS files for every of my website pages. For the project's front-end I am not using a JS framework like Vue or React. Steps To Reproduce:You have to install Laravel 8 or older version in order to reproduce this.
const mix = require('laravel-mix');
const MixGlob = require('laravel-mix-glob');
const mixGlob = new MixGlob({ mix });
mixGlob.sass('resources/sass/pages/*.scss', 'public/css', null, {
outputDir: 'resources/sass/',
})
.js('resources/js/pages/*.js', 'public/js', null, {
outputDir: 'resources/js/',
})
.mix('options')({
processCssUrls: false
});
mix.version();
<?php
namespace App\Http\Controllers;
class PagesController extends Controller
{
public function about()
{
$page = 'about';
return view($page, compact('page'));
}
public function contacts()
{
$page = 'contacts';
return view($page, compact('page'));
}
public function home()
{
$page = 'home';
return view($page, compact('page'));
}
}
<?php
use App\Http\Controllers\PagesController;
Route::get('/', [PagesController::class, 'home'])->name('home');
Route::get('/about', [PagesController::class, 'about'])->name('about');
Route::get('/contacts', [PagesController::class, 'contacts'])->name('contacts');
<link rel="stylesheet" href="{{ asset('css/' . $page . '.css') }}">
<script src="{{ asset('js/' . $page . '.js') }}"></script>
When you visit your Question:Is there a way to achieve the same thing with Laravel running on Vite already? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 4 replies
-
Yes you can. Both Vite input and output are handled by rollupOptions section but laravel-vite helps you with input options Assuming you have this assets structure
you can create entries from pattern like it described here
Install glob package and change npm i -D glob // vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import glob from 'glob';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const input = Object.fromEntries(
glob.sync('resources/js/pages/**/*.js').map(file => [
// This remove `resources/js/pages/` as well as the file extension from each file, so e.g.
// resources/js/pages/nested/foo.js becomes nested/foo
path.relative('resources/js/pages', file.slice(0, file.length - path.extname(file).length)),
fileURLToPath(new URL(file, import.meta.url))
])
);
export default defineConfig({
plugins: [
laravel({
input,
refresh: true,
}),
],
}); You can make same thing for all style entries (css, sass files) but I prefer to import file within appropriate JS entrypoint // home.js
import '../../sass/pages/home.scss'
// you may create an [alias](https://vitejs.dev/config/shared-options.html#resolve-alias) if you wish
// import '@sass/pages/home.scss' Nest step - output. But it's optional - I'll explain later import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import glob from 'glob';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const input = Object.fromEntries(
glob.sync('resources/js/pages/**/*.js').map(file => [
path.relative('resources/js/pages', file.slice(0, file.length - path.extname(file).length)),
fileURLToPath(new URL(file, import.meta.url))
])
);
export default defineConfig({
resolve: {
alias: {
'@sass': 'resources/sass'
}
},
build: {
rollupOptions: {
output: {
assetFileNames: (assetInfo) => {
// Get file extension
// TS shows asset name can be undefined so I'll check it and create directory named `compiled` just to be safe
let extension = assetInfo.name?.split('.').at(1) ?? 'compiled'
// This is optional but may be useful (I use it a lot)
// All images (png, jpg, etc) will be compiled within `images` directory,
// all svg files within `icons` directory
// if (/png|jpe?g|gif|tiff|bmp|ico/i.test(extension)) {
// extension = 'images'
// }
// if (/svg/i.test(extension)) {
// extension = 'icons'
// }
// Basically this is CSS output (in your case)
return `${extension}/[name].[hash][extname]`
},
chunkFileNames: 'js/chunks/[name].[hash].js', // all chunks output path
entryFileNames: 'js/[name].[hash].js' // all entrypoints output path
}
}
},
plugins: [
laravel({
input,
refresh: true,
}),
],
}); This will create exact output you need within The only part left is to load required assets on required page (home assets on home page, etc). And this is the beauty of Route::get('/', function () {
// No need to specify CSS file
// as it was imported within `home.js` file
// and will be loaded as its dependency (check compiled `manifest.json` file)
$entries = 'resources/js/pages/home.js';
return view('welcome', compact('entries'));
});
Route::get('/about', function () {
$entries = 'resources/js/pages/about.js';
return view('welcome', compact('entries'));
}); Add @vite($entries) That's it On <link rel="preload" as="style" href="http://127.0.0.1:8000/build/css/home.37409bf5.css" />
<link rel="modulepreload" href="http://127.0.0.1:8000/build/js/home.4a8a2fc6.js" />
<link rel="stylesheet" href="http://127.0.0.1:8000/build/css/home.37409bf5.css" />
<script type="module" src="http://127.0.0.1:8000/build/js/home.4a8a2fc6.js"></script> and on <link rel="preload" as="style" href="http://127.0.0.1:8000/build/css/about.76cb1bb6.css" />
<link rel="modulepreload" href="http://127.0.0.1:8000/build/js/about.ae540380.js" />
<link rel="stylesheet" href="http://127.0.0.1:8000/build/css/about.76cb1bb6.css" />
<script type="module" src="http://127.0.0.1:8000/build/js/about.ae540380.js"></script> |
Beta Was this translation helpful? Give feedback.
-
Tested and it works perfectly with your code examples. Thank you! |
Beta Was this translation helpful? Give feedback.
Yes you can. Both Vite input and output are handled by rollupOptions section but laravel-vite helps you with input options
Assuming you have this assets structure
you can create entries from pattern like it described here