一、概述
目前我们所知的三大框架都是客户端渲染前端框架: Agular、react、Vue
这些客户端渲染框架所构建的spa单页面应用的有点: 用户体验好;开发效率高;渲染性能好;可维护性好;......
同样这些spa单页面应用的缺点:首屏渲染时间长(所有的页面都是由js先解析html模板)、不利于SEO,因为浏览器都是爬取html,而这些单页面应用在没有解析js之前html都是没有内容的
为了解决上述的缺点,借鉴了传统的服务端渲染
同构应用:1、通过服务端渲染首屏直出,解决spa应用首屏渲染慢以及不利于SEO问题。2、通过客户端渲染接管页面内容交互获得更好的用户体验
这种方式通常称之为现代化的服务端渲染,也叫同构渲染;这种方式构建的应用称之为服务端渲染应用或者是同构应用
二、什么是渲染?
渲染就是把【数据】+ 【模板】拼接到一起,他的本质就是字符串的解析替换
三、传统的服务端渲染
传统服务端渲染缺点:前后端代码完全耦合在一起,不利于开发和维护; 前端没有足够发挥空间; 服务端压力大; 用户体验一般
四、客户端渲染
优点:前端更独立于后端更好处理
缺点:首屏渲染满;不利于SEO
首屏渲染慢的原因: 因为传统的服务端渲染只有一次请求页面直出;而客户端渲染至少又三次http请求周期 ,一个是html页面的请求 一个是js的请求 一个是动态数据的请求所以首屏渲染慢。
不利于SEO的原因:SEO的实质是搜索引擎得知道你这个页面的关键词,单页面应用基本上是0Seo,SEO的前提是搜索引擎得知道这个网站有什么
// 搜索引擎是怎么获取网页内容的?
const http = require('http')
// 通过程序获取指定的网页内容
// http.get('http://localhost:3000/', res => {
http.get('http://localhost:8080/', res => {
let data = ''
// 监听data 每有一个代码块过来就会拼接
res.on('data', chunk => {
data += chunk
})
res.on('end', () => {
console.log(data)
})
})
由程序如果获取服务端的页面,那么他会得到完整的内容,根据内容去获取网页的关键词,而获取的客户端渲染的内容他的body里面是空的就如同下面这个样子,它的内容是必须解析最下面那个js才能获取相应的内容,而SEO获取的内容仅仅是html字符串,他不会去解析js
五、现代化的服务端渲染
同构渲染 = 前端渲染 + 后端渲染
- 基于React、Vue等框架,客户端渲染和服务端渲染的结合(在服务器端执行一次,用于实现服务器端渲染【首屏直出】、客户端再执行一次,用于接管页面交互)
- 核心解决SEO和首屏渲染慢的问题
- 拥有传统服务端渲染的优点,也有客户端渲染的优点
如何实现同构渲染:
1、使用Vue、React等框架的官方解决方案:优点是有利于理解原理 缺点是需要搭建环境,十分麻烦
2、使用第三方解决方案:React生态的Next.js以及Vue生态的Nuxt.js
六、同构渲染的SPA应用
1、在nuxt.js的框架中如果想解决渲染首屏过慢和SEO的问题,需要调用nuxt.js的 asyncData方法,它的作用是应用在进入首屏时获取数据并将数据渲染到html返回,它取代了Vue中的created方法,并且asyncData会返回一个data对象,里面会把请求过来的数据插入到本页面的data中,这块是服务端渲染
export default {
name: 'HomePage',
components: {
Foo
},
// 当你想要动态页面内容有利于 SEO 或者是提升首屏渲染速度的时候,就在 asyncData 中发请求拿数据
async asyncData () {
console.log('asyncData')
console.log(this)
const res = await axios({
method: 'GET',
url: 'http://localhost:3000/data.json'
})
return res.data
},
// 如果是非异步数据或者普通数据,则正常的初始化到 data 中即可
data () {
return {
foo: 'bar'
}
}
}
2、nuxt.js中的layout里面存放的是全局的父组件,相当于vue app.vue中的唯一iddiv, 里面的<Nuxt/>相当于<router-view></router-view>,里面是每一个页面组件,同过路由跳转页面,就是客户端渲染
<template>
// 子页面出口
<Nuxt />
</template>
七、同构渲染的问题
- 开发条件所限 (主要是某些代码操作需要区分运行环境)
- 浏览器特定的代码只能在某些生命周期钩子函数中使用(因为要区分服务端渲染的生命周期和客户端渲染的生命周期)
- 一些外部扩展库可能需要特殊处理才能在服务端渲染应用中运行
- 不能在服务端渲染期间操作dom
- 涉及构建设置和部署的更多要求
- 构建方面:客户端渲染仅构建客户端应用即可,而同构渲染需要构建两个端
- 部署方面:客户端渲染可以部署在任意Web服务器中,而同构渲染只能部署在Node.js Server中
- 更多的服务器负载
- 在Node中渲染完整的应用程序,相比仅仅提供静态文件的服务器 需要占用大量CPU资源
- 如果应用在高流量环境下使用,需要准备相应的服务器负载
- 需要更多的服务端渲染优化工作处理