Create your account

Already have an account? Login here

Note: By joining, you will receive periodic emails from Coursetro. You can unsubscribe from these emails.

Create account

Vue Prerender Plugin Tutorial - Vue 2 SEO without Server Side Rendering

By Gary simon - Feb 19, 2018

Vue, along with other frontend JavaScript frameworks like Angular and React provide us with a lovely set of tools to enhance apps and websites. There's a problem they all face when SEO becomes a requirement; searh engine crawlers can't crawl the content.

A solution offered is server side rendering, where the server generates the content and serves it to the browser. The problem with this approach is that it's usually quite complex and introduces development considerations.

You can avoid this, however, if the requirements of your project are straight-forward. You can use a prerendering plugin to generate static HTML files of your app, assuming your app meets the following criteria:

  • It doesn't have a ton of routes (pages), otherwise it could take a long time for the build to process.
  • The content doesn't change frequently.
  • It doesn't have user-specific content.

These issues are all addressed in the prerender-spa-plugin that we're going to use for this tutorial.

Let's get started!

If you prefer watching a video..

Be sure to Subscribe to the Official Coursetro Youtube Channel for more videos.

Starting a New Vue Project

We are going to use the Vue CLI to start a new project using the init command based on the webpack-simple template:

> vue init webpack-simple vue-static-pre

Just hit enter on all of the prompts (and y or n based on whether you want Sass support).

Next, hop into the new project folder and install the dependencies:

> cd vue-static-pre
> npm install

Installing the Vue Prerender Plugin

While still in the console, run the following command to install the prerenderer plugin, an HTML webpack plugin, and the Vue router:

> npm install prerender-spa-plugin html-webpack-plugin --save-dev
> npm install vue-router --save

Next, open up /webpack.config.js and add the following 2 lines to the top:

var path = require('path')
var webpack = require('webpack')
var PrerenderSpaPlugin = require('prerender-spa-plugin') // Here
var HtmlWebpackPlugin = require('html-webpack-plugin') // And here

Next, on around line 10, we need to change the publicPath property to:

  output: {
    ...
    publicPath: '/',  // Right here
    ...
  },

Around line 59 in the same file, add the following:

// Find this line, around line 59:
if (process.env.NODE_ENV === 'production') {
  
    // Paste the following as another plugin. Other code removed for brevity

    new HtmlWebpackPlugin({
      template: 'index.html',
      filename: path.resolve(__dirname, 'dist/index.html')
    }),

    new PrerenderSpaPlugin(
      // Absolute path to compiled SPA
      path.resolve(__dirname, './dist'),
      // List of routes to prerender
      [ '/', '/about' ],
      {
        // Options 
      }
    ),

First, HtmlWebpackPlugin overwrites our index.html as the webpack-simple template we used to generate this project does not include it in the webpack output.

Next, PrerenderSpaPlugin is where the magic happens. We're simply telling it the location of the ./dist folder, and then providing it with a list of our routes in an array.

Next, within { }, we can add options. We'll add options to this a bit later on..

Creating Routes

Create a folder /src/router/ and a file within it index.js with the following contents:

import Vue from 'vue'
import Router from 'vue-router'
import About from '../About'
import Home from '../Home'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    },
    {
      path: '/about',
      name: 'About',
      component: About
    }
  ],
  mode: 'history'
})

This is a typical router file, so there's not much to explain here.

Create About.vue and Home.vue files in the /src/ folder.

For Home.vue paste the following contents:

<template>
  <div class="home">
    <h1>HOME</h1>
    <p>This is my lovely home page, how awesome!</p>
  </div>
</template>

For About.vue paste:

<template>
  <div class="about">
    <h1>ABOUT</h1>
    <ul>
        <li>About me point 1</li>
        <li>About me point 2</li>
        <li>About me point 3</li>
    </ul>
  </div>
</template>

Next, open up /src/main.js and make the following adjustments:

import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'  // Add this
import router from './router'       // Add this

Vue.use(VueRouter)                  // Add this

new Vue({
  el: '#app',
  router,                           // Add this
  render: h => h(App)
})

Great! We also need to modify our /src/App.vue root component template section to:

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <h1>{{ msg }}</h1>
    <p>
      <router-link to="/">Home</router-link>
      <router-link to="/about">About</router-link>
    </p>
    <router-view></router-view>
  </div>
</template>

One tiny last thing we need to do is remove line #9 from index.html as our new build injects its own script to build.js on its own:

<!-- Remove this line: -->
<script src="/dist/build.js"></script>

Adding a Title to Routes

The prerender-spa-plugin provides you with all of the possible options that you can specify. Chances are, you're going to want to at least specify a unique title for each route.

Visit the /webpack.config.js file and in the // options line, paste the following:

      {
        postProcessHtml: function (context) {
          var titles = {
            '/': 'My home page',
            '/about': 'My awesome about page'
          }
          return context.html.replace(
            /<title>[^<]*<\/title>/i,
            '<title>' + titles[context.route] + '</title>'
          )
        }
      }

Within the titles object, you simply match up the route with the value for the title tag. Simple!

Building the Vue Project

In the console or command line, run the following command:

> npm run build

Give it a little time, and it should produce a /dist folder with the static files.

To give it a quick test, hop into the /dist folder and start a simple http server:

> cd dist
> http-server

Note: If you don't have http-server installed, simply run the command: npm install -g http-server 

You can then open up a browser, head on over to http://localhost:8080 and see the app in action.

If you open up the dev inspector CTRL-SHIFT-i on Chrome, and view the HTML source, you will find that all of the HTML is present. This means search engine spiders will be able to see your content!

At this point, you would simply upload the contents of your /dist folder to a web server, and it should work.


Share this post




Say something about this awesome post!