Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

从浏览器渲染谈前端开发 #6

Open
abcrun opened this issue Apr 18, 2014 · 0 comments
Open

从浏览器渲染谈前端开发 #6

abcrun opened this issue Apr 18, 2014 · 0 comments
Labels

Comments

@abcrun
Copy link
Owner

abcrun commented Apr 18, 2014

关于浏览器工作原理之前有一篇很出名的文章How Browsers Work: Behind the scenes of modern web browsers,分别用两张图描述了FF和Chrome的渲染过程:

Chrome

Webkit

Firefox

FF

[更新]:关于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:

  1. 不要一条一条地修改DOM的样式。与其这样,还不如预先定义好css的class,然后修改DOM的className。
  2. 把DOM离线后修改。如:使用documentFragment 对象在内存里操作DOM;先把DOM给display:none(有一次reflow),然后你想怎么改就怎么改。比如修改100次,然后再把他显示出来;clone一个DOM结点到内存里,然后想怎么改就怎么改,改完后,和在线的那个的交换一下。
  3. 不要把DOM结点的属性值放在一个循环里当成循环里的变量。不然这会导致大量地读写这个结点的属性。
  4. 尽可能的修改层级比较低的DOM。
  5. 为动画的HTML元件使用fixed或absoult的position,那么修改他们的CSS是不会reflow的。
  6. 千万不要使用table布局。因为可能很小的一个小改动会造成整个table的重新布局。

更多关于网站性能优化,可以参考网站性能优化

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant