Come hang with us on Discord and chat directly with the team!Discordtop-bar-close-icon

2024-08-28

How to Install Server Side Rendering (SSR) with Fastify on a VueJS App

tutorials
img

Are you looking to boost your VueJS app's performance and SEO? Server-Side Rendering (SSR) might be just what you need. In this guide, we'll walk you through the process of setting up SSR using Fastify for your VueJS application on CloudBlast's VPS hosting. Let's dive in!

Prerequisites

Before we begin, make sure you have:

1. A CloudBlast VPS with Node.js installed
2. Basic knowledge of VueJS and Fastify
3. SSH access to your VPS

Step 1: Set Up Your VueJS Project

First, let's create a new VueJS project or navigate to your existing one:


Create a new Vue project
vue create my-ssr-app

Navigate to your project directory
cd my-ssr-app
 

Step 2: Install Required Dependencies

Install the necessary packages for SSR with Fastify:


npm install fastify @fastify/static vue vue-server-renderer
 

Step 3: Create the Server Entry Point

Create a new file called `server.js` in your project root:


const fastify = require('fastify')({ logger: true })
const path = require('path')
const fs = require('fs')
const { createBundleRenderer } = require('vue-server-renderer')

const template = fs.readFileSync('./src/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
})

fastify.register(require('@fastify/static'), {
  root: path.join(__dirname, 'dist'),
  prefix: '/dist/'
})

fastify.get('*', (request, reply) => {
  const context = { url: request.url }

  renderer.renderToString(context, (err, html) => {
    if (err) {
      if (err.code === 404) {
        reply.code(404).send('Page not found')
      } else {
        reply.code(500).send('Internal Server Error')
      }
      return
    }
    reply.type('text/html').send(html)
  })
})

const start = async () => {
  try {
    await fastify.listen(3000, '0.0.0.0')
    fastify.log.info(`Server listening on ${fastify.server.address().port}`)
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}

start()
 

Step 4: Create an HTML Template

Create a new file called `index.template.html` in your `src` directory:


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue SSR App</title>
</head>
<body>
  <!--vue-ssr-outlet-->
</body>
</html>
 

Step 5: Modify Your Vue App for SSR

Update your `src/main.js` file to export a function that creates a new app instance:


import Vue from 'vue'
import App from './App.vue'

export function createApp() {
  const app = new Vue({
    render: h => h(App)
  })
  return { app }
}
 

Step 6: Create Server and Client Entry Files

Create `src/entry-server.js`:


import { createApp } from './main'

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

Create `src/entry-client.js`:


import { createApp } from './main'

const { app } = createApp()
app.$mount('#app')
 

Step 7: Configure Webpack for SSR

You'll need to create two Webpack configurations: one for the client and one for the server. Create a `vue.config.js` file in your project root:


const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
const nodeExternals = require('webpack-node-externals')
const merge = require('lodash.merge')

const TARGET_NODE = process.env.WEBPACK_TARGET === 'node'
const target = TARGET_NODE ? 'server' : 'client'

module.exports = {
  configureWebpack: () => ({
    entry: `./src/entry-${target}.js`,
    target: TARGET_NODE ? 'node' : 'web',
    node: TARGET_NODE ? undefined : false,
    plugins: [TARGET_NODE ? new VueSSRServerPlugin() : new VueSSRClientPlugin()],
    externals: TARGET_NODE
      ? nodeExternals({
          allowlist: /\.css$/
        })
      : undefined,
    output: {
      libraryTarget: TARGET_NODE ? 'commonjs2' : undefined
    },
    optimization: {
      splitChunks: undefined
    }
  }),
  chainWebpack: config => {
    config.module
      .rule('vue')
      .use('vue-loader')
      .tap(options => {
        return merge(options, {
          optimizeSSR: false
        })
      })
  }
}
 

Step 8: Build Your App

Add the following scripts to your `package.json`:


"scripts": {
  "build:client": "vue-cli-service build",
  "build:server": "cross-env WEBPACK_TARGET=node vue-cli-service build --mode server",
  "build": "npm run build:client && npm run build:server",
  "start": "node server.js"
}
 

Now, build your app:


npm run build
 

Step 9: Deploy to CloudBlast VPS

1. Upload your built files to your CloudBlast VPS using SCP or SFTP.
2. SSH into your VPS.
3. Navigate to your project directory.
4. Install production dependencies:


npm install --production
 

5. Start your server:


npm start
 

Your Vue.js app with SSR using Fastify should now be running on your CloudBlast VPS!

Conclusion

Congratulations! You've successfully set up Server-Side Rendering for your Vue.js app using Fastify on CloudBlast's VPS hosting. This setup will improve your app's initial load time and SEO performance.

Remember to configure your domain and set up a reverse proxy like Nginx for production use. If you need any further assistance, don't hesitate to reach out to CloudBlast's support team.

Happy coding!