- 安装vue和vue-server-renderer
npm install vue vue-server-renderer --save
2.创建vue实例,使用renderer解析
// 创建vue实例
const Vue = require("vue");
const app = new Vue({
template: `<div>hellow world</div>`,
});
// 创建一个renderer
const renderer = require("vue-server-renderer").createRenderer();
// 将实力渲染成HTML
// renderer.renderToString(app,(err,html)=>{
// if (err) throw err;
// console.log(html)
// })
// 2.5.0++ 不传入回调函数
renderer
.renderToString(app)
.then((html) => {
console.log(html);
})
.catch((err) => {
console.log(err);
});
与服务器集成
安装express
npm install express --save
启用一个服务,访问任何页面都只返回一个renderer.renderToString方法将vue实例app转换成的html
const Vue = require("vue");
const server = require("express")();
const renderer = require("vue-server-renderer").createRenderer();
/**
* req 请求对象
* res 响应对象
*/
server.get("*", (req, res) => {
const app = new Vue({
data() {
return {
url: req.url,
};
},
template: `<div>访问的URL是:{{url}}</div>`,
});
renderer
.renderToString(app)
.then((html) => {
res.end(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>${html}</body>
</html>
`);
})
.catch((err) => {
res.status(500).end("Internal Server Error");
});
});
server.listen(8000, () => {
console.log("服务启动在localhost:8000...");
});
renderer创建时传入模板,将来自动将内容渲染到模板中标签上
模板中支持插值表达式,{{{}}}表示不用转义,{{}}会做转义处理
const renderer = require('vue-server-renderer').createRenderer({
template: require('fs').readFileSync('./index.template.html', 'utf-8')
})
renderer.renderToString(app, (err, html) => {
console.log(html) // html 将是注入应用程序内容的完整页面
})
template中的值来源于renderer.toString执行传入的第二个参数
const context={
title:"这是注入的title",
meta: `
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
`
}
//执行时传入即可
renderer
.renderToString(app,context)
.then((html) => {
console.log(html)
res.end(html);
})
.catch((err) => {
res.status(500).end("Internal Server Error");
});
完整代码
const Vue = require("vue");
const server = require("express")();
const template = require("fs").readFileSync("./index.template.html", "utf-8");
const renderer = require("vue-server-renderer").createRenderer({
template,
});
const context = {
title: "这是注入的title",
meta: `
<meta name="keyword" content="vue,ssr">
<meta name="description" content="vue srr demo">
`,
};
/**
* req 请求对象
* res 响应对象
*/
server.get("*", (req, res) => {
const app = new Vue({
data() {
return {
url: req.url,
};
},
template: `<div>访问的URL是:{{url}}</div>`,
});
renderer
.renderToString(app, context)
.then((html) => {
res.end(html);
})
.catch((err) => {
res.status(500).end("Internal Server Error");
});
});
server.listen(8000, () => {
console.log("服务启动在localhost:8000...");
});
编写通用代码
服务器的数据的响应式
因为代码在服务器端,希望每次访问都是一个新的实例,因为服务器端来说,每个请求都是一次新的服务,
实际渲染过程中需要确定性,我们要在服务器上预取数据,这意味着,服务器端的响应式是多于的,默认禁用,省了些性能开销
生命周期的执行位置
beforeCreate/created在服务器端执行,这些方法中不要使用setInterval,可以在beforeMount/mounted中设置,在beforeDestroy 或者destroy中销毁