March 13, 2018


Vue.js is a great framework for developing different kinds of web applications, however, it has a problem with SEO: the asynchronous content of an application can't be optimally crawled by search engine bots, so it could be a huge problem for your business. In this article, we will tell you about one of the easiest ways to resolve this problem and, at the same time, to improve the UX of your application. Yes, we will talk about prerendering.

Prerendering is a process to preload all elements on the page and generate the static HTML of your Single Page Application.

Advantages of prerendering

The usage of prerendering has the following benefits:

  1. SEO. Yes, finally, we can solve the problem of SEO for sites with asynchronous data: all such data will be preloaded before the crawler will index your site.
  2. Speeding up page content loading. The user can get an access to your application even before the entire JavaScript loads which significantly improves the UX of your application. No one likes to wait a long time.
  3. Cheap graceful degradation. This point follows the previous one. Now even users of old browsers or users with a disabled JS or a slow device have the access to your application. Of course, they are not able to fully interact with it but they can access important information instead of seeing an empty page.
  4. Rich Previews. All unique OpenGraph metadata are prefetched correctly now. Share your site on the Facebook and other socials, to expand target audience.

The official Vue documentation proposes to use the prerender-spa-plugin for prerendering. In common, the plugin does the following steps:

  1. It creates an instance of Phantom JS and runs the application.
  2. Takes a snapshot of the DOM.
  3. Outputs the snapshot to an HTML file in our build folder.

All right, let’s see how it works in practice.

Practice: prerendering in a Vue.js application

For demonstration, I will use the application which was created in my previous article about a single page Vue application. Get familiar with the project and start with building a simple SPA following the guide in the article, or, if you want to continue right now, just clone the repo and jump to the step 4 in that guide:

$ git clone [email protected]:DChuchin/vue-spa-tutorial.git
$ cd vue-spa-tutorial
$ git checkout step-4

Now install the plugin:

npm install --save-dev prerender-spa-plugin

After that, we need to configure the plugin for the correct work. Let’s go to webpack.conf.js and add the following settings:

var path = require('path')
var PrerenderSpaPlugin = require('prerender-spa-plugin')

module.exports = {
  // ...
  plugins: [
    new PrerenderSpaPlugin(
      // Absolute path to compiled SPA
      path.join(__dirname, '.'),
      // List of routes to prerender

Here we specify a directory from which we want to get a page for prerendering. In our case, this is the root directory. Also, we should add a list of routes which we want to prerender. For demonstration purposes, I will take just first four posts.

We should also take into account that we get data asynchronously, so if we carry on building the app following this approach, we’ll get a generated HTML with no content. To address this issue, the plugin offers three next options (check the documentation for more info):

// NOTE: Unless you are relying on asynchronously rendered content,
        // such as after an Ajax request, none of these options should be
        // necessary. All synchronous scripts are already executed before
        // capturing the page content.

        // Wait until a specific event is fired on the document.
        captureAfterDocumentEvent: 'custom-post-render-event',
        // This is how you would trigger this example event:
        // document.dispatchEvent(new Event('custom-post-render-event'))

        // Wait until a specific element is detected with
        // document.querySelector.
        captureAfterElementExists: '#content',

        // Wait until a number of milliseconds has passed after scripts
        // have been executed. It's important to note that this may
        // produce unreliable results when relying on network
        // communication or other operations with highly variable timing.
        captureAfterTime: 5000,

        // NOTE: You can even combine strategies if you like. For example,
        // if you only _sometimes_ want to wait for an event to fire, you
        // can create a timeout by combining captureAfterTime with
        // captureAfterDocumentEvent. When combining strategies, page
        // content will be captured after the first triggered strategy.

That’s all, folks! Now if we build the application, we get a prerendered HTML. If you want to manage metadata, you can use one of the available plugins for Vue, for example, vue-meta. For instance, let’s add a unique title for each page. We need to install the plugin for this.

npm install vue-meta --save

Add it into main.js

import Meta from 'vue-meta'


const router = new Router({


And insert the following into src/components/Post.vue

metaInfo() {
  return {
    title: &&,

It’s enough to make the content of the application indexed and also available for users with a disabled JavaScript. Now search engines and social networks can read meta-information of our site. Also, we succeeded to reduce the load time to the FMP (first meaningful paint), the browser doesn’t wait for the full load of JavaScript but starts rendering our page as soon as HTML is loaded. As a result, a user can start receiving information from our site earlier.

When you don’t need prerendering

Using the simple plugin prerender-spa-plugin on a build step you can easily improve search engine optimization and create the better user experience of your Vue application. Unfortunately, there are few cases when using prerendering is inappropriate.

  1. User-specific content: some page’s content, e.g. user profile page content, should be shown only for a specific user. On the build step, we don’t know who exactly will open this page, so we can’t prerender it. Anyway, if we did it, we would open user’s private information to everybody.
  2. Frequently changing content: if you work on something like a chat or some online trading application or real-time game where content must be always relevant, usage of prerendering might be ineffective as it displays an old content until a client-side JS takes over with the latest data. As a potential solution, you could set your build to re-prerender every time as data changes, or often enough to be sure that content is relevant. But it might be very resource-consuming for the server. For the data that is updated even more frequently than every minute, you should avoid prerendering.
  3. A large number of routes: it is not a good idea to prerender thousands of routes as this will take a lot of time to build your application.

In these cases, the best way is to use server-side rendering which you will be told about in the future article.

Useful links

The official Vue documentation
The Prerender SPA Plugin documentation

Was this article helpful? Click to rate: 
Average: 3.8 (6 votes)

You may also like

IntroductionNowadays, websites more and more look like applications...
Table of contents Introduction Server-side Client-side Conclusion...
Introduction Hello there! This little website audit checklist will...