Views path

Update resource_path().

<?php
return [
'paths' => [
- resource_path('views'),
+ resource_path(),
],
];

Livewire

<?php
return [
- 'view_path' => resource_path('views/livewire'),
+ 'view_path' => resource_path('livewire'),
];

Laravel Vite config

Add new View namespace.

class AppServiceProvider extends ServiceProvider
{
public function boot()
{
// ...
+ View::addNamespace('new-app', resource_path('new-app'));
}
}

Blade templates

Update main template

<!DOCTYPE html>
<html>
<head>
@isset($vite)
{{ $vite }}
@else
@vite('views', 'app.ts', 3100)
@endisset
</head>

Create multiple layouts

php artisan make:component Layout/Views
php artisan make:component Layout/NewApp
<x-app>
<x-slot name="vite">
@vite('views', 'app.ts', 3100)
</x-slot>
{{ $slot }}
</x-app>
<x-app>
<x-slot name="vite">
@vite('new-app', 'app.ts', 3200)
</x-slot>
{{ $slot }}
</x-app>

Import layout in each app

With views app.

<x-layouts.views>
<div>Welcome</div>
</x-layouts.views>

With new-app app.

mkdir resources/new-app
mkdir resources/new-app/pages
touch resources/new-app/pages/index.blade.php
<x-layouts.new-app>
<div>Welcome</div>
</x-layouts.new-app>

Routes

Create route to serve page.

<?php
namespace App\Http\Controllers;
class MainController extends Controller
{
public function index()
{
return view('views.pages.index');
}
public function newApp()
{
return view('new-app.pages.index');
}
}
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', [MainController::class, 'index'])->name('welcome');
Route::get('/new-app', [MainController::class, 'newApp'])->name('new-app');

Vite configurations

Into each app

Create two Vite configuration for each application: resources/views/vite.config.ts and resources/new-app/vite.config.ts.

APPNAME
import path from 'path'
import { defineConfig } from 'vite'
import { baseConfig, bladePlugin } from '../../vite.config'
// https://vitejs.dev/config/
export default defineConfig({
...baseConfig(path.basename(__dirname)),
resolve: {
alias: {
'~/APPNAME': `${__dirname}`,
},
},
plugins: [bladePlugin()],
})

Global configuration at root

import type { PluginOption, UserConfigExport } from 'vite'
import Dotenv from 'dotenv'
Dotenv.config()
// https://vitejs.dev/config/
export const baseConfig = (entry: string): UserConfigExport => {
return {
server: {
hmr: {
host: process.env.VITE_DEV_SERVER_HOST,
},
},
base: '',
root: `resources/${entry}`,
publicDir: `${entry}/static`,
build: {
outDir: `../../public/assets/dist/${entry}`,
emptyOutDir: true,
manifest: true,
rollupOptions: {
input: '/app.ts',
},
},
cacheDir: `../../node_modules/.vite/${entry}`,
}
}
/**
* Enable full reload for blade file
*/
export const bladePlugin = (): PluginOption => ({
name: 'vite:laravel',
handleHotUpdate({ file, server }) {
if (file.endsWith('.blade.php')) {
server.ws.send({
type: 'full-reload',
path: '*',
})
}
},
})

tsconfig.json paths

Add new paths to tsconfig.json

{
"compilerOptions": {
"paths": {
"~/views": ["resources/views"],
"~/views/*": ["resources/views/*"],
"~/new-app": ["resources/new-app"],
"~/new-app/*": ["resources/new-app/*"]
}
}
}

Update package.json scripts

pnpm add npm-run-all -D
{
"scripts": {
"dev": "run-p dev:*",
"build": "run-p build:*",
"dev:views": "vite --config resources/views/vite.config.ts --port 3100 --host",
"build:views": "vite build --config resources/views/vite.config.ts",
"dev:newapp": "vite --config resources/new-app/vite.config.ts --port 3200 --host",
"build:newapp": "vite build --config resources/new-app/vite.config.ts"
}
}

TypeScript

If you use TypeScript with Alpine JS or not, you have to move ts files.

mv resources/app.ts resources/views/app.ts
mv resources/global.d.ts resources/views/global.d.ts
mv resources/ts resources/views/ts
mv resources/app.css resources/views/app.css
touch resources/new-app/app.ts
touch resources/new-app/global.d.ts
mkdir resources/new-app/ts
import './app.css'
// you can import Alpine JS here.