As much as developers might like to ignore it, SEO is still a crucial part of any website or web app. Applications and sites that are not easily indexed by search engines or poorly optimized will end up hidden behind pages and pages of search results. Now if you, a Vue.js developer, don’t want that to happen to your project, take a look at our tips for optimizing Vue.js sites and apps for the demanding eyes of search engine spiders.
Heady Stuff
The first thing most developers think of when they think of SEO is stuffing their <head>
elements full of meta tags. So how would one do that with Vue? Enter vue-meta. (Okay, admittedly vue-meta
isn’t stable yet, it’s pretty powerful already.)
First off, install vue-meta
via Yarn or NPM.
Then, import and use it it in your Vue entrypoint:
import Vue from 'vue'; ... import Meta from 'vue-meta'; Vue.use(Meta); ...
Meta tags
Now in your components, you can add a metaInfo
property that contains the various bits you’ll want to inject into your <head>
:
<template> ... </template> <script> export default { ... metaInfo: { // Children can override the title. title: 'My Page Title', // Result: My Page Title ← My Site // If a child changes the title to "My Other Page Title", // it will become: My Other Page Title ← My Site titleTemplate: '%s ← My Site', // Define meta tags here. meta: [ {http-equiv: 'Content-Type', content: 'text/html; charset=utf-8'}, {name: 'viewport'. content: 'width=device-width, initial-scale=1'}, {name: 'description', content: 'I have things here on my site.'} ] } } </script>
Social tags
It’s also a good idea for you to include relevant social media tags for every page, especially if you expect it to be shared on social media.
metaInfo: { ... meta: [ ... // OpenGraph data (Most widely used) {property: 'og:title', content: 'My Page Title ← My Site'}, {property: 'og:site_name', content: 'My Site'}, // The list of types is available here: http://ogp.me/#types {property: 'og:type', content: 'website'}, // Should the the same as your canonical link, see below. {property: 'og:url', content: 'https://www.my-site.com/my-special-page'}, {property: 'og:image', content: 'https://www.my-site.com/my-special-image.jpg'}, // Often the same as your meta description, but not always. {property: 'og:description', content: 'I have things here on my site.'} // Twitter card {name: 'twitter:card', content: 'summary'}, {name: 'twitter:site', content: 'https://www.my-site.com/my-special-page'}, {name: 'twitter:title', content: 'My Page Title ← My Site'}, {name: 'twitter:description', content: 'I have things here on my site.'}, // Your twitter handle, if you have one. {name: 'twitter:creator', content: '@alligatorio'} {name: 'twitter:image:src', content: 'https://www.my-site.com/my-special-image.jpg'}, // Google / Schema.org markup: {itemprop: 'name', content: 'My Page Title ← My Site'}, {itemprop: 'description': 'I have things here on my site.'}, {itemprop: 'image', content: 'https://www.my-site.com/my-special-image.jpg'} ] }
Canonical link
It’s entirely possible, especially for SPAs, that the URL that a user ends up on and the URL that represents that page on the server might be slightly different, or that someone might access www.my-site.com
instead of my-site.com
or vice-versa. Just in-case, you should put a canonical link in your head to instruct search engines to consider that URL as the intended URL for this page.
metaInfo: { ... links: [ {rel: 'canonical', href: 'https://www.my-site.com/my-special-page'} ] }
Sitemaps
It’s not super important, at least for small sites, to have a sitemap, but a sitemap can be useful to indicate to search engines which pages you think are of particular relevance and importance on your site. You’ll either have to generate one somehow from your data or write it by hand, however.
An example (simple) sitemap:
sitemap.xml
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"> <url> <loc>https://www.my-site.com</loc> </url> <url> <loc>https://www.my-site.com/my-special-page</loc> </url> <url> <loc>https://www.my-site.com/my-other-special-page</loc> </url> <url> <loc>https://www.my-site.com/okay-this-one-isnt-that-special-but-it-kinda-works</loc> </url> </urlset>
You can include the sitemap in robots.txt
by adding a line such as:
robots.txt
Sitemap: https://www.my-site.com/sitemap.xml
Mobile Optimizations
Google, at least, prefers sites that are mobile-optimized.
These are issues that would give you a mobile optimization warning:
- The
viewport
meta tag isn’t set. (See above.) - The viewport width is fixed.
- The content requires horizontal scrolling.
- The font-size is too small.
- Touchable elements are too close together.
Google’s guide can give you some pointers on how to correct these issues.
You’d also get extra bonus points if your site is a PWA.
Other Issues
- You’ll take a hit in ranking if your site isn’t served over HTTPS or your HTTPS configuration is broken.
- Page speed is a significant factor these days in SEO, as several search engines are preferring sites that load in a few seconds over sites with potentially better content that are incredibly slow and bloated.
- If no one is linking to your site, it may take awhile for it to rise in search ratings. Even posting it on social media can help with that sometimes.
You can use Lighthouse to test for a wide variety of issues that might affect your search ranking.
Prerendering / SSR
Last but not least, an SPA is, by default, at an SEO disadvantage, because all URLs are handled by a single route, and crawlers will need to be able to run JavaScript to render the full page (an iffy process).
There are two methods commonly used to turn a SPA into a bunch of already-populated pages that present the data on the page before loading the SPA:
- Prerendering - The simpler of the two methods. Basically you have a browser automatically visit all the pages you want prerendered in your app during your build step, and it spits out whatever the resulting HTML is. You can pretty much drop it in to your existing build step.
- Server-Side Rendering - SSR is a much more complex process. It basically allows you to render your app on the server on-demand, but comes with a number of caveats and requires you to design your app with it in mind.
For the vast majority of sites, Prerendering is the simplest solution, but for highly dynamic sites, SSR might be preferred.
That's about it! If there's anything else you can think of that might help search engines rank your Vue.js project even higher, let us know!