什么是服务端渲染
我们的网页都是由代码组成的,代码就是字符串
,服务期会把浏览器请求的网页,按照字符串格式发送给浏览器,然后浏览器解析这些字符串,我们就能看到网页了。
现在的网页很多都是动态页面,也就是页面的数据会随着用户不同的操作,而进行不同数据的替换,那么这个替换数据的过程,就可以称之为渲染。
这个渲染过程放在浏览器这里进行,就叫做浏览器渲染,常见的有Ajax请求,异步等。
当这个过程放在服务器上完成的时候,就叫做服务端渲染。
举个栗子🌰:
<div>
{{$value}}
</div>
上面代码中如果是浏览器端渲染
,那么服务器会把完整的,带有花括号的字符串发送给浏览器,然后浏览器解析道{{$value}}
的时候,会去绑定的数据当中找是什么数据,然后把数据放到<div>
标签中,然后解析成下面的样子
<div>
hello world
</div>
最终再解析上面的html,完成网页渲染。
如果是服务器端渲染
,那么浏览器在发送请求之后,服务器会根据请求,找到对应的页面,先把页面转换成字符串
,然后利用模版引擎,对
{{$value}}
进行替换,替换为hello world之后,再把替换好的字符串,发送给浏览器,这个时候浏览器就会直接解析数据已经被替换好的页面
为什么要使用服务端渲染
服务端渲染利于SEO搜索优化,应为数据都是解析好的,直接交给了浏览器,那爬虫在抓取我们网页信息的时候,就非常好抓,直接摆在明面上。
服务端渲染过程
下方是基于node进行展示的渲染过程
- 启动服务器监听端口
- 页面发送请求,服务器接收到到之后,根据url,找到对应的相应区域
- 读取需要发送给浏览器的页面
- 把页面的内容转化成字符串
- 利用模版引擎,对字符串中需要替换的数据进行替换(替换的数据可以根据需要,去读取不同的文件)
- 将完成替换的字符串发送给浏览器
//node核心模块引入
let http = require('http');
let url = require('url');
let fs = require('fs');
//模版引擎引入
let template = require('art-template');
//页面数据存放数组
let comments = [
{
name: 'Tony',
age: '18',
sex: 'male',
date: '2020-04-11'
},
{
name: 'Lucy',
age: '18',
sex: 'female',
date: '2020-04-11'
},
{
name: 'Sun',
age: '18',
sex: 'female',
date: '2020-04-11'
}
]
/**
* @param {object} req 浏览器发送过来的请求参数
* @param {object} res 服务器对相应请求事件参数
*/
http
.createServer(function (req, res) {
/**
*
* 通过url核心模块的parse方法,可以解析浏览器端请求的地址,适用于get请求解析参数
* 该方法可直接解析成json格式
* eg:http://127.0.0.1:3000/submint?name=Tony&age=18&sxe=male
* Url{
* protocol: 'http:',
* slashes: true,
* auth: null,
* host: '127.0.0.1:3000',
* port: '3000',
* hostname: '127.0.0.1',
* hash: null,
* search: '?name=Tony&age=18',
* query: {name: Tony, age: 18, sex: male},
* pathname: '/submint',
* path: '/submint?name=Tony&age=18&sxe=male',
* href: 'http://127.0.0.1:3000/submint?name=Tony&age=18&sxe=male'
* }
*/
let parseObj = url.parse(req.url, true);
//拿到解析完成后的路径名称
let pathname = parseObj.pathname;
if (pathname = '/') {
//读取文件
fs.readFile('/view/index.html', function (err, data) {
if (err) {
return res.end('404 Not Found.')
}
//使用template模版引擎,对刚读取到的 html ‘字符串’进行字符串替换
let htmlStr = template.render(data.toString(), {
comments: comments
})
res.end(htmlStr);
})
} else if (pathname.indexOf('/public/') === 0) {
fs.readFile('.' + pathname, function (err, data) {
if (err) {
return res.end('404 Not Found.');
}
res.end(data);
})
}else if (pathname === 'submint') {
//获取上面从地址中解析出来的参数
let comment = parseObj.query
comment.dataTime = new Date;
//将提交的数据放入数组,完成了数据提交
comments.unshift(comment);
/**
* 设置重定向
* 1.状态码设置成302,临时重定向
* statusCod
* 2.在相应头中通过Location告诉客户端往哪重定向
* setHeader
* 如果客户端收到服务器的相应状态码是302,会自动去Location相应头中找Location
* 这时便可以看到客户端跳转
*/
res.statusCode = 302;
res.setHeader('Location', '/');
res.end();
} else {
fs.readFile('./views/404.html', function (err, data) {
if (err) {
return res.end('404 Not Found.')
}
res.end(data)
})
}
})
/**
* 监听端口
* @param {number} 服务器监听的端口号
* @param {function} 监听成功后执行的函数
*/
.listen(3000, function () {
console.log('服务器启动成功');
})
Html部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div>
{{each comments}}
<ul>
<li>姓名:{{$value.name}}</li>
<li>年龄:{{$value.age}}</li>
<li>性别:{{$value.sex}}</li>
<li>提交日期:{{$value.date}}</li>
</ul>
{{/comments}}
</div>
</body>
</html>
上面代码是帮助理解服务端渲染过程,并不严谨。