When combined, Vue.js with Laravel form a powerful duo, seamlessly integrating front-end and back-end technologies to help developers create interactive and fast web applications. Together, they allow you to leverage the best of both worlds—Vue.js for dynamic user interfaces and Laravel for robust, scalable server-side functionality.
In this article, we’ll explore why this pairing is a game-changer, how it enhances developer productivity, and the different ways you can integrate Vue with Laravel. But before we get into the integration specifics, let’s take a look at the key benefits this combination offers.
Vue.js with Laravel
The Benefits of Pairing Vue.js with Laravel
This duo isn’t just a simple convenience—it’s a strategic match that aligns with modern development needs. Here’s why combining Vue.js with Laravel makes sense for your projects:
1. Efficient Single-Page Applications (SPAs):
Vue.js adds life to Laravel’s solid backend, transforming it into a dynamic platform for building fast, responsive SPAs. With Vue’s reactivity and virtual DOM, Laravel-powered SPAs deliver a smooth, native-like experience without the need for frequent page reloads. This combination ensures faster load times, reduced server load, and better overall performance.
2. Hot Reloading with Vite:
Both Vue.js and Laravel support the use of Vite, which provides Hot Module Replacement (HMR). This feature allows developers to see changes instantly in the browser without having to refresh the page. It’s a productivity booster for rapid development, helping you avoid delays and testing interruptions.
3. Server-Side Rendering (SSR) for SEO:
Vue.js and Laravel are a perfect match for tackling SEO challenges. By using server-side rendering with Laravel, you can ensure that search engines index your pages properly, as the server pre-renders content before sending it to the browser. Meanwhile, Vue.js enhances client-side interactivity, allowing you to get the best of both worlds—improved SEO and seamless user engagement.
4. Simplified State Management:
Managing state in complex applications can get tricky, but tools like Pinia offer a smooth experience for client-side state management in Vue.js. On the other hand, server-side state management tools like Inertia.js ensure seamless integration between the client and server, making your application more efficient and easier to manage.
5. Thriving Developer Communities:
Both Vue.js and Laravel boast large, active communities, meaning you’ll have access to a wealth of support, tutorials, and open-source packages. Whether you need help troubleshooting or are looking for the latest best practices, the combined power of these communities ensures you’re never alone in your development journey.
6. Future-Proof Technology Stack:
Both Vue.js and Laravel are constantly evolving to keep pace with emerging technologies. By using these frameworks, you ensure your applications stay modern and adaptable to future advancements, giving your projects a long-lasting edge in an ever-changing tech landscape.
Vue.js with Laravel
Choosing Between Client-Side and Server-Side Rendering
Vue.js and Laravel give you flexibility when it comes to rendering methods. Let’s dive into how Client-Side Rendering (CSR) and Server-Side Rendering (SSR) differ, and which might be best for your project.
Client-Side Rendering (CSR)
In CSR, the server primarily serves an empty HTML shell along with essential assets (CSS, JavaScript). Once the browser receives these files, it takes over the rendering process, executing JavaScript to populate the content dynamically. While this allows for dynamic, interactive SPAs, it can present challenges in SEO, as search engines may struggle to index pages properly. It could take hours or even weeks for search engines to crawl and index content.
Server-Side Rendering (SSR)
With SSR, the server pre-renders the HTML, delivering a fully populated page to the browser. This makes it easy for search engines to index content right away, resulting in faster SEO results. While Vue.js still handles dynamic client-side actions after the page loads, the initial page load is faster, and performance is typically optimized. SSR is ideal for SEO-heavy applications where quick content indexing is essential.
Method 1: Single Blade Hosting a Vue.js App
Laravel Blade Hosting Vue.js App
In this integration method, a single Laravel Blade file serves as the host for the entire Vue.js application. This API-driven approach allows both frameworks to coexist smoothly within the same project directory, with the help of the Vite plugin specifically designed for Vue.js.
While the project shares the same directory and domain, it still follows the principle of separation of concerns. This means Vue.js operates as a client-side rendered application, communicating with Laravel APIs to fetch and update data.
Additionally, Vue Router takes charge of client-side navigation, making it easy to manage the routes and enhance the user experience. If you’re new to Vue Router, consider exploring specialized courses, like the one at VueSchool, to gain in-depth knowledge and master the art of routing.
Vue.js with Laravel
Integration Guide
The first step in this integration process is to create a new Laravel project. Here’s a quick guide to getting started using Composer.
- Create a New Laravel ProjectOpen your terminal or command prompt and run the following command to create a fresh Laravel project:
composer create-project laravel/laravel example-app
The previous command installed the latest version of Laravel (currently v11.41.3). Next, we install Laravel related npm dependencies.
npm install
Now, we’re ready to invite Vue to the party.
npm install vue@next vue-router@4 @vitejs/plugin-vue
The previous command installed the latest version of Vue, Vue Router and Vite’s official plugin for Vue 3.
// package.json
"dependencies": {
"@vitejs/plugin-vue": "^4.6.0",
"vue": "^3.2.36",
"vue-router": "^4.2.5"
}
To start using Vue in Laravel, we should add Vite’s plugin for Vue to the plugins array inside vite.config.js
file. The final code will look like this:
import { defineConfig } from "vite";
import laravel from "laravel-vite-plugin";
import vue from "@vitejs/plugin-vue";
export default defineConfig({
plugins: [
vue(),
laravel({
input: ["resources/css/app.css", "resources/js/app.js"],
refresh: true,
}),
],
resolve: {
alias: {
vue: "vue/dist/vue.esm-bundler.js",
},
},
});
Head to ./resources/js
and create a new file App.vue
. This file will serve as an entry point for our Vue.js application.
<template>
<h2>
Shikshatech Rocks! 🤘
</h2>
</template>
Time to create a new Vue app instance in our Laravel project. To do so, we’ll need to modify ./resources/js/app.js
file and add the following
import "./bootstrap";
import { createApp } from "vue";
import App from "./App.vue";
createApp(App).mount("#app");
This will mount our Vue app inside an element with the id
of “app”. Let’s create that <div>
within the <body>
of ./resources/views/welcome.blade.php
file. This Blade file containing our Vue app, is the only Laravel file that will be exposed to the browser.
<body>
<div id="app"></div>
</body>
We also have to import our ./resources/js/app.js
file using the @vite() Blade directive.
<head>
@vite(['resources/js/app.js'])
</head>
<body>
<div id="app"></div>
</body>
With just that, we got Vue working with Laravel 🥳 We can test it by running npm run dev
and php artisan serve
Vue.js with Laravel
We still need to make it a dynamic single-page application. To achieve this, we will use Vue Router. Let’s create a new file ./resources/js/router.js
to define the router :
import { createRouter, createWebHistory } from "vue-router";
const routes = [];
export default createRouter({
history: createWebHistory(),
routes,
});
Next step, integrate the router we just created with our Vue instance inside ./resources/js/app.js
file
import "./bootstrap";
import router from "./router/router";
import { createApp } from "vue";
import App from "./App.vue";
createApp(App).use(router).mount("#app");
So, now we need a ./resources/js/Pages/
directory that will contain our route components. We first create ./resources/js/Pages/HomeRoute.vue
with a router-link
to test internal navigation when we’re done:
<template>
<div>
<h2>HOME</h2>
<router-link to="/test"> Take me to Test page </router-link>
</div>
</template>
Then we create ./resources/js/Pages/TestRoute.vue
<template>
<p>I'm here to test!</p>
</template>
Next, Lazy load the new route components in the router’s file ./resources/js/router.js
import { createRouter, createWebHistory } from "vue-router";
const routes = [
{
path: "/",
component: () => import("./Pages/HomeRoute.vue"),
},
{
path: "/test",
component: () => import("./Pages/TestRoute.vue"),
},
];
export default createRouter({
history: createWebHistory(),
routes,
});
It’s worth mentioning that we can use unplugin-vue-router
package to enable file based routing feature. But for this tutorial, we’ll stick with the official Vue Router approach.
Finally, we tweak the code inside the Vue entry file to make it dynamic. Luckily, Vue Router provides RouterView built-in component, which exposes slots that we can leverage to dynamically render route components.
Head to ./resources/js/App.vue
and modify it as follows:
<template>
<router-view v-slot="{ Component, route }">
<div :key="route.name">
<Component :is="Component" />
</div>
</router-view>
</template>
Now if we hit npm run dev
and php artisan serve
in the terminal, click on the link to navigate to /test
, we will find it working as expected with client-side navigation. But here’s the catch, if we do a hard refresh, Laravel will return a “404 Not Found” error. This is happening because we don’t have web routes defined in Laravel.
To overcome this challenge, we can head to ./routes/web.php
and define a single route that will catch all valid routes and use the Blade entry file which contains our Vue application.
Route::get('/{vue_capture?}', function () {
return view('welcome');
})->where('vue_capture', '[\/\w\.-]*');
With that done, hard refresh won’t ruin our application anymore. However, it’s worth mentioning that 404 pages still need to be handled using Vue Router. You can follow the instructions in the “404-not-found-page” free lesson at VueSchool to handle this scenario like a pro.
At this point, we still don’t have a communication channel between Vue’s client-side components with Laravel backend. For this, we can use axios as our promise-based HTTP client for the browser.
npm install axios
Let’s quickly craft a testing API endpoint in Laravel and consume it from a Vue component. Inside ./routes/api.php
, we will add a new API endpoint
Route::get("/test-me", function () {
return 'Hello from Laravel!';
});
We’ll then consume this new API endpoint from ./resources/js/Pages/HomeRoute.vue
component using axios
. Let’s prepare a button that will trigger getValue()
function which will fire a get request to the endpoint. I’ll also create a ref
to store the response value.
<template>
<div>
<h2>HOME</h2>
<router-link to="/test"> Take me to Test page </router-link>
<button @click.prevent="tiggerEndpoint">Trigger Endpoint</button>
<p v-if="response">{{ response.data }}</p>
</div>
</template>
Finally, we’ll use script setup
to create the function and variable ref
import axios from "axios";
import { ref } from "vue";
const response = ref();
const getValue = async () => {
try {
response.value = await axios.get("/api/test-me");
} catch (error) {
// Do something with the error
console.log(error);
}
};
When we run the app, and once the button is clicked, the getValue()
function will trigger the test-me
endpoint and the response will be displayed in the browser.
if api not working please run this command
php artisan install:api
and also include api url in /bootstrap/app.php
api: __DIR__.'/../routes/api.php',
Vue.js with Laravel