Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Gabotronix's avatar

Laravel + Vue.js MPA/SPA hybrid structure suggestions and thoughts.

I thought about the following MPA - SPA hybrid, where I basically treat each page as an SPA, but still reloading pages to transit from one page to another (index.blade.php to posts.blade.php) like the habitual MPA. This methods uses laravel routing, session and auth poweful features to render a blade template wich contains a single vue.js component .

Imagine you are at the main page, you will have something like this:

@extends('layouts.master')
@section('content')
<body id="vue_root">
    <page-index data={{ json encoded data from backend }}></page-index>
</body>
@endsection

As you can see I pass a json object as a prop to vue component, this prop contains all needed data for vue to render.

When using this approach of treating each page as a component I can use vue.js single files to contain all the markup, logic (vue component methods and style) into a single file wich will make it easier for me to test and debug.

I have a single vue.js root instance where I register all page components.

However since I'm using laravel controllers as a backend for retrieving all the data along with blade views I will also have to create vue.js components and laravel blade templates, that sounds like double work to me.

What do yout think of this pattern? is it good? any ideas to improve this, should I use inline-templates instead (that way I would not need to make corresponding blade templates and vue.js page components.

0 likes
11 replies
martinbean's avatar

@Gabotronix I’m not sure what benefit this gives? You’re just making your website as reliant on JavaScript as a SPA.

Gabotronix's avatar

I see, so what pattern would you recommend me @martinbean.

Just using laravel for server rendering the views and adding the neccesary components to blade templates, since I have a single vue instance would it be possible to import components and classes only when needed?

What other structure patterns exist for easily maintaining laravel + vue.js MPAs

martinbean's avatar
Level 80

@Gabotronix A pattern for what? I don’t know what you’re building.

Building up pages that are a single Vue component in themselves just have all the drawbacks of an SPA with no upside. Either build an SPA, or build a “traditional” app where you navigate page to page, and dynamic functionality is added using multiple Vue components.

A Vue component is meant to be used for exactly that: discreet components of functionality; not building entire pages.

4 likes
phrane's avatar

Excellent discussion and blog. I'm a relative newbie getting to grips laravel+tailwindcss+vue. I'm trying to figure out how to make my laravel blog site more dynamic (i.e. fancy dropdowns, carousels, active forms etc...). Do I make my multipage site a bunch of SPA's to utilise js, or or is this perfectly possible and neat within standard blade templates. ...my rhetorical questions.

orest's avatar

@martinbean

Laracasts itself loads a new page when you click on a discussion, but the body of the discussion as well as the body of the replies seem to be dynamic ( you can edit the text, add a new reply etc on the fly, without reloading the page )

Is this considered a "not good" practice with respect to SEO ?

I'm asking because i want to make more clear, in what cases should we add a Vue component and in what cases it is better to prefer the server-side rendering.

martinbean's avatar

replies seem to be dynamic ( you can edit the text, add a new reply etc on the fly, without reloading the page )

@orest Editing posts and adding new replies are dynamic actions taken by an authenticated user. Google can’t emulate that, therefore those functions can be dynamically implemented using JavaScript without any affect on SEO.

1 like
orest's avatar

@martinbean thanks!

Could you please provide an example which shows the "bad" case of combining laravel and vue ?

Because i thought that when the data ( text in this case ) is rendered on the client-side then it is not SEO-friendly.

Basically to me the discussion section of laracasts looks like a blade view which consists of just a vue component ( or a least a big part of it is a vue component), which is as you mentioned a "bad" practice because it is somewhere in between MPA and SPA.

martinbean's avatar

@orest Yes, you shouldn’t rely on JavaScript to render content, as it’s not SEO-friendly (although Google’s getting better).

However, user interactions such as posting to a forum, aren’t an issue because Google would never “index” that interaction. Google can’t log in to Laracasts, and it can’t post replies to threads. But it can read posts, so posts should be server-rendered rather than client-rendered.

orest's avatar

@martinbean

I guess post = thread-body / reply-body

But in order to be able to edit a post, you have to also render it on the client-side which i guess this is what Jeffrey does here.

So for example, when you click on a discussion, a new page is loaded with the relevant data, such as thread body, reply body etc.

Then these data i guess are passed to a Vue component in order to be able to edit/delete without reloading the page. In addition to that, if you go to the bottom of the page, you can dynamically load new replies which are again rendered on the client-side.

Therefore, Google cannot read the content of the discussion page, is this correct ?

eugenefvdm's avatar

I am very interested in this topic. To cut to the chase, I want to know if it's possible to run Laravel web.php routing and a Vuejs router together. The majority of tutorials on the web related to Laravel and Vuejs SPAs has this single line for routing in web.php:

Route::get('/{any}', 'SinglePageController@index')->where('any', '.*');

This doesn't work for me because it takes over all routes.

To elaborate on this SPA/MPA dilemma, I will explain the rest of the architecture of my App:

  • It's a shopping cart. Vuejs is perfect for this for many reasons some mentioned below.
  • It has a back office. I'm using Laravel Nova for this. Please note, the back office in this instance is only used by the shop owner, and not shop clients / shoppers.
  • It has a shop user back office. This shop back office is for a shopper who places orders and so that they can see what is going on with their orders.

I have no interest in created an SPA for the shop user back office.

For the shopping cart front-end, Vuejs seems perfect. There are many dynamic parts of interacting with a shop, e.g. search, "add to cart", category selection, stock depletion with UI output, etc. There also is a ton of good, albeit very basic, tutorials on doing shopping carts with Vuejs. Creating this in Vue also means incredible responsiveness and speed and is a lot of fun too.

For the shop owner back office, I have decided to use Nova. The licensing fee is minimal compared to what it would take me to develop such features. It's super powerful and perfect for my shop owner's needs, and very interestingly, written using Vuejs and Laravel combined. It's sort of like an SPA but I haven't quite figured it out.

The the shop user's login and remember password and "view orders" section, I am not interested in creating an SPA. I simply don't have the time for that and everything in Laravel is already suited including Blade. That's after all what all that nice scaffolding is all about.

So am I missing the point here? Are you supposed to choose one or the other? How to fix this router problem? Please give me some direction.

2 likes

Please or to participate in this conversation.