服务端渲染
基于客户端渲染的前端框架
- angular
- React
- Vue
SPA单页面应用
优点
- 用户体验好
- 开发效率高
- 渲染性能好
- 可维护性好等等
缺点
- 首屏渲染时间长,不利于用户体验
- 不利于SEO,搜索引擎爬取内容时,spa是没有内容的
借鉴了传统的服务端渲染
客户端激活为SPA
同构应用
- 通过服务端渲染首屏直出,解决SPA应用首屏渲染慢以及不利于SEO内容
- 通过客户端渲染接管界面内容交互得到更好的用户体验
- 这种方式通常被称为现代化的服务端渲染,也叫同构渲染
- 这种方式构建的应用称为服务端渲染应用或者是同构应用
相关概念
- 什么是渲染
- 传统的服务端渲染
- 客户端渲染
- 现代化的服务端渲染(同构渲染)
什么是渲染
渲染:把【数据】+ 【模板】拼接到一起,渲染的本质其实就是字符串的解析替换{message :"你好,渲染"}
<h1>{{message}}</h1>
结果 <h1>你好,渲染</h1>
传统的服务端渲染
早期的Web页面渲染都是在服务端进行的 使用node的express实现 index.jsconst express = require('express')
const fs = require('fs')
const template = require('art-template')
const app = express()
app.get('/', (req, res) => {
// 1. 获取页面模板
const templateStr = fs.readFileSync('./index.html', 'utf-8')
// 2. 获取数据
const data = JSON.parse(fs.readFileSync('./data.json', 'utf-8'))
// 3. 渲染:数据 + 模板 = 最终结果
// const html = template.render('hello {{}}',{message:"世界"})
const html = template.render(templateStr, data)
// 4. 把渲染结果发送给客户端
res.send(html)
})
app.get('/about', (req, res) => {
res.end(fs.readFileSync('./about.html'))
})
app.listen(3000, () => console.log('running...'))
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>传统的服务端渲染</title>
</head>
<body>
<h1>传统的服务端渲染</h1>
<h2>{{ title }}</h2>
<ul>
{{ each posts }}
<li>{{ $value.title }}</li>
{{ /each }}
</ul>
</body>
</html>
网页越来越复杂的情况下,存在很多不足
- 前后的代码完全耦合到一起,不利于开发和维护
- 前端没有足够的发挥空间
- 服务端压力大
- 用户体验一般
客户端渲染
传统的服务端渲染缺点- 前后的代码混合在一起
- 服务端压力大
- 体验不够友好
- …
随着客户端Ajax技术的普及
Ajax使得客户端动态获取数据成为可能
服务端渲染工作 -> 来到了客户端
前后端分离使业务更加专注,后端负责数据,前端负责展示,代码更精简,前端负责SPA无刷新页面,体验感好,前端更加独立
前后端分离的问题 - 首屏渲染慢
- 不利于SEO
为什么客户端首屏渲染慢
首屏加载需要一次并行加载,加载网页,加载js脚本是并行加载,相应的数据,如果网络较差,资源加载较慢
为什么客户端不利于SEO
SEO就是搜索引擎中的排名
单页面seo接近为0
- 因为单页面中的内容都是动态生成的,页面内容是ajax请求来的
- 搜索引擎不会等待,只会讲对应的网页解析成字符串,并不包含搜索内容,所以seo不友好,不擅长静态资源的抓取和分析
// 搜索引擎是怎么获取网页内容的?
const http = require('http')
// 通过程序获取指定的网页内容
// http.get('http://localhost:3000/', res => {
http.get('http://localhost:8080/', res => {
let data = ''
res.on('data', chunk => {
data += chunk
})
res.on('end', () => {
console.log(data) //拿到对应的网页字符串形式
})
})
现代化的服务端渲染
客户端渲染的问题:
1.首屏渲染慢
2.不利于SEO
解决方式:现代化的服务端渲染 + 同构渲染
同构渲染 = 后端渲染 + 前端渲染
基于React,Vue 等框架,客户端渲染和服务端渲染相结合
1.在服务端执行一次,用于实现服务器端渲染(首屏直出)
2.在客户端再执行一次,用于接管页面交互核心解决SEO和首屏渲染慢的问题 用于传统服务端渲染的优点,也有客户端渲染的优点
如何实现同构渲染
使用Vue,React等框架的官方解决方案
- 优点:有助于理解原理
- 缺点:需要搭建环境,比较麻烦
使用第三方的解决方案
- React生态的Next.js
- Vue生态的Nuxt.js
- …
同构Nuxt.js体验同构渲染
- 创建文件夹 mkdir ssr
- 生成配置文件 npm init -y
- 安装nuxt.js npm i nuxt
- 修改package中 script,增加 “dev”: “nuxt”
- 增加 pages/index.vue 文件
- 执行 npm run dev 生成 .nuxt文件夹,执行构建过程,可以打开对应的网页
- 安装axios npm i axios
index.vue
<template>
<div>
<h1>{{ title }}</h1>
<nuxt-link to="/about">About</nuxt-link>
<br>
<foo :posts="posts" />
</div>
</template>
<script>
import axios from 'axios'
import Foo from '@/components/Foo'
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'
}
}
}
</script>
<style>
</style>
Foo.vue 设置对应的路由
<template>
<div>
<h1>FooPage</h1>
<ul>
<li
v-for="item in posts"
:key="item.id"
>
<nuxt-link :to="'/article/' + item.id">{{ item.title }}</nuxt-link>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'FooPage',
props: ['posts'],
// async asyncData () {
// console.log('foo asyncData')
// return {
// foo: 'bar'
// }
// }
}
</script>
同构渲染的问题
- 开发条件有限
- 涉及构建设置和部署的更多要求
- 更多的服务端负载
开发条件有限
- 浏览器特定的代码只能在某些生命周期钩子函数中使用
- 一些外部扩展库可以需要特殊处理才能在服务端渲染应用中运行
- 不能在服务端渲染期间操作DOM
- 某些特定代码需要区分运行环境
更多的服务端负载
- 在Node在渲染完整的应用程序,相比仅仅只提供静态文件的服务器 需要大量占用CPU资源
- 如果应用在高流量环境下使用,需要准备相应的服务器负载
- 需要更多的服务端渲染优化工作处理
服务端渲染使用建议
- 首屏渲染速度是否真的重要
- 是否真的需要SEO