Vue SSR 指南(一)
根据官网按步骤实现Vue SSR搭建过程
命令构建项目初始化 : 新建一个文件夹 ssr
cd ssr
npm init -y
npm install vue vue-server-renderer express --save
或者yarn add vue vue-server-renderer express --save
渲染一个 Vue 实例
1.新建文件server1.js
// 1、创建一个vue实例
const Vue = require('vue')
const app = new Vue({
template:`<div>hello ssr</div>`
})
//2、创建一个renderer
const renderer = require('vue-server-renderer').createRenderer()
//3、将vue实例渲染为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)
})
2.运行命令node server.js
,控制台会输出两行<div data-server-rendered="true">Hello ssr</div>
与服务器集成
1.新建文件server2.js (npm install express --save)
const Vue = require('vue')
const server = require('express')()
const renderer = require('vue-server-renderer').createRenderer()
server.get('*', (req, res) => {
const app = new Vue({
data: {
url: req.url,
},
template: `<div>访问的 URL是:{{url}}</div>`,
})
renderer.renderToString(app, (err, html) => {
if (err) {
res.status(500).end('Internal Server Error')
return
}
res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' }) //writeHeader可以设置http返回状态码,多个http响应头。但是setHeader只针对单一属性的设置。
// res.setHeader('Content-Type', 'text/html;charset=UTF-8') //解决乱码 注意:文件必须是utf-8格式
res.end(`
<!DOCTYPE html>
<html lang="en">
<head><title>Hello</title></head>
<body>${html}</body>
</html>
`)
})
})
server.listen(8080)
2.运行命令node server2.js
,浏览器打开 localhost:8080
使用一个页面模板
1.使用页面模板,新建文件index.template.html 。注意 <!--vue-ssr-outlet-->
注释 – 这里将是应用程序 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>vue ssr</title>
</head>
<body>
<!--vue-ssr-outlet-->
</body>
</html>
2.新建文件server3.js
const Vue = require('vue')
const server = require('express')()
const renderer = require('vue-server-renderer').createRenderer({
template: require('fs').readFileSync('./index.template.html', 'utf-8'),
})
server.get('*', (req, res) => {
const app = new Vue({
data: {
url: req.url,
},
template: `<div>您访问的URL: {{url}}</div>`,
})
renderer.renderToString(app, (err, html) => {
if (err) {
res.status(500).end('Internal Server Error')
return
}
res.end(html)
})
})
server.listen(8080)
模板插值
1.使用页面模板,新建文件index.template1.html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- 使用三花括号(triple-mustache)进行 HTML 不转义插值(non-HTML-escaped interpolation) -->
{{{ meta }}}
<!-- 使用双花括号(double-mustache)进行 HTML 转义插值(HTML-escaped interpolation) -->
<title>{{ title }}</title>
</head>
<body>
<!--vue-ssr-outlet-->
</body>
</html>
2.新建server4.js
const Vue = require('vue')
const server = require('express')()
const renderer = require('vue-server-renderer').createRenderer({
template: require('fs').readFileSync('./index.template1.html', 'utf-8'),
})
server.get('*', (req, res) => {
const app = new Vue({
data: {
url: req.url,
},
template: `<div>您访问的URL: {{url}}</div>`,
})
const context = {
title: 'Vue ssr',
meta: `
<meta charset="utf-8">
`,
}
renderer.renderToString(app, context, (err, html) => {
if (err) {
res.status(500).end('Internal Server Error')
return
}
res.end(html)
})
})
server.listen(8080)
源码结构,避免避免状态单例
为每个请求创建一个新的根vue实例,避免请求共享,状态污染。暴露一个可以重复执行的工厂函数,为每个请求创建新的应用程序实例:
1.新建app.js
const Vue = require('vue')
module.exports = function createApp(context) {
return new Vue({
data: {
url: context.url,
},
template: `<div>{{url}}</div>`,
})
}
2.新建server.js
const createApp = require('./app')
const server = require('express')()
const renderer = require('vue-server-renderer').createRenderer({
template: require('fs').readFileSync('./index.template.html', 'utf-8'),
})
server.get('*', (req, res) => {
const app = createApp({ url: req.url })
renderer.renderToString(app, (err, html) => {
if (err) {
res.status(500).end('Internal Server Error')
return
}
console.log('html: ', html)
res.end(html)
})
})
server.listen(8080)
3.运行node server.js
源码
目录结构下的ssr