Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Inside the Browser 
浏览器渲染原理 
张立理 
otakustay@gmail.com
WHY? 
HTML布局无处不在已经不局限与浏览器
Summary 
 浏览器的工作过程 
 资源下载 
 HTML解析 
 CSS计算 
 布局 
 渲染 
 浏览器对细节的具体优化手段 
 Firefox 
 Webkit / Chrome
How?
下载 
一个HTTP库能够搞定? 
 DNSClient 
 WebRequest 
 NetworkStream 
 HTMLParser 
 够了吗? 
不仅仅一个文件! 
 <script src… 
 <link href...
下载 
 <head>中的<script>和<link> 
 服务器端Response.Flush() 
 <body>中的<script> 
 document.write 
 new Image().src = … 
 defe...
下载 
 资源优先级 
 link[rel=stylesheet] / script 
 object / img / iframe 
 link[rel=prefetch] 
 脚本依赖 
 下载阻塞VS 执行阻塞 
 并行度 ...
下载 
 Socket重用 
 Connection: keep-alive 
 Content-Length 
 Transfer-Encoding: chucked 
 正确性保证 
 Content-MD5 
 断点续传 
...
下载 
 BS的精髓– 缓存 
 验证型缓存 
 Last-Modified & If-Modified-Since / If-Unmodified-Since 
 ETag & If-Match / If-None-Match 
 ...
下载 
 缓存年龄计算 
 age_value – Age响应头的值 
 date_value – Date响应头的值 
 request_time – 发起请求的本地时间 
 response_time – 收到响应的本地时间 
