使用 Vue SSR 渲染一个 Vue 实例

2021-03-26  本文已影响0人  翔子丶
Vue SSR 介绍
使用场景

在对你的应用程序使用服务器端渲染 (SSR) 之前,你应该问的第一个问题是,是否真的需要它。

如何使用 Vue SSR
  1. 基于 Vue SSR 官方文档提供的解决方案

    官方方案具有更直接的控制应用程序的结构,更深入底层,更加灵活,同时在使用官方方案的过程中, 也会对 Vue SSR 有更加深入的了解。

    该方式需要你熟悉 Vue.js 本身,并且具有 Node.js 和 webpack 的相当不错的应用经验。

  2. Nuxt.js 开发框架

    NUXT 提供了平滑的开箱即用的体验,它建立在同等的 Vue 技术栈之上,但抽象出很多模板,并提供了 一些额外的功能,例如静态站点生成。通过 Nuxt.js 可以快速的使用 Vue SSR 构建同构应用。

Vue SSR 基本使用(使用 Vue SSR 渲染一个 Vue 实例)
  1. 在 nodeJs 中使用 VueSSR,将一个 Vue 实例渲染为 HTML 字符串

    • 初始化项目,安装 vue 和 vue-server-renderer
    • 创建 server.js,引入 Vue 并创建 Vue 实例
    • 引入 vue-server-renderer 并调用 createRenderer 生成一个渲染器来渲染 Vue 实例
    const Vue = require('vue')
    // 调用createRenderer生成一个渲染器
    const renderer = require('vue-server-renderer').createRenderer()
    
    const app = new Vue({
      template: `
        <div id="app">
          <h1>{{ message }}</h1>
        </div>
      `,
      data: {
        message: '拉钩',
      },
    })
    /**
     * app Vue实例
     * err 错误
     * html 返回的html字符串
     */
    renderer.renderToString(app, (err, html) => {
      if (err) throw err
      console.log(html)
    })
    // 在 2.5.0+,如果没有传入回调函数,则会返回 Promise:
    renderer
      .renderToString(app)
      .then((html) => {
        console.log(html)
      })
      .catch((err) => {
        console.error(err)
      })
    

    在控制台会输出下列信息:data-server-rendered="true"是将来用于客户端渲染激活接管的入口

    image-20210325080026326.png
  2. 与服务端集成,如何把渲染得到的结果发送给用户端浏览器

    安装express npm i express --save

    const Vue = require('vue')
    const renderer = require('vue-server-renderer').createRenderer()
    const express = require('express')
    // 得到express实例
    const server = express()
    
    server.get('/', (req, res) => {
      const app = new Vue({
        template: `
          <div id="app">
            <h1>{{ message }}</h1>
          </div>
        `,
        data: {
          message: '拉钩',
        },
      })
      renderer.renderToString(app, (err, html) => {
        if (err) {
          return res.status(500).end('Internal Srever ERROR')
        }
        // 解决乱码问题1
        // res.setHeader('Content-Type', 'text/html;charset=utf-8')
        // 解决乱码问题2
        res.end(`
          <!DOCTYPE html>
          <html lang="en">
          <head>
            <meta charset="UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Document</title>
          </head>
          <body>
            ${html}
          </body>
          </html>
        `)
      })
    })
    
    // 启动web服务
    server.listen(3000, () => {
      console.log('server running at port 3000')
    })
    

    此时,打开浏览器控制台,可以看到返回 html 片段信息:

    image-20210325080651945.png
  1. HTML 模板内容单独维护

    在根目录下生成生成index.template.html文件

    复制模板到这里,删除${html}标签,添加``,使用 renderer 渲染页面时会把它当作模板来使用,会由具体渲染内容替换

    <!--index.tenplate.html-->
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
      </head>
      <body>
        <!--vue-ssr-outlet-->
      </body>
    </html>
    

    createRenderer 中可以添加参数 template 模板

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

    当设置模板后 renderer.renderToString 会把渲染后的结果解析替换到模板中。作为完整结果返回,此时页面内容正常

  2. 页面模板使用外部数据

    修改模板内容后,需重启服务端,对标签进行渲染,使用{{{ meta }}}进行绑定,vue 就不会进行处理,原文输出

    ... {{{ meta }}}
    <title>{{ title }}</title>
    ...
    
    renderer.renderToString(app, {
        title: '拉钩教育',
        meta: `
              <meta name="description" content="拉钩">
            `
          }, (err, html) => {
        ...
     }
    })
    

    此时可以看到浏览器中返回的 html 片段如下:

    image-20210325082514556.png
    项目地址
上一篇 下一篇

猜你喜欢

热点阅读