筆記:關於 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 函數, 這些均可以嘗試一下。

相關文章
相關標籤/搜索