前言
今天我们的主题是:Vue SSR,这个名词相信我们大家都不陌生,但是现在我们做的一些项目并不会都去使用,那SSR具体是怎么实现呢?又什么时候用才好呢?今天我们就从Vue中的SSR的实现来入手,完整的走一遍流程,一起来吧~
PS:Vue-SSR将会分为三部分完成:理解SSR以及实践于Vue(上)、Vue中同构开发SSR应用(中)、Nuxt.js实践(下)
什么是SSR
SSR全称为服务端渲染(Server Side Render),ennnn,那我们又该问了?什么又是服务端渲染呢?先别急,我们来从web开发的一步步发展开始讲起~
传统web开发
我们都知道,web的开发工作在开始之初其实基本都是后端开发者完成的,那时候甚至来说都还没有前端开发工程师这个职位,那时候都是前后端不分离(如jsp这种),也就是说网页内容是在服务端渲染完成之后,再一次性传输到浏览器。
我们画一张图来大概表示一下这个过程:
通过上图我们应该可以了解到传统的web开发的模式,接下来我们就使用node来构建简单的服务端来模拟一下以前的方式:
node服务端的代码如下:
const express = require("express")
const app = express()
app.get("/", (req, res) => {
res.send(`<h3>hello,guangying</h3>`);
});
app.listen(3000, () => {
console.log("server running...");
});
我们将其运行起来然后右键显示网页源代码,我们可以看到结果:
那么结合上面的描述,我们发现这种方式浏览器拿到的是全部完整的DOM结构
单页应用SPA(Single Page App)
由于传统的开发模式导致的结果是用户体验不是太好,而单页应用的优秀用户体验,让其逐渐发展为主流,页面内容由JS渲染出来,这种方式我们也称为客户端渲染
我们同样也画一张图来展示一下大概过程:
通过上图我们发现:相较于传统web开发,SPA的方式如果要完整的呈现在用户面前,那么最少都需要经历两次网络请求,因为第一次的时候服务器返回给客户端的只是页面骨架,并没有实际的内容,真正的内容是要等到客户端执行js代码之后才会生成的
这里我们以Vue为例,通过node来模拟一下该种方式:
const express = require('express')
const app = express()
app.get('/', (req, res) => {
const html = `
<div id="app">
<h3>hello, {{name}}</h3>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data:{
name: 'guangying'
}
})
</script>
`
res.send(html)
})
app.listen(3030, () => {
console.log('server running2...')
})
我们同样来通过查看网页源代码的方式检查一下,如图:
通过分析,我们基本上能够得出SPA方式的优缺点:
优点:
- 渲染计算放到客户端,这样减轻了服务端的压力
- 由于是单页面应用,会节省一部分流量
缺点:
- 首屏加载速度慢,尤其是网络环境不好的情况下
- 不利于搜索引擎的SEO
服务端渲染SSR(Server Side Render)
由于前两种方式存在的缺陷,于是便有了SSR,它相当于是位于前两者之间,SSR解决方案是:服务端渲染出完整的首屏DOM结构返回,前端能拿到的内容包括首屏以及完整的SPA结构,应用激活后仍然按照SPA方式运行,这种渲染方式就是SSR
PS:
- 简单点说那就是前两者之间的结合和改善
- 这里要提及一个概念——首屏!首屏!首屏!重要的事情说三遍,不是单纯的首页,这里感觉很容易混淆
同样我们也来画一个图来展示一下:
我们通过学习SSR的过程,我们发现他解决了前两者的问题,因为首屏是在服务端进行渲染的,SEO是可以正确拿到结果的;同时首屏在渲染完成传回客户端的时候,SSR同样也能携带如路由信息,状态管理信息等等到前端,简单点说就是传回来前端的就是首屏全部的结构以及SPA方式该有的结构,这样首屏渲染也就得到了改善
接下来我们就以Vue为例,进行Vue SSR的实践:
1、安装依赖:Vue中的服务端渲染模块:vue-server-renderer
PS:注意安装依赖的时候要保证Vue和vue-server-renderer的版本一致
npm install vue-server-renderer@2.6.10 -S
2、运行脚本:
const express = require('express')
const app = express()
// 1、导入Vue
const Vue = require('vue')
// 2、导入createRenderer并且获取渲染器
const {createRenderer} = require('vue-server-renderer')
const renderer = createRenderer()
app.get('*', async (req, res) => {
// 3、创建一个待渲染的Vue实例
const vm = new Vue({
template: `
<h1>hello,{{name}}</h1>
`,
data() {
return {
name: 'guangying'
}
},
})
try {
// renderToString将vue实例渲染为html字符串,它返回⼀个Promise
const html = await renderer.renderToString(vm)
// 返回html给客户端
res.send(html)
} catch (error) {
console.log(error)
}
})
app.listen(3333, () => {
console.log('sever running3')
})
写完之后我们运行,同样查看网页源代码,如图:
我们可以发现这时候我们得到了完整的DOM结构,但是我们注意红框中的属性,这是给Vue的,有了这个信息,Vue就知道这是服务端渲染的内容,将来在做激活的时候就有了凭证
我们现在这个例子是最基本的一个SSR例子,接下来我们来看看接入Vue-router之后的情况:
const express = require('express')
const app = express()
// 1、导入Vue
const Vue = require('vue')
// 引⼊vue-router
const Router = require('vue-router')
Vue.use(Router)
const {createRenderer} = require('vue-server-renderer')
const renderer = createRenderer()
// path修改为通配符
app.get('*', async (req, res) => {
// 每次创建⼀个路由实例
const router = new Router({
routes: [
{path: '/', component: {template: '<h1>这是首页</h1>'}},
{path: '/detail', component: {template: '<h1>这是详情</h1>'}}
]
})
const vm = new Vue({
// 添加router-view显示内容
template: `
<div>
<h1>hello,{{name}}</h1>
<router-link to="/">首页</router-link>
<router-link to="/detail">详情</router-link>
<router-view></router-view>
</div>
`,
router, // 挂载
data() {
return {
name: 'guangying'
}
},
})
try {
// 跳转⾄对应路由
router.push(req.url)
const html = await renderer.renderToString(vm)
res.send(html)
} catch (error) {
console.log(error)
}
})
app.listen(3333, () => {
console.log('sever running3')
})
其实讲到这里,我们关于Vue SSR的基本实践已经差不多了,但是我们想一想我们现在这样的写法会有哪些问题呢?
比如我们这么写是将服务端和前端混合在了一起,这样我们的开发负担会增加,同时代码不美观不容易维护,能不能让我们按照以前熟悉的Vue方式开发呢?
再比如如果我们想添加用户事件怎么让其生效呢?因为现在就是返回HTML字符串,直接按照熟悉的Vue方式写是无效的,换句话说那就是怎么激活后续的客户端呢?
这一篇我们主要就是介绍SSR的基本定义和基本实践,我们要先弄明白他的实现原理和实现的过程,下一篇我们继续学习如何使用同构的方式来完成服务端渲染和客户端激活
文末
欢迎关注「前端光影」公众号,公众号都是以系统专题模块的形式来展示的,这样看起来就会比较方便,系统,让我们一起持续学习各种前端知识,加油!
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!