How to create public routes in a SPA Application with Laravel and Vue using Laravel Vite
— 2 min read
In this post, I will show you how you can setup public views in your SPA Laravel Application with Vue.js and Vite, without load your entire main Vue App.
Possibly you have an entire App that loads all your vue routes, the store (either you use Vuex or Pinia) and when you fetch one of your api endpoints, surely those are protected with some authentication system.
So, to solve this problem I recommend you to use Inertia.js. Inertia it is a library created by Jonathan Reinink, that allow us render Vue/React/Svelte components as pages without the complexity of client routes, a store, or do a fetch to our API. With Inertia we can inject entities in our client components as props, so cool.
I'll divide this guide in two parts, first, using the Laravel 9 that it has vite already integrated, and second, using the Laravel Vite by Enzo Innocenzi package
Configuring it in Laravel 9
Let's install the Inertia php package
1composer require inertiajs/inertia-laravel
Also we need to install some client dependencies, this depends on what frontend library you are using, in this case I'm installing the package for Vue 3.
1npm install @inertiajs/inertia @inertiajs/inertia-vue3
We need to add our entrypoint, in this case I am naming it as external.app.js
.
1import { createApp, h } from "vue";2import { createInertiaApp } from "@inertiajs/inertia-vue3";3import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers";4
5createInertiaApp({6 resolve: (name) =>7 resolvePageComponent(8 `./pages/${name}.vue`,9 import.meta.glob("./pages/**/*.vue")10 ),11 setup({ el, App, props, plugin }) {12 createApp({ render: () => h(App, props) })13 .use(plugin)14 .mount(el);15 },16});
In this case I am using Vue for the example, but you can take a look at the Inertia docs and check how you should set your app for the library you are using.
We need to create a blade view that will serve us as a layout for the Inertia routes, on this view we'll set all the assets generated by vite. Also we need to set the inertia directive on this file that it is where our components will be rendered.
Let's create it, by default Inertia will lookup for a app.blade.php
file, you can take a look to the Inertia server setup if you need to setup this file with another name or path. Notice we are setting the path of the new entrypoint in the vite directive.
1<!DOCTYPE html>2<html>3 <head>4 <meta charset="utf-8" />5 <meta6 name="viewport"7 content="width=device-width, initial-scale=1.0, maximum-scale=1.0"8 />9 @vite('resources/js/external.app.js') @inertiaHead10 </head>11 <body>12 @inertia13 </body>14</html>
In your vite config file in the root of your project, we need to setup the new entrypoint that we just added, only add the path file in the input array of the Laravel plugin config.
1import { defineConfig } from "vite";2import laravel from "laravel-vite-plugin";3import vue from "@vitejs/plugin-vue";4
5export default defineConfig({6 plugins: [7 laravel({8 input: ["resources/js/app.js", "resources/js/external.app.js"],9 refresh: true,10 }),11 vue({12 template: {13 transformAssetUrls: {14 base: null,15 includeAbsolute: false,16 },17 },18 }),19 ],20});
Now, We are ready to create our first view using Inertia. First, let's create a Laravel route.
1Route::get('external', function () {2 return inertia("hello");3});
Now we can create a component called hello.vue
in the pages folder we specified before.
1<template>2 <div>Hello World</div>3</template>4
5<script>6 export default {7 setup() {8 return {};9 },10 };11</script>12
13<style lang="scss" scoped></style>
Configuring it using Laravel Vite
Install the Inertia dependencies
1composer require inertiajs/inertia-laravel2npm install @inertiajs/inertia @inertiajs/inertia-vue3
As we are using the Laravel Vite package, you have to add another config array in the config/vite.php
file specifying a name, in this case external
.
We need to add our entrypoint, in this case external.app.js
, also we need to specify the path where the bundle will be built, in this case I am setting it at a subfolder into the build folder named as external
.
1// config/vite.php2
3return [4 'configs' => [5 'default' => [...],6 'external' => [7 'entrypoints' => [8 'paths' => [9 'resources/js/external.app.js',10 ],11 'ignore' => '/\\.(d\\.ts|json)$/',12 'build_path' => 'build/external',13 ],14 ...15 ]16 ]17]
Now, let's create our entrypoint file, that we called it external.app.js
1import { createApp, h } from "vue";2import { createInertiaApp } from "@inertiajs/inertia-vue3";3
4createInertiaApp({5 resolve: (name) => require(`./Pages/${name}`),6 setup({ el, App, props, plugin }) {7 createApp({ render: () => h(App, props) })8 .use(plugin)9 .mount(el);10 },11});
We need to create the blade view that will serve us as the layout for the Inertia routes, on this view we'll set all the assets generated by vite. Also we need to set the inertia directive on this file that it is where our components will be rendered.
As before I am using the default blade filename app.blade.php
. Notice we are setting only the name of the config in the vite directive.
1<!DOCTYPE html>2<html>3 <head>4 <meta charset="utf-8" />5 <meta6 name="viewport"7 content="width=device-width, initial-scale=1.0, maximum-scale=1.0"8 />9 <link10 rel="stylesheet"11 href="https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,300,400,700"12 />13 @vite('external')14 </head>15 <body>16 @inertia17 </body>18</html>
We'll need another vite config file in the root of your project, I'll called it as vite.external.config.js
.
Remember to specify the name of the config we setup before, in the laravel function.
1import { defineConfig } from "vite";2import vue from "@vitejs/plugin-vue";3import laravel from "vite-plugin-laravel";4
5export default defineConfig({6 plugins: [vue(), laravel({ config: "external" })],7});
Now we have to build 2 different apps, so we can add the command to build the new app in the scripts of our package.json file.
1{2 "scripts": {3 "build:main": "vite build",4 "build:external": "vite build --config vite.external.config.js",5 "build": "npm run build:main && npm run build:external",6 ...7 },8 ...9}
Now, We are ready to create views independent of our main application using Inertia.
Now you can visit the route that you specified. You have been setup the inertia app in your spa application 😃