1. 服务端渲染
在前后端分离这个概念还没出现的时候,一个团队开发网站的时候是这样来开展工作的:
那个时候的前端开发叫做网页制作,只是简单的开发网站的结构和样式,然后提交给后端,后端进行数据绑定;后端通过jsp、php或asp的语法来实现数据绑定。
这种服务端渲染时,浏览器拿到的既有数据也有样式,可以直接展示出来,但是这样对服务器的压力太大了,并且这个时候的页面不能实现局部刷新的功能;但是服务端渲染有利于SEO优化。
SEO:百度/谷歌浏览器会不定时开启一个爬虫(搜索引擎搜录)爬取网站上的内容,收录的内容越多,网站的权重越大(不同标签的权重不同,所以标签语义化有利于提高网站的权重),但是爬虫只会爬取源代码中存在的信息,例如客户端渲染的技术就会导致源代码里面没有内容,不利于优化。
1) 优点
有利于SEO优化。
2) 缺点
数据全从服务器渲染导致服务器压力很大;
不能实现局部刷新的效果,因为每次修改后都是直接整个页面;
不利于团队协作开发,前端不会jsp等技术,后端不会html、css等技术,配合起来难度很高。
2. 客户端渲染
随着时代的发展,在服务器渲染之后出现了客户端渲染技术,实现了前后端分离,解放了服务器的巨大压力,浏览器首次获取的只有结构和样式,并没有动态绑定的数据;数据是在后面的ajax请求中才返回回来,由客户端自己渲染,完成数据的绑定。
1) 优点
通过AJAX实现局部刷新效果;
团队配合很方便,前后端工作泾渭分明;
服务器压力会小很多。
2) 缺点
客户端渲染是基于js动态绑定的数据,在源代码中没有值,不利于SEO优化。
3. 办分离半不分离
需要SEO的部分服务器渲染,其他地方客户端渲染(再或者第一次服务器渲染,后期操作想要局部刷新,再交给客户端渲染) => SSR服务器渲染; vue->nuxt.js react->next.js
骨架屏技术(服务器):如果服务器承压能力比较好,我们项目的首屏信息是服务器渲染的,其余屏幕信息再滚动条滚动到指定位置的时候,再基于客户端渲染;
骨架屏技术(客户端):第一次从服务器获取回来的只有结构样式,没有数据,此时我们用占位图或者默认的灰色块,先把结构样式撑起来(或者做一个loding的状态,真实数据获取到之后再修改),当页面第一次渲染完成,再从服务器获取数据,进行客户端渲染(真实项目中的数据请求是异步的,这样可以防止数据的请求阻碍GUI的渲染)。
4.白屏
所谓白屏,就是当前设备打开页面,第一步从服务器请求回来HTML,然后渲染,渲染过程中请求CSS资源,生成DOM树、CSSOM树、Render-Tree渲染树,最后整个渲染页面,这个过程是需要时间的,从请求页面到整个所有东西没有完成之前所经历的时间会产生一个白屏的效果。
白屏优化:减少第一次页面渲染时间,包括后续打开时间,这些优化就是项性能优化的关键点。
5. CRP性能节点优化
为了提高性能;Webkit浏览器预测解析:chrome的预加载扫描器html-preload-scanner通过扫描节点中的“src”, “link”等属性,找到外部连接资源后进行预加载,避免了资源加载的等待时间,同样实现了提前加载以及加载和执行分离。
减少DOM树的渲染时间(HTML层级不要太深,注意标签语义化);
减少CSSOM树渲染时间(选择器是从右向左解析,所以尽可能减少使用选择器的层级【less/sass虽然好用但是是个大坑】);
尽早尽快地把CSS下载到客户端(充分利用HTTP多请求并发机制),把请求放在头部;
为了避免白屏,可以进来第一件事,快速生成一套 loding 的渲染树(前端骨架屏);服务器的SSR骨架屏所提高的渲染是避免了客户端再次单独请求数据,而不是样式和结构上的(首屏处理);
把JS放在页面底部以及尽可能使用defer或者async;
减少DOM回流和重绘;
1) 回流repaint和重绘reflow
重绘:元素样式的改变(但宽高、大小、位置不变)
回流:元素的大小或者位置发生了变化(当页面布局和几何信息发生了变化的时候),触发了重新布局,导致渲染树重新计算布局和渲染;
回流一定会触发重绘,但是重绘不一定触发回流。
优化:放弃操作DOM,分离读写,集中式改变。
现代版浏览器存在一个渲染队列机制,对于修改样式的操作会存放到渲染队列中,接着执行代码,如果还是修改代码的继续添加进去(只要不是获取元素样式直接无视),直到代码是获取元素样式或者执行结束为止,最后立即把队列中的样式统一进行渲染,最后只引发一次回流重绘。
box.style.width = '200px';
box.style.height = '200px';
// 这样只触发一次回流
box.style.width = '200px';
box.offsetWidth;
box.style.height = '200px';
// 这样触发两次回流
box.cssText = 'width:200px;height:200px;'
// 这样只触发一次回流
复制代码
缓存布局信息和元素批量修改:
for (let i = 0; i < 10; i++) {
let span = document.createElement('span');
span.innerHTML = i;
document.body.appendChild(span);
}
// 这样会触发十次回流
let frg = document.createDocumentFragment();
for (let i = 0; i < 10; i++) {
let span = document.createElement('span');
span.innerHTML = i;
frg.appendChild(span);
}
document.body.appendChild(frg);
// 这样利用文档碎片只触发一次回流;用字符串拼接也能实现相同效果
复制代码