• 基本用法
    • 安装
      • 注意
  • 渲染一个 Vue 实例
  • 与服务器集成
  • 使用一个页面模板
    • 模板插值

    基本用法

    安装

    1. npm install vue vue-server-renderer --save

    我们将在整个指南中使用 NPM,但你也可以使用 Yarn。

    注意

    • 推荐使用 Node.js 版本 6+。
    • vue-server-renderervue 必须匹配版本。
    • vue-server-renderer 依赖一些 Node.js 原生模块,因此只能在 Node.js 中使用。我们可能会提供一个更简单的构建,可以在将来在其他「JavaScript 运行时(runtime)」运行。

    渲染一个 Vue 实例

    1. // 第 1 步:创建一个 Vue 实例
    2. const Vue = require('vue')
    3. const app = new Vue({
    4. template: `<div>Hello World</div>`
    5. })
    6. // 第 2 步:创建一个 renderer
    7. const renderer = require('vue-server-renderer').createRenderer()
    8. // 第 3 步:将 Vue 实例渲染为 HTML
    9. renderer.renderToString(app, (err, html) => {
    10. if (err) throw err
    11. console.log(html)
    12. // => <div data-server-rendered="true">Hello World</div>
    13. })
    14. // 在 2.5.0+,如果没有传入回调函数,则会返回 Promise:
    15. renderer.renderToString(app).then(html => {
    16. console.log(html)
    17. }).catch(err => {
    18. console.error(err)
    19. })

    与服务器集成

    在 Node.js 服务器中使用时相当简单直接,例如 Express:

    1. npm install express --save

    1. const Vue = require('vue')
    2. const server = require('express')()
    3. const renderer = require('vue-server-renderer').createRenderer()
    4. server.get('*', (req, res) => {
    5. const app = new Vue({
    6. data: {
    7. url: req.url
    8. },
    9. template: `<div>访问的 URL 是: {{ url }}</div>`
    10. })
    11. renderer.renderToString(app, (err, html) => {
    12. if (err) {
    13. res.status(500).end('Internal Server Error')
    14. return
    15. }
    16. res.end(`
    17. <!DOCTYPE html>
    18. <html lang="en">
    19. <head><title>Hello</title></head>
    20. <body>${html}</body>
    21. </html>
    22. `)
    23. })
    24. })
    25. server.listen(8080)

    使用一个页面模板

    当你在渲染 Vue 应用程序时,renderer 只从应用程序生成 HTML 标记 (markup)。在这个示例中,我们必须用一个额外的 HTML 页面包裹容器,来包裹生成的 HTML 标记。

    为了简化这些,你可以直接在创建 renderer 时提供一个页面模板。多数时候,我们会将页面模板放在特有的文件中,例如 index.template.html

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head><title>Hello</title></head>
    4. <body>
    5. <!--vue-ssr-outlet-->
    6. </body>
    7. </html>

    注意 <!--vue-ssr-outlet--> 注释 — 这里将是应用程序 HTML 标记注入的地方。

    然后,我们可以读取和传输文件到 Vue renderer 中:

    1. const renderer = createRenderer({
    2. template: require('fs').readFileSync('./index.template.html', 'utf-8')
    3. })
    4. renderer.renderToString(app, (err, html) => {
    5. console.log(html) // html 将是注入应用程序内容的完整页面
    6. })

    模板插值

    模板还支持简单插值。给定如下模板:

    1. <html>
    2. <head>
    3. <!-- 使用双花括号(double-mustache)进行 HTML 转义插值(HTML-escaped interpolation) -->
    4. <title>{{ title }}</title>
    5. <!-- 使用三花括号(triple-mustache)进行 HTML 不转义插值(non-HTML-escaped interpolation) -->
    6. {{{ meta }}}
    7. </head>
    8. <body>
    9. <!--vue-ssr-outlet-->
    10. </body>
    11. </html>

    我们可以通过传入一个”渲染上下文对象”,作为 renderToString 函数的第二个参数,来提供插值数据:

    const context = {
      title: 'hello',
      meta: `
        <meta ...>
        <meta ...>
      `
    }
    
    renderer.renderToString(app, context, (err, html) => {
      // 页面 title 将会是 "Hello"
      // meta 标签也会注入
    })
    

    也可以与 Vue 应用程序实例共享 context 对象,允许模板插值中的组件动态地注册数据。

    此外,模板支持一些高级特性,例如:

    • 在使用 *.vue 组件时,自动注入「关键的 CSS(critical CSS)」;
    • 在使用 clientManifest 时,自动注入「资源链接(asset links)和资源预加载提示(resource hints)」;
    • 在嵌入 Vuex 状态进行客户端融合(client-side hydration)时,自动注入以及 XSS 防御。

    在之后的指南中介绍相关概念时,我们将详细讨论这些。