笔记:关于 Vue-SSR 的实践性测试

Express SSR

yarn add express
#or
npm i express --save

在根目录新建一个 index.js 文件, 内容以下:html

index.jsvue

const app = require('express')()

app.get('/', (req, res) => {
  res.send(`
  <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <h1>你好世界!</h1>
    </body>
    </html>
  `)
})

app.listen(3000);
console.info('application is running at: http://localhost:3000');

这时候执行 node .\index.js 是能够访问到你好世界的, 这其实就是 SSR。node

Vue-SSR 意思能够解读为将 Vue 对象放在服务端建立。express

Express 渲染 Vue

安装 vue 与 vue-server-renderer。npm

yarn add vue vue-server-renderer
#or
npm i vue vue-server-renderer --save

在 express 中渲染一个 Vue 的实例须要 3 步:bash

  1. 建立一个 Vue 实例
  2. 建立一个 Renderer
  3. 用 Renderer 渲染 Vue 实例

因此, 打开 index.js 文件,在顶部添加引入app

const Vue = require('vue')
const renderer = require('vue-server-renderer').createRenderer()

引入后再添加一个新的路由地址函数

app.get('/vue', (req, res) => {
  // 建立 Vue 实例
  const app = new Vue({
    data: {
      content: 'Hello Vue'
    },
    template: `
    <h1>{{content}}</h1>
    `
  })

  // 使用 renderer 把 Vue 实例渲染为 HTML
  renderer.renderToString(app, (err, html) => {
    if (err) {
      res.status(500).end('Internal Server Error')
      return
    }
    res.end(`
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      ${html}
    </body>
    </html>
    `)
  })
})

准备好之后从新启动ui

node index.js

访问:http://localhost:3000/vue,便可查看效果。ssr

使用 HTML 模板

观察上面的内容不难发现, Vue 实例被渲染后生成的 HTML 并非一个完整的文件,他是须要配合 end 函数中的一大堆字符串 HTML 一块儿工做。

这么一大串 HTML 的字符串写起来但是不太友好。

因此 renderer 对象在建立时能够被指定一个 HTML 模板,这个模板至关于把 end 函数中的那一大串 HTML 字符串提出去了,而且经过约定,将 Vue 实例生成的 HTML 放在约定好的位置。

具体作法以下:

  1. 在根目录新建 index.template.html 文件。
  2. 写入基础 HTML。
  3. 在想要渲染 Vue 实例的位置贴上 <!--vue-ssr-outlet--> 这个注释。

例如:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <!--vue-ssr-outlet-->
</body>

</html>
注意: <!--vue-ssr-outlet--> 不能够有空格

而后修改 index.js 文件的 createRenderer 函数:

const renderer = require('vue-server-renderer').createRenderer({
  template: require('fs').readFileSync('./index.template.html', 'utf-8')
})

修改 /vue 路由:

app.get('/vue', (req, res) => {
  const app = new Vue({
    data: {
      content: 'Hello Vue'
    },
    template: `
    <h1>{{content}}</h1>
    `
  })
  renderer.renderToString(app, (err, html) => {
    if (err) {
      res.status(500).end('Internal Server Error')
      return
    }
    res.end(html)
  })
})

从新启动

node index.js

访问:http://localhost:3000/vue, 看起来一切正常。

关于 Renderer

Renderer 接口的定义以下:

interface Renderer {
  renderToString(vm: Vue, callback: RenderCallback): void;
  renderToString(vm: Vue, context: object, callback: RenderCallback): void;
  renderToString(vm: Vue): Promise<string>;
  renderToString(vm: Vue, context: object): Promise<string>;

  renderToStream(vm: Vue, context?: object): Readable;
}

renderToString 具备 4 个重载,另外还有一个 renderToStream 函数, 这些均可以尝试一下。

相关文章
相关标签/搜索