Skip to content

SSR guide #864

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Feb 24, 2021
5 changes: 5 additions & 0 deletions src/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ const sidebar = {
]
}
],
ssr: [
['/guide/ssr/introduction', 'Introduction'],
'/guide/ssr/getting-started'
],
contributing: [
{
title: 'Contribute to the Docs',
Expand Down Expand Up @@ -420,6 +424,7 @@ module.exports = {
collapsable: false,
'/guide/migration/': sidebar.migration,
'/guide/contributing/': sidebar.contributing,
'/guide/ssr/': sidebar.ssr,
'/guide/': sidebar.guide,
'/community/': sidebar.guide,
'/cookbook/': sidebar.cookbook,
Expand Down
2 changes: 1 addition & 1 deletion src/guide/ssr.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## The Complete SSR Guide

We have created a standalone guide for creating server-rendered Vue applications. This is a very in-depth guide for those who are already familiar with client-side Vue development, server-side Node.js development and webpack. Check it out at [ssr.vuejs.org](https://ssr.vuejs.org/).
We have created a standalone guide for creating server-rendered Vue applications. This is a very in-depth guide for those who are already familiar with client-side Vue development, server-side Node.js development and webpack. Check it out [here](/guide/ssr/introduction.html).

## Nuxt.js

Expand Down
97 changes: 97 additions & 0 deletions src/guide/ssr/getting-started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Getting Started

> This guide is currently under active development

## Installation

In order to create a server-side rendered application, we need to install the `@vue/server-renderer` package:

```bash
npm install @vue/server-renderer
## OR
yarn add @vue/server-renderer
```

#### Notes

- It's recommended to use Node.js version 10+.
- `@vue/server-renderer` and `vue` must have matching versions.
- `@vue/server-renderer` relies on some Node.js native modules and therefore can only be used in Node.js. We may provide a simpler build that can be run in other JavaScript runtimes in the future.

## Rendering a Vue Application

Unlike a client-only Vue application, which is created using `createApp`, an SSR application needs to be created using `createSSRApp`:

```js
const { createSSRApp } = require('vue')

const app = createSSRApp({
data() {
return {
user: 'John Doe'
}
},
template: `<div>Current user is: {{ user }}</div>`
})
```

Now, we can use the `renderToString` function to render our application instance to a string. This function returns a Promise which resolves to the rendered HTML.

```js{2,13}
const { createSSRApp } = require('vue')
const { renderToString } = require('@vue/server-renderer')

const app = createSSRApp({
data() {
return {
user: 'John Doe'
}
},
template: `<div>Current user is: {{ user }}</div>`
})

const appContent = await renderToString(app)
```

## Integrating with a Server

To run an application, in this example we will use [Express](https://expressjs.com/):

```bash
npm install express
## OR
yarn add express
```

```js
const { createSSRApp } = require('vue')
const { renderToString } = require('@vue/server-renderer')
const server = require('express')()

server.get('*', async (req, res) => {
const app = createSSRApp({
data() {
return {
user: 'John Doe'
}
},
template: `<div>Current user is: {{ user }}</div>`
})

const appContent = await renderToString(app)
const html = `
<html>
<body>
<h1>My First Heading</h1>
${appContent}
</body>
</html>
`

res.end(html)
})

server.listen(8080)
```

Now, when running this Node.js script, we can see a static HTML page on `localhost:8080`. However, this code is not _hydrated_: Vue hasn't yet take over the static HTML sent by the server to turn it into dynamic DOM that can react to client-side data changes. This will be covered in the [Client Side Hydration](#) section.
47 changes: 47 additions & 0 deletions src/guide/ssr/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Server-Side Rendering Guide

> This guide is currently under active development

## What is Server-Side Rendering (SSR)?

Vue.js is a framework for building client-side applications. By default, Vue components produce and manipulate DOM in the browser as output. However, it is also possible to render the same components into HTML strings on the server, send them directly to the browser, and finally "hydrate" the static markup into a fully interactive application on the client.

A server-rendered Vue.js application can also be considered "isomorphic" or "universal". This means that the majority of your app's code runs on both the server **and** the client.

## Why SSR?

Compared to a traditional SPA (Single-Page Application), the advantage of SSR primarily lies in:

- Better search engine optimization (SEO), as the search engine crawlers will directly see the fully rendered page.

Note that as of now, Google and Bing can index synchronous JavaScript applications just fine. Synchronous being the key word there. If your app starts with a loading spinner, then fetches content via API call, the crawler will not wait for you to finish. This means if you have content fetched asynchronously on pages where SEO is important, SSR might be necessary.

- Faster time-to-content, especially on the slow Internet connection or slow devices. Server-rendered markup doesn't need to wait until all JavaScript has been downloaded and executed to be displayed, so your user will see a fully-rendered page sooner. This generally results in better user experience, and can be critical for applications where time-to-content is directly associated with the conversion rate.

There are also some trade-offs to consider when using SSR:

- Development constraints. Browser-specific code can only be used inside certain lifecycle hooks; some external libraries may need special treatment to be able to run in a server-rendered app.

- More involved build setup and deployment requirements. Unlike a fully static SPA that can be deployed on any static file server, a server-rendered app requires an environment where a Node.js server can run.

- More server-side load. Rendering a full app in Node.js is going to be more CPU-intensive than just serving static files, so if you expect high traffic, be prepared for corresponding server load and wisely employ caching strategies.

Before using SSR for your application, the first question you should ask is whether you actually need it. It mostly depends on how important time-to-content is for your application. For example, if you are building an internal dashboard where an extra few hundred milliseconds on the initial load doesn't matter that much, SSR would be overkill. However, in cases where time-to-content is absolutely critical, SSR can help you achieve the best possible initial load performance.

## SSR vs Prerendering

If you're only investigating SSR to improve the SEO of a handful of marketing pages (e.g. `/`, `/about`, `/contact`, etc), then you probably want **prerendering** instead. Rather than using a web server to compile HTML on-the-fly, prerendering generates static HTML files for specific routes at build time. The advantage is setting up prerendering is much simpler and allows you to keep your frontend as a fully static site.

If you're using [webpack](https://webpack.js.org/), you can add prerendering with the [prerender-spa-plugin](https://github.com/chrisvfritz/prerender-spa-plugin). It's been extensively tested with Vue apps.

## About This Guide

[//]: # 'TODO: This guide is focused on server-rendered Single-Page Applications using Node.js as the server. Mixing Vue SSR with other backend setups is a topic of its own and briefly discussed in a [dedicated section].'

This guide will be very in-depth and assumes you are already familiar with Vue.js itself, and have a decent working knowledge of Node.js and webpack.

[//]: # 'If you prefer a higher-level solution that provides a smooth out-of-the-box experience, you should probably give [Nuxt.js](https://nuxtjs.org/) a try. It's built upon the same Vue stack but abstracts away a lot of the boilerplate, and provides some extra features such as static site generation. However, it may not suit your use case if you need more direct control of your app's structure. Regardless, it would still be beneficial to read through this guide to understand better how things work together.'

[//]: # 'TODO: As you read along, it would be helpful to refer to the official [HackerNews Demo](https://github.com/vuejs/vue-hackernews-2.0/), which makes use of most of the techniques covered in this guide'

Finally, note that the solutions in this guide are not definitive - we've found them to be working well for us, but that doesn't mean they cannot be improved. They might get revised in the future - and feel free to contribute by submitting pull requests!