
SPA development’s SEO is notoriously murky. Depending on who you ask, crawling of client-rendered content is either totally fine, fine if it’s synchronous, or not at all fine.
Because of all these conflicting opinions, I see the question “Is my Vue SPA SEO friendly?””friendly?””friendly?”” pop up in places like the Vue.js Developers Facebook group and the Vue.js Forums.
Throughout this article, we will challenge popular opinions, perform some basic tests, and conclude with a few sensible recommendations for building SEO-friendly SPAs.
Note: this article was originally posted here on the Vue.js Developers blog on 2018/04/09
The issue with client-rendered content
With a single-page app, the browser receives no meaningful content but only a page shell. JavaScript loads the content on demand from the server via AJAX and then adds it to the page using Java.
By doing this, a user can view the “pages” of an SPA site without having to refresh the page, theoretically improving the user experience.

This architecture may work for humans viewing the page in a browser, but what about search engine crawlers? Is JavaScript supported by crawlers? Does this mean they will wait until the AJAX calls have completed before crawling the page?
Knowing this is important because it could determine whether or not a search engine can index the site’s content, and just as important, how well its content is ranked.
Googlebot
Our investigation should focus on Googlebot, the Google search engine crawler, since it is the most popular search engine in the world.
Googlebot crawled only static HTML pages in the early days of the web. Googlebot began crawling in 2014, but now attempts to render JavaScript before it begins.
For helping webmasters troubleshoot JavaScript-modified pages, Google provides the Fetch As Google tool, which displays a snapshot of what Googlebot sees at a particular URL.
One common myth is that Googlebot won’t crawl asynchronous JavaScript. This article has done a great job of busting it. TLDR; Googlebot will wait at least 20 seconds for asynchronous calls to complete!
How Googlebot sees an SPA
Vue HackerNews Clone 2.0 is the quintessential example of a Vue.js SPA. The Vue team provides this open source project as a way of showing off the capabilities of Vue and effective design patterns.
This application was deployed to a Heroku instance and executed using Fetch As Google. As shown below, the screenshot on the left shows a screen shot as seen by Googlebot, while the screenshot on the right shows a screen shot as seen by a user. Their appearances are identical.

Removing server-side rendering
Server-side rendering (SSR) is a key feature of the Vue HackerNews Clone 2.0. It means that, unlike a more basic SPA, the content for each page is rendered on the server and sent to the browser when the page loads.
Ultimately, we would like to understand how Googlebot perceives client-generated content. Therefore, I turned off the SSR and repeated the test:

Googlebot was able to view the content even with client rendering only. After a few days I also checked to see if Google had indexed the app. I found that:

But wait…
It seems that this test answers any concerns about client-rendered content, but there are some reasons why you shouldn’t have complete confidence in it:
- The Googlebot engine, like all JavaScript engines, is not infallible. There may be situations where it cannot render your page.
- It doesn’t mean that a page will rank well just because it can be indexed