-
Notifications
You must be signed in to change notification settings - Fork 10
Description
关于浏览器工作原理之前有一篇很出名的文章How Browsers Work: Behind the scenes of modern web browsers,分别用两张图描述了FF和Chrome的渲染过程:
Chrome
Firefox
[更新]:关于Chrome浏览器渲染的详细内容,可参考图解浏览器渲染过程 - 基于Webkit/Blink内核Chrome浏览器
浏览器的渲染对前端有着重要的影响,根据浏览器的渲染原理,为了提高用户体验,我们可以在以下方面多多注意
由于历史的原因,不规范的HTML代码普遍存在,为了保证网页的正常显示,浏览器需要额外对代码进行处理(如标签的闭合,table中元素的缺失等等),尽管如此有时也会出现错误,不规范的代码甚至会成为漏洞被他人攻击,因此在 编写代码时一定要严格规范。
JS线程和渲染线程是互斥的,当遇到JS代码时会阻塞DOM树的构建,尽管FF和Webkit对此做了优化(当遇到脚本时候会预先扫描后面的代码是否有需要加载资源的,如果有则调用Browser进程加载资源,然后在阻塞渲染线程执行脚本),但是从整体而言也会影响用户体验,为了防止这种情况的发生, JS文件放在页面最下面还是必要的,当然也可以给script代码添加defer属性。
当渲染线程遇到CSS样式时,会将其之逐条解析成规则对象,并存放在DocumentRuleSets对象中,便于Node节点构建renderObject计算时使用,renderObject记录着对应Node元素的样式位置等信息,如果元素创建后尚查不到当前元素的样式信息,那么将会影响到元素的展示,因此尽量在DOM节点创建之前添加样式信息,这样不至于再次渲染产生的闪白情况。所以 CSS文件应该放在页面前面
元素的大小位置信息等都记录在renderObject对象中,在计算这些信息时,渲染线程会从DocumentRuleSets对象中查找与当前元素匹配的所有样式规则,并进行排序,最终计算出最终样式,然后不合理的写法将会增加查找和排序的时间,从而影响用户体验,所以在书写CSS代码时一定要注意,这里引用《高性能网站建设进阶指南》一书中的建议:
- 避免使用通配符(包括兄弟选择符,子选择符,后代选择符,属性选择符)
- 不要限定ID选择符,如:ul#idStr
- 不要限定类选择符,如:p.className
- 规则越具体越好
- 避免使用后代选择符
- 避免使用标签-子选择符
- 质疑子选择符的所有用途
- 依靠继承
网页分为框结构和层次结构,页面的渲染也分为软件渲染,软件合成渲染和硬件加速渲染,这些都影响着页面内容(CSS,DOM等)更新时的用户体验,因此 根据产品要求,编写前端代码时考虑网页的层次结构 非常重要,这样可以避免页面不必要的relayout(reflow)。
基本上来说,reflow有如下的几个原因:
Initial。网页初始化的时候。
Incremental。一些Javascript在操作DOM Tree时。
Resize。其些元件的尺寸变了。
StyleChange。如果CSS的属性发生变化了。
Dirty。几个Incremental的reflow发生在同一个frame的子树上。
针对这些问题这里引用:http://coolshell.cn/articles/9666.html 这篇文章中得总结来避免多次reflow:
- 不要一条一条地修改DOM的样式。与其这样,还不如预先定义好css的class,然后修改DOM的className。
- 把DOM离线后修改。如:使用documentFragment 对象在内存里操作DOM;先把DOM给display:none(有一次reflow),然后你想怎么改就怎么改。比如修改100次,然后再把他显示出来;clone一个DOM结点到内存里,然后想怎么改就怎么改,改完后,和在线的那个的交换一下。
- 不要把DOM结点的属性值放在一个循环里当成循环里的变量。不然这会导致大量地读写这个结点的属性。
- 尽可能的修改层级比较低的DOM。
- 为动画的HTML元件使用fixed或absoult的position,那么修改他们的CSS是不会reflow的。
- 千万不要使用table布局。因为可能很小的一个小改动会造成整个table的重新布局。
更多关于网站性能优化,可以参考网站性能优化