...
下载 
 缓存过期计算 
 freshness_lifetime = 
 使用max-age时为max-age的秒数 
 使用Expires时为(Expires - Date) 
 response_is_fresh = (fresh...
下载 
 输入– 资源URI 
 输出– HTML字符流 
 HTTP的超链接特性注定资源之间有关联的依赖 
 外部资源位置、类型不同影响下载时机 
 Response.Flush对下载的影响 
 缓存机制复杂但完善
解析 
• Token List 
• Normalized 
Token List 
•DOM Tree 
Demo
解析 
 只有这些? document.write
解析 
 输入– HTML字符流 
 输出– DOM Tree 
 HTML无法用自顶向下或自底向上的方法解析 
 过程– 序列化-> 转义处理-> 标签匹配 
 脚本执行会增加解析的回溯 
 DOM操作回溯至标签匹配过程 
 d...
CSS计算 
 元素– 匹配样式 
 div>div>div>div>div…>div { color: red; } 
 dom.parentNode istanceof HTMLDivElement && 
div.parentNod...
CSS计算 
 Webkit – 特定条件下样式共享 
 鼠标状态(:hover / down / clicked)相同 
 没有id 
 标签名相同 
 class名称相同 
 attribute均相同 
 链接状态(:link...
CSS计算 
 Firefox 
 Rule Tree + Style Context Tree 
Style sheets & 
rules 
Rule tree 
Style context 
tree 
DEMO 
https://d...
CSS计算 
 Map 
 { string: [ selector, selector, … ] } 
 以最右选择器为依据 
 匹配 
 查找id map 
 查找class map 
 查找tag map 
 确定sele...
CSS计算 
 #title { … } 
 p.error { … } 
 input[type=radio] { … } 
 #nav li~li a { … } 
 .fix-clear * { … } 
 <div clas...
CSS计算 
 CSS层级(优先级) 
 来源层级 
 浏览器UA样式 
 用户样式 
 作者样式 
 作者样式+ !important 
 用户样式+ !important 
 样式层级 
 1,1,1,1算法 
 inl...
CSS计算 
DOM Tree 
document 
html 
head 
meta title 
body 
h1 p 
Render Tree 
html 
viewport 
scroll 
block 
body 
block 
h1...
CSS计算 
 元素没有渲染对象 
 head / meta / script 
 元素有多个渲染对象 
 html / li 
 select / input[type=file] 
 通过CSS改变渲染对象 
 display...
CSS计算 
 输入– DOM Tree 
 输出– Render Tree 
 目标– 内存优化、匹配效率优化 
 方法– 样式共享、选择器索引 
 DOM Tree !== Render Tree
布局 
 流布局 
 display: inline / inline-block / block 
 float: left / right 
 clear: left / right / both 
 position: stat...
布局 
 table布局 
 display: table / inline-table / table-row-group / table-header- 
group / table-footer-group / table-row /...
布局 
 坐标系– 左上角为0,0点,右|下为正坐标 
 布局是递归过程 
 流布局可自左向右、自上而下进行,流中靠后的元素不会影响 
流中靠前的元素的布局(无回溯) 
 table布局需要回溯才能够完成(知道每一个单元格的大小,才 
...
布局 
 全局Reflow 
 整个Render Tree全部重新计算布局 
 全局布局样式变更– body { font-size: 12px; } / 添加新样式表 
 窗口大小变化 
 局部Reflow 
 仅标识为needL...
布局 
 同步Reflow 
 全局Reflow通常同步进行 
 读取offsetWidth/offsetHeight等属性 
 异步Reflow 
 局部Reflow通常异步进行 
 FireFox:Reflow任务进入线程Que...
布局 
 父元素确定自己的宽度 
 开始遍历子元素 
 指定子元素渲染器的x/y属性 
 判断子元素是否需要布局,调用layout函数 
 累计所有子元素的width/padding/border/margin,计算自己 
的宽度 
...
布局 
 文字布局 
 text-align: justified 
 white-space: nowrap / pre / pre-wrap 
 overflow: hidden / visible 
 换行计算 
 每行一个l...
布局 
 有流式布局和table布局2种 
 table布局需要回溯,流式布局通常不需要 
 Reflow的分类 
 触发类型上– 全局和局部 
 执行类型上– 同步和异步 
 布局过程递归进行 
 坐标系为左上角0,0点,右、下...
渲染 
 transform / filter / z-index / color / visibility… 
 Reflow VS Repaint – display: none VS visibility: hidden 
 渲染顺...
渲染 
 Firefox – display list 
 找到Render Tree中在指定Repaint区域内的渲染对象 
 Render Tree的渲染对象经Stacking Order排序后生成 
 [background(A)...
渲染 
 Webkit – rectangle storage 
 Repaint前先将原有矩形内容保存为位图 
 计算重绘后的矩形内容的位图 
 比对2个位图,仅绘制差异部分 
 Chrome的Repaint在独立进程中 
 进程...
Upcoming SlideShare
Loading in …5
×

Inside the browser

621 views

Published on

Inside the browser - how browser work when you enter an URL in the address bar

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

Inside the browser

  1. 1. Inside the Browser 浏览器渲染原理 张立理 otakustay@gmail.com
  2. 2. WHY? HTML布局无处不在已经不局限与浏览器
  3. 3. Summary  浏览器的工作过程  资源下载  HTML解析  CSS计算  布局  渲染  浏览器对细节的具体优化手段  Firefox  Webkit / Chrome
  4. 4. How?
  5. 5. 下载 一个HTTP库能够搞定?  DNSClient  WebRequest  NetworkStream  HTMLParser  够了吗? 不仅仅一个文件!  <script src…  <link href…  <img src…  <iframe src…  何时开始下载它们?
  6. 6. 下载  <head>中的<script>和<link>  服务器端Response.Flush()  <body>中的<script>  document.write  new Image().src = …  defer VS async
  7. 7. 下载  资源优先级  link[rel=stylesheet] / script  object / img / iframe  link[rel=prefetch]  脚本依赖  下载阻塞VS 执行阻塞  并行度  服务器压力VS 客户端效率 http://www.otakustay.com/browser-strategy-loading-external-resource/
  8. 8. 下载  Socket重用  Connection: keep-alive  Content-Length  Transfer-Encoding: chucked  正确性保证  Content-MD5  断点续传  Accept-Range  Content-Range
  9. 9. 下载  BS的精髓– 缓存  验证型缓存  Last-Modified & If-Modified-Since / If-Unmodified-Since  ETag & If-Match / If-None-Match  If-Range  非验证型缓存  Cache-Control  Expires  缓存失效  Vary / Via / Date / Age http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
  10. 10. 下载  缓存年龄计算  age_value – Age响应头的值  date_value – Date响应头的值  request_time – 发起请求的本地时间  response_time – 收到响应的本地时间  now – 当前本地时间  apparent_age = max(0, response_time - date_value);  corrected_received_age = max(apparent_age, age_value);  response_delay = response_time - request_time;  corrected_initial_age = corrected_received_age + response_delay;  resident_time = now - response_time;  current_age = corrected_initial_age + resident_time;
  11. 11. 下载  缓存过期计算  freshness_lifetime =  使用max-age时为max-age的秒数  使用Expires时为(Expires - Date)  response_is_fresh = (freshness_lifetime > current_age)  max-age=0 VS no-cache  max-age=0 – 要求浏览器向服务器验证缓存  no-cache – 要求浏览器向服务器请求全新内容
  12. 12. 下载  输入– 资源URI  输出– HTML字符流  HTTP的超链接特性注定资源之间有关联的依赖  外部资源位置、类型不同影响下载时机  Response.Flush对下载的影响  缓存机制复杂但完善
  13. 13. 解析 • Token List • Normalized Token List •DOM Tree Demo
  14. 14. 解析  只有这些? document.write
  15. 15. 解析  输入– HTML字符流  输出– DOM Tree  HTML无法用自顶向下或自底向上的方法解析  过程– 序列化-> 转义处理-> 标签匹配  脚本执行会增加解析的回溯  DOM操作回溯至标签匹配过程  document.write回溯至序列化过程
  16. 16. CSS计算  元素– 匹配样式  div>div>div>div>div…>div { color: red; }  dom.parentNode istanceof HTMLDivElement && div.parentNode.parentNode instanceof HTMLDivElement && div.parentNode.parentNode.parentNode instanceof …  问题  DOM很大,对内存造成压力  每个元素生成一个StyleObject浪费内存  查找元素匹配的样式消耗时间和CPU  如果是div div div div … div呢?
  17. 17. CSS计算  Webkit – 特定条件下样式共享  鼠标状态(:hover / down / clicked)相同  没有id  标签名相同  class名称相同  attribute均相同  链接状态(:link / :visited)相同  聚焦状态(:active / :focus)相同  不能匹配属性选择器  没有内联样式  没有兄弟选择器(+ / :first-child / :last-child / …)
  18. 18. CSS计算  Firefox  Rule Tree + Style Context Tree Style sheets & rules Rule tree Style context tree DEMO https://developer.mozilla.org/en/Style_System_Overview
  19. 19. CSS计算  Map  { string: [ selector, selector, … ] }  以最右选择器为依据  匹配  查找id map  查找class map  查找tag map  确定selector完全匹配  遍历general map
  20. 20. CSS计算  #title { … }  p.error { … }  input[type=radio] { … }  #nav li~li a { … }  .fix-clear * { … }  <div class=“fix-clear”> <span id=“title” class=“error”>Erorr Occurred!</span> </div>
  21. 21. CSS计算  CSS层级(优先级)  来源层级  浏览器UA样式  用户样式  作者样式  作者样式+ !important  用户样式+ !important  样式层级  1,1,1,1算法  inline(0/1), count(id), count(attribute), count(tag)  ul#nav ol li.red
  22. 22. CSS计算 DOM Tree document html head meta title body h1 p Render Tree html viewport scroll block body block h1 block text p block text https://developer.mozilla.org/en/Mozilla_Style_System_Documentation
  23. 23. CSS计算  元素没有渲染对象  head / meta / script  元素有多个渲染对象  html / li  select / input[type=file]  通过CSS改变渲染对象  display: none  ::before / ::after
  24. 24. CSS计算  输入– DOM Tree  输出– Render Tree  目标– 内存优化、匹配效率优化  方法– 样式共享、选择器索引  DOM Tree !== Render Tree
  25. 25. 布局  流布局  display: inline / inline-block / block  float: left / right  clear: left / right / both  position: static / relative / absolute / fixed  HTML三条流  文档流、浮动流、定位流  其它因素  display: list-item  display: run-in http://www.w3.org/TR/css3-box/#the-lsquo
  26. 26. 布局  table布局  display: table / inline-table / table-row-group / table-header- group / table-footer-group / table-row / table-column- group / table-column / table-cell / table-caption  div VS table – 流布局VS table布局
  27. 27. 布局  坐标系– 左上角为0,0点,右|下为正坐标  布局是递归过程  流布局可自左向右、自上而下进行,流中靠后的元素不会影响 流中靠前的元素的布局(无回溯)  table布局需要回溯才能够完成(知道每一个单元格的大小,才 能完成整个布局)  反对table布局的原因– 回溯对渲染的影响 DEMO
  28. 28. 布局  全局Reflow  整个Render Tree全部重新计算布局  全局布局样式变更– body { font-size: 12px; } / 添加新样式表  窗口大小变化  局部Reflow  仅标识为needLayout的渲染元素计算布局  Render Tree中插入新的渲染元素  渲染元素属性变化  Reflow会引起另一个Reflow – Reflow导致滚动条位置变化
  29. 29. 布局  同步Reflow  全局Reflow通常同步进行  读取offsetWidth/offsetHeight等属性  异步Reflow  局部Reflow通常异步进行  FireFox:Reflow任务进入线程Queue,任务调度器负责执行  Webkit:定时器遍历Render Tree,布局所有needLayout对象  Reflow任务可合并,一次脚本执行过程中多个样式修改仅做一 次Reflow,但是有阀值 DEMO
  30. 30. 布局  父元素确定自己的宽度  开始遍历子元素  指定子元素渲染器的x/y属性  判断子元素是否需要布局,调用layout函数  累计所有子元素的width/padding/border/margin,计算自己 的宽度  同时考虑availWidth / sizing-box / min-width / max-width  将needLayout改为false
  31. 31. 布局  文字布局  text-align: justified  white-space: nowrap / pre / pre-wrap  overflow: hidden / visible  换行计算  每行一个line-box负责渲染  当需要换行时,通知父元素,父元素创建新的line-box并重新布局  换行算法与文化相关  英文单词不能断开  中文标点不能在行首
  32. 32. 布局  有流式布局和table布局2种  table布局需要回溯,流式布局通常不需要  Reflow的分类  触发类型上– 全局和局部  执行类型上– 同步和异步  布局过程递归进行  坐标系为左上角0,0点,右、下为正方向
  33. 33. 渲染  transform / filter / z-index / color / visibility…  Reflow VS Repaint – display: none VS visibility: hidden  渲染顺序(CSS2):  background color  background image  border  children  outline http://www.w3.org/TR/CSS21/zindex.html
  34. 34. 渲染  Firefox – display list  找到Render Tree中在指定Repaint区域内的渲染对象  Render Tree的渲染对象经Stacking Order排序后生成  [background(A), border(A), border(B), outline(A)]  避免多次遍历Render Tree  [background(A, B), border(A, B), outline(A, B)]  完全不可见的元素不可被加到display list中  display: none;  opacity: 0;
  35. 35. 渲染  Webkit – rectangle storage  Repaint前先将原有矩形内容保存为位图  计算重绘后的矩形内容的位图  比对2个位图,仅绘制差异部分  Chrome的Repaint在独立进程中  进程间通过事件进行传递和响应  绘制监听器负责监听重绘事件,把事件委托给Render Tree的根  Repaint永远从Render Tree的根开始,遍历并找到需要重绘的节 点,对节点调用重绘(递归至叶子节点)

×