Something missing or incorrect? This article's source is on Github.
Please feel free to open an issue or send a PR.
Table of Contents
- Introduction
- Reasons to use Vue and Laravel together
- Common gotchas when using Vue and Laravel together
- Thanks and good bye
Introduction
Recently the excellent Vue Community guide was released. A guide on all things Vue - written for the Vue community, by the Vue community.
This article's stuture will mirror exactly the layout of the Laravel section of the Vue Community guide, heading for heading.
The intent is to provide a living resource (i.e. it will be updated over time if/when necessary) that goes into far greater detail (including code samples/demos) than the guide (which is intended to be more concise and easier to digest).
Reasons to use Vue and Laravel together
Scaffolded by default
A default install of Laravel has everything you need to begin enhancing your server-rendered (Blade) templates with Vue components. No setup necessary.
After having created a Laravel project, you'll be provided with:
-
bootstrap.js
:- loads some libraries such as lodash, axios and Popper
- configures axios for CSRF
-
app.js
:- makes Vue globally available
- registers the
ExampleComponent.vue
- provides example code on how to automatically register Vue components
- initialises Vue
-
ExampleComponent.vue
:
You are of course free to customise these files to your needs such as by removing unneeded/unwanted libraries.
Laravel Mix
Laravel Mix--a fluid API on top of Webpack, also included in the box--takes much of the pain out of asset compiling for you, so you can focus on authoring your Vue components.
You simply need to run npm run watch
and then you can get straight to work on writing your Vue components!
It's not quite @vue/cli-levels of awesome but it's actually a really nice library and I do recommend it. It's also not at all tied to Laravel in any way- you can use it in any project.
Widespread community adoption
Several prominent members of the Laravel community are proponents of Vue (and its ecosystem).
This includes but is not limited to:
-
Taylor Otwell
- Founder (and Benevolent Dictator for Life) of Laravel itself
- Known user of Laravel and Vue
-
Adam Wathan
- Author of TailwindCSS
- Creator of the Advanced Vue Component Design course
- Known user of Laravel and Vue
-
Jeffrey Way
- Author of Laravel Testing Decoded
- Reoccuring speaker at Laracon
- Creator of several Laravel/Vue courses
- Known user of Laravel and Vue
This advocacy and support of Vue, as far as I can tell, extends to the Laravel community as a whole, meaning that a majority of Laravel developers will likely be more comfortable and familiar with Vue than say React or Angular.
Naturally, then, it follows that there will be:
- more resources to help you learn (guides, tutorials, articles)
- more people who have experience with Vue+Laravel (help, support, guidance)
- in general a healthy ecosystem (plugins, boilerplates, etc.)
Common gotchas when using Vue and Laravel together
Blade and Vue interpolation syntax
As you may be aware both Blade templates and Vue templates use moustache syntax (i.e. {{ message }}
) for variable interpolation, which presents a problem.
Fortunately the solution is simple - just prepend an @
to the moustache statement. This will instruct the Blade template rendering engine to ignore this statement, leaving it to be later processed by Vue.
<p>You have @{{ messageCount }} new message(s).</p>
If you need to escape several moustache statements, you may instead use the @verbatim
directive.
@verbatim
<div class="container">
<p>Welcome {{ user.name }} ({{ user.id }})!</p>
<p>Your last visit was: {{ user.lastVisit }}.</p>
</div>
@endverbatim
Passing PHP variables as Vue component props
If you ever need to pass a Blade variable as a prop into a Vue component from within a Blade template then you may be tempted to reach for json_encode
however you should instead use the @json
directive:
<user-profile :user='@json($user)' />
Laravel router and vue-router
You can absolutely use Laravel router and vue-router together without too much effort.
Perhaps you want vue-router to handle all routing; or for it to handle only some and for Laravel to handle the others; or to serve multiple SPAs using one Laravel app. All of this and more is possible.
Setting it all up
NOTE: This section presumes a relatively basic understanding of Vue, vue-router, Laravel and the command line.
The boilerplate provided by Laravel does not include vue-router but it won't be much trouble to set up.
Install vue-router
npm install vue-router --save
Create a router instance and some routes
Create resources/js/router.js
:
import Vue from "vue";
import VueRouter from "vue-router";
import PageHome from "./pages/Home";
import PageAbout from "./pages/About";
Vue.use(VueRouter);
const router = new VueRouter({
mode: "history",
routes: [
{
path: "/",
component: PageHome
},
{
path: "/about",
component: PageAbout
}
]
});
export default router;
Create a simple App component
Create resources/js/components/App.vue
:
<template>
<div>
<nav>
<ul>
<li>
<router-link to="/">Home</router-link>
</li>
<li>
<router-link to="/about">About</router-link>
</li>
</ul>
</nav>
<main>
<router-view></router-view>
</main>
</div>
</template>
Create a few page components
Create resources/js/pages/Home.vue
:
<template>
<div>Home</div>
</template>
Create resources/js/pages/About.vue
:
<template>
<div>About</div>
</template>
Configure the root Vue instance
Modify resources/js/app.js
:
import router from "./router";
import App from "./components/App";
const app = new Vue({
el: '#app',
router, // <-- register router with Vue
render: (h) => h(App) // <-- render App component
});
Configure the Laravel router
This is the important part - we need to instruct Laravel to route all requests to the index
action on the SPAController
.
Replace routes/web.php
:
<?php
Route::get('/{vue}', 'SPAController@index')->where('vue', '.*');
NOTE: Any routes registered before this catch-all will still function.
This is how we are able to handle some routes with Laravel and others with vue-router.
Create the controller and action
Create app/Http/Controllers/SPAController.php
:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class SPAController extends Controller
{
public function index()
{
return view("spa");
}
}
Create the view
Create resources/views/spa.blade.php
:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="csrf-token" content="{{ csrf_token() }}" />
<title>Laravel + Vue = ❤️</title>
<link href="{{ asset('css/app.css') }}" rel="stylesheet" />
</head>
<body>
<div id="app"></div>
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
That's it! You are now serving a Vue SPA with Laravel and vue-router is in charge of all routing (except for any routes which were defined before the catch-all, which will be handled by Laravel!).
Lack of Webpack aliases when using Laravel Mix
If you've used vue-cli then you'll probably be familiar with (and used to using) aliases such as @
and ~
.
Unfortunately this is not setup by default. Fortunately for us - there's a plugin.
Thanks and good bye
Thanks for reading and enjoy developing with Laravel and Vue.
Also, be sure to check out the new Vue Community.
Something missing or incorrect? This article's source is on Github.
Please feel free to open an issue or send a PR.
Top comments (3)
Please note that the PR that adds this to the Vue Community has not yet been merged.
The PR is now merged.
Great job!