SSR介绍-2: 传统SSR实现
此篇文章将结合vue来简单介绍如何实现传统的SSR,为后续实现现今流行的SSR打个基础。
参考vue ssr官网:https://ssr.vuejs.org/zh/guide/#%E5%AE%89%E8%A3%85
新建工程
创建项目(vue-cli):vue create ssr
安装依赖:npm install vue-server-renderer express -D
安装时,注意保证依赖vue, vue-server-renderer,vue-template-compiler版本一致,不然可能会报错(这里我的版本是2.6.12)
创建服务器
这里使用express作为服务器,使用vue-server-renderer实现将vue实例渲染成html字符串功能
// 导入express服务器,将vue ssr集成进来
const express = require('express')
// 1. 创建express实例,用于启动web服务器
const server = express()
// 导入vue,用于声明待渲染的vue实例
const Vue = require("vue")
// 2. 获取渲染器实例
const { createRenderer } = require('vue-server-renderer')
const renderer = createRenderer()
// 创建后端路由
server.get('*', (req, res) => {
// 1. 创建vue实例
const app = new Vue({
// 注意模板最外层只能有一个元素,不然会报错
template: `<div>
<h1>hello ssr</h1>
<div @click="onClick">{{msg}}</div>
</div>
`,
data() {
return {
msg: 'vue ssr'
}
},
methods: {
logMsg() {
console.log(this.msg);
}
}
})
// 2. 用渲染器渲染vue实例,将vue实例渲染成html字符串
renderer.renderToString(app).then(html => {
console.log(html);
res.send(html)
}).catch(err => {
res.status(500)
res.send('Internet Server Error')
})
})
server.listen(3000, () => {
console.log('server is running!');
})
根据不同的路由,动态渲染不同的模板页面
上面的例子,是将模板给写死的,但在实际过程中,我们一般是将模板(html页面)给抽离出来,根据不同的路由,加载对应的模板文件,下面来改进一下
- 创建模板文件,用于测试不同路由渲染模板的功能
<!-- server/home.html -->
<body>
<div>
<h1>首页</h1>
<div @click="onClick">{{msg}}</div>
</div>
</body>
<!-- server/detail.html -->
<body>
<div>这是详情页</div>
</body>
- 修改服务器文件,改为根据路由名称来加载不同的模板文件
// server/index.js
// 1. 引入fs(进行IO操作)和path(用于读取和拼接路径)库
const fs = require('fs')
const path = require('path')
server.get('*', (req, res) => {
console.log(req.url);
// 2. 这里简单的截取/后的路由(暂时不考虑多级路由的情况)
const templateName = req.url.substring(1) || 'index'
// 3. 根据路由名称,读取对应的html页面
const template = fs.readFileSync(path.join(__dirname, `${templateName}.html`), 'utf-8')
const app = new Vue({
// 4. 将模板文件由写死的改为动态读取的html页面
template: template,
data() {
return {
msg: `这是访问'${req.url}'后的页面,渲染的是${templateName}.html文件`
}
},
methods: {
logMsg() {
console.log(this.msg);
}
}
})
renderer.renderToString(app).then(html => {
res.send(html)
}).catch(err => {
res.status(500)
res.send('Internet Server Error')
})
})
启动服务
可以安装nodemon,用于热启动(即修改服务后不需要手动重新启服务)服务:npm i nodemon -g
启动服务:nodemon ./server/index.js
在浏览器中访问'/'和'detail'的效果如下:
访问/.png
访问/detail.png
可以看到启动效果,此时已经返回一个完整html结构,怎么确认它是服务端渲染的页面呢?它会有个标识 data-server-rendered="true",这就代表着是服务端渲染的。
可以看到,即使我们在创建vue实例时,写了click点击事件,但在经过ssr后,它会变成一个静态文件,你点击msg时,并不会有日志输出,这是因为经过ssr后,后端返回的是一个静态页面,是不能进行任何交互的。
那么,怎么实现在前端激活这些交互呢?这就是我们现在流行的ssr区别于传统ssr的一大特点,本来想自己写激活的博客的,突然发现别的大佬讲得更清楚,我就不献丑了,直接上链接:
https://segmentfault.com/a/1190000019618170
https://segmentfault.com/a/1190000019462324?utm_source=sf-similar-article