Vue SSR 介绍
- 官方文档:https://ssr.vuejs.org/
- Vue SSR(Vue.js Server-Side Rendering) 是 Vue.js 官方提供的一个服务端渲染(同构应用)解 决方案
- 使用它可以构建同构应用
- 还是基于原有的 Vue.js 技术栈
使用场景
在对你的应用程序使用服务器端渲染 (SSR) 之前,你应该问的第一个问题是,是否真的需要它。
- 技术层面: 更快的首屏渲染速度,更好的 SEO
- 业务层面: 不适合管理系统,适合门户资讯类网站,例如企业官网、知乎、简书等 适合移动网站
如何使用 Vue SSR
-
基于 Vue SSR 官方文档提供的解决方案
官方方案具有更直接的控制应用程序的结构,更深入底层,更加灵活,同时在使用官方方案的过程中, 也会对 Vue SSR 有更加深入的了解。
该方式需要你熟悉 Vue.js 本身,并且具有 Node.js 和 webpack 的相当不错的应用经验。
-
Nuxt.js 开发框架
NUXT 提供了平滑的开箱即用的体验,它建立在同等的 Vue 技术栈之上,但抽象出很多模板,并提供了 一些额外的功能,例如静态站点生成。通过 Nuxt.js 可以快速的使用 Vue SSR 构建同构应用。
Vue SSR 基本使用(使用 Vue SSR 渲染一个 Vue 实例)
-
在 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) })
在控制台会输出下列信息:
image-20210325080026326.pngdata-server-rendered="true"
是将来用于客户端渲染激活接管的入口 -
与服务端集成,如何把渲染得到的结果发送给用户端浏览器
安装
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
-
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 会把渲染后的结果解析替换到模板中。作为完整结果返回,此时页面内容正常
-
页面模板使用外部数据
修改模板内容后,需重启服务端,对标签进行渲染,使用
{{{ meta }}}
进行绑定,vue 就不会进行处理,原文输出... {{{ meta }}} <title>{{ title }}</title> ...
renderer.renderToString(app, { title: '拉钩教育', meta: ` <meta name="description" content="拉钩"> ` }, (err, html) => { ... } })
此时可以看到浏览器中返回的 html 片段如下:
image-20210325082514556.png
项目地址
网友评论