Yes, here are 4 ways to handle SEO with Vue (even without Node SSR)
Tags: Vue Router, Vue 3, Vuejs, Vue, Nuxtjs

That’s pretty much it for the backend, nothing more. You only need a single “view” file that takes title, meta, initialData or whatever parameters you need for SEO/SMO and that’s it.

The “window.initialData = @ json($state)” is also very important here, but not mandatory for SEO. It’s for performance/UX purposes. It’s just for you to have initial data in the frontend, to avoid an initial AJAX request to your API server.

Here’s how to use it for the /posts/:id route for example:

In a nutshell: you check if initialData exists, use it if does, or get it from the API Server if it doesn’t.

This could be done in any other lifecyle hook or method. Another way to use it could be to store the initial data in your Vuex state for example.

In most cases, the title and meta tags are the most important to render from the backend, for the rest, Google can parse and crawl your JavaScript.

Of course, SEO with classic SSR has it’s drawbacks:

You have to mirror each route were you need SEO on the backend

You have to pass “the same data” to the frontend and to APIs, sometimes if feels like duplicating stuff

But all things considered, this technique works damn well and I use it in production for a very big app. Actually carrefour.fr, a Fortune 40 company in France also uses this technique with Vue JS and Sympfony (PHP).

There are some cases where, you don’t need “dynamic” rendering from the server for each request. That’s where JAMStack come’s in.

4. JAMStack aka Static Site Generation aka Prerendering

This is my the method I love the most, but it isn’t meant for all situations.

So what is JAMStack? Well it’s a fancy word for something that existed before that we called: static websites.

When the web was created, we only did pure HTML files that always returned the same content. That’s what we refer to as “static content”.

It was a bit cumbersome, that’s when they invented “dynamic websites” which is what we previously called: server side rendering.

But! Somewhere in 2008/2009, something came out and got popular in 2011/2012: Jekyll, the Static Site Generator.

Basically it was a Ruby app, that would generate static files from route definitions and data you would give to it at build-time.

That’s what we refer to as: prerendering.

It was only static files so… It was fast. Really fast.

That meant, each time you needed to update your website with fresh content, you had to prerender the website again.

No biggie. CI/CD is your friend.

So what’s JAMStack then? JavaScript API Markup.

JAMStack is the concept of prerendering, but automated and modernized.

It’s an architecture solely based on the fact that you will prerender markup with initial data, that markup would use JavaScript to bring interaction and eventually more data from APIs (yours and/or others).

In a JAMStack architecture, you would usually use a frontend framework to prerender your static files that would then turn to an SPA.

It’s mostly based on the fact that you would rebuild pages on-the-fly anytime data changes in your APIs, through webhooks with CI/CD.

So it’s really nice, but not great for websites/webapps that have daily updates with a lot of pages.

Why? Because all pages are regenerated each time.

It’s the fastest, most SEO-friendly and “cheapest” method.

You only need your API server, a static host (Netlify, Vercel, S3, Firebase Hosting, etc…), and a CI/CD system for rebuilds which you most likely already have to handle tests or deployment.

Prerendering tools

Nuxt (yep they have an option for that): https://nuxtjs.org

Gridesome (the best for pure static IMO): https://gridsome.org

VuePress/VitePress: vuepress.vuejs.org / vitepress.vuejs.org

Poi + Static Plugin: https://poi.js.org/guide/plugin-vue-static.html

Any other SSG (static site generator) would be good but, you won’t have hydration with those not Vue-driven.

APIs: You can create your own API but, usually when you do JAMStack, it’s for content-drive websites/webapps. That’s why we often use what we call: Headless CMSs.

A headless CMS, is a CMS that can render HTTP APIs as a response.

There are many of them: Strapi, Directus (Node), WordPress (yep it can), Cockpit CMS (PHP), Contentful, Dato, Prismic (hosted)…

You can find more here: https://jamstack.org/headless-cms

Conclusion: What’s the best SEO method then?

There isn’t a silver bullet. It depends on your stack, budget, team, type of app and some other parameters.

In a nutshell, I would say:

If you don’t care a lot about it: an optimized SPA with Vue meta is fine

If you can use Node: do Node-based SSR

If you can’t use Node: do classic SSR with initial data rendering

If you don’t have daily page updates or too many pages: JAMStack

That’s it. Remember: there’s never ONLY ONE WAY to do something.

Tanks for reading.

PS: If you want some time-to-time Vue/Frontend news, signup to my newsletter: https://maisonfutari.com