小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
概述
现在主流的单应用开发,前端开发构建打包成静态资源文件,然后上传部署到 nginx,或者 tomcat。当用户访问的网站的时候,首先会加载html模板文件,然后再去加载js文件,由js进行主要的执行渲染,这类称为“浏览器渲染”,简称“CSR”。它的弊端主要是,不利于SEO优化、首页渲染白屏时间等。相对而言,服务端渲染(SSR),则直接返回的是html文件进行渲染,白屏时间更短,也利于SEO,但是它增加了服务器的负担。
两种渲染方式,放到指标上进行衡量的话,是这样的: CSR无法提前FMP时间,即使它能够通过骨架屏、甚至一个loading来提前FP、FCP时间而减少白屏时间。而SSR直接将FMP提前到js加载前,毕竟它返回的是渲染好的html文件,不需等待加载js进行主要内容的渲染解析。
知识点:
- FP:首帧绘制的时间
- FCP:首次内容绘制时间
- FMP:首次有效绘制,网站最有意义的那块内容,比如,相对于电商网站,可能就是商品内容。
所以,三个指标触发的时间顺序是:FP -> FCP - > FMP。
知道了SSR的必要性,那下面看个最简单的SSR渲染。
模板渲染例子
用node实现一个渲染json文件数据的index模板网页。例子简单,直接上代码:
// json数据文件: data.json
['小张', '小明', '小红']
<!-- 模板文件 index.html -->
<!doctype html>
<html>
<head></head>
<body>
<h1>我的朋友</h1>
<!-- %:会被替换的内容 -->
<ul><li>%</li></ul>
</body>
</html>
// node服务,进行ssr
const http = require('http')
const fs = require('fs')
const getTemplate = (data, res) => {
// 读取模板文件
fs.readFile('./index.html', (err, data) => {
if(err) return res.end('server error')
const temp = data.toString()
// 替换模板数据
const html = temp.replace('%', data.join('</li><li>'))
// 写响应头,返回数据
res.writeHead(200, {'Content-Type': 'text/html'})
res.end(html)
})
}
const renderTemplate = (res) => {
// 读取json数据
fs.readFile('./data.json', (err, data) => {
if(err) return res.end('server error')
getTemplate(JSON.parse(data.toString()), res)
})
}
// 创建node服务
const server = http.createServer(function(req, res){
renderTemplate(res)
}).listen(80, '127.0.0.1')
这就是最简单的SSR服务端渲染了,本质上都是如此,进行模板字符串替换。只是当你更复杂时,需要定义一套自己的模板渲染规则,而不能进行简单的替换。
总结
服务端模板引擎很多,比如Pug、EJS、Mustache等,当然如果技术栈是Vue,则可以使用Nuxt.js,它是一个基于Vue生态更高层的框架用于处理服务端渲染,方便服务端和浏览器端共用一套组件。当然如果是react技术栈,可以采用next.js框架。