Skip to main content

Server-Side Rendering with Vue.js

Introduction

In this tutorial, we will focus on Server-Side Rendering (SSR) with Vue.js. SSR is a popular technique for rendering a client-side single page application (SPA) on the server and then sending a fully rendered page to the client. This method improves SEO and initial load time by displaying a static snapshot of your app to users until the client-side app is fully loaded. Let's dive in!

Why Server-Side Rendering?

Before diving into the how-tos, let's understand why we need SSR. The main reasons are:

  1. Better SEO: As some search engines may not be able to see the fully rendered asynchronous content, SSR sends a fully rendered page to the client, making it more friendly to search engine crawler.
  2. Faster time-to-content: Without SSR, users will see a blank page until the JavaScript is downloaded, parsed and executed. With SSR, they will see a fully rendered page much sooner.

Prerequisites

Before we begin, you need to have a basic understanding of Vue.js and Node.js. You should also have Node.js, npm, and Vue CLI installed on your computer.

Getting Started

Setting Up the Project

Let's start by creating a new Vue project. Open your terminal and run the following command:

vue create ssr-project

When prompted, choose the default preset (babel, eslint).

Navigate into the project directory:

cd ssr-project

Install Vue Server Renderer

To render our Vue app on the server, we need to install the vue-server-renderer package. Install it by running:

npm install vue-server-renderer --save

Create an Entry File for the Server

Next, create a new file in the src folder named entry-server.js. This will be the entry point for our server-side bundle. In this file, we need to export a function that creates a new instance of our Vue app.

import { createApp } from './main'

export default context => {
return new Promise((resolve, reject) => {
const { app, router } = createApp()

router.push(context.url)

router.onReady(() => {
resolve(app)
}, reject)
})
}

Create an Entry File for the Client

Next, create entry-client.js in the src folder. This will be the entry point for our client-side bundle.

import { createApp } from './main'

const { app, router } = createApp()

router.onReady(() => {
app.$mount('#app')
})

Update Your Webpack Configuration

Vue SSR requires a bit of setup in the webpack configuration. This is because the server-side bundle needs to be created with Node.js in mind, while the client-side bundle is for the browser.

const path = require('path')
const webpack = require('webpack')
const merge = require('webpack-merge')
const nodeExternals = require('webpack-node-externals')
const baseConfig = require('./webpack.base.config.js')
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')

module.exports = merge(baseConfig, {
target: 'node',
entry: './src/entry-server.js',
output: {
filename: 'server-bundle.js',
libraryTarget: 'commonjs2'
},
externals: nodeExternals({
whitelist: /\.css$/
}),
plugins: [
new webpack.DefinePlugin({
'process.env.VUE_ENV': '"server"'
}),
new VueSSRServerPlugin()
]
})

Rendering the Application

Finally, let's create a Node.js server to render our Vue app. Create a new file named server.js in the root of your project and add the following code:

const express = require('express')
const server = express()
const { createBundleRenderer } = require('vue-server-renderer')
const template = require('fs').readFileSync('./index.template.html', 'utf-8')
const serverBundle = require('./dist/vue-ssr-server-bundle.json')
const clientManifest = require('./dist/vue-ssr-client-manifest.json')

const renderer = createBundleRenderer(serverBundle, {
runInNewContext: false,
template,
clientManifest
})

server.get('*', (req, res) => {
const context = { url: req.url }

renderer.renderToString(context, (err, html) => {
if (err) {
res.status(500).end('Internal Server Error')
return
}
res.end(html)
})
})

server.listen(8080)

Run your server with the command:

node server

You can now access your application on http://localhost:8080. Your Vue.js application is now server-rendered!

Conclusion

This was a basic introduction to Server-Side Rendering with Vue.js. There are more advanced topics to explore like code-splitting, using Vuex with SSR, and handling redirects and 404s. But for now, you have a good starting point to begin experimenting with SSR in your Vue.js applications.