概述
对于一直从事B/S架构(B/S也是一种C/S架构,只不过C/S自己写显示而B/S有相对统一的显示引擎实现而已)WEB领域的开发人员来说,浏览器Browser再熟悉不过了。不管你是JAVA流还是微软流抑或PHP流,WEB开发新流派。不论你的服务器端采用哪种业务架构,ORACLE数据库还是MSSQL,站在用户的角度思考,这个才是他们直接能接触到的,前端的用户体验给了用户直观的印象,投其所好,我们也总少不了要跟它打交道,很多问题的根源皆来源于此,了解一下其内部执行原理,也许对我们的开发工作会事半功倍,从一位纯粹的开发人员到一位技术领域的专家,也许就在于这些细节中。
本文讨论仅限HTML/CSS类与浏览器显示相关的知识。
不包括javascript浏览器引擎。
不包括客户端与服务器端HTTP通信。
不包括服务器端处理流程部分。
浏览器种类
我们现在经常使用的主要有5种浏览器,Internet Explorer,Firefox,Safari,Chrome跟Opera,包含了市面上3种主流的浏览器网页排版引擎,WebKi(chrome,safari,opera),Gecko(Mozilla,Firefox 等使用的排版引擎)和Trident(也称为MSHTML,IE 使用的排版引擎)。(详见http://www.cnblogs.com/liuzijing688/archive/2008/05/18/1201755.html),大家可以跑一下您所使用的浏览器跑分情况http://html5test.com/。其中Firefox,Chrome ,Safari三款浏览器部分源代码是开源的,一些分析工作正式基于其源码进行的分析。顺便说一句, Chrome等开源浏览器市场中所占的份额越来越高(见http://www.w3schools.com/browsers/browsers_stats.asp)(ie6使用情况http://www.ie6countdown.com/), HTML5前端开发利器的推出,HTML支持标准的逐渐统一,IE6(7,8)等低版本的逐渐淘汰,也许往后针对CSS HACK等兼容性场景的需求会越来越少,专注于实现而不是专注于兼容,提高我们的效率,体现思想核心价值体现,这才是开发人员真正该干的事。站在用户的角度来思考,只是稍微改变一下操作方式换来的是真正的产品易用性与安全性的提升,也是一件好事,希望往后的产品开发都只针对IE9以上版本。
浏览器的主要职责
浏览器,我们天天在用,可是如果哪天面试一个WEB领域的开发,要你说出他的职责,未必人人都能一下子清楚的表述出来。我觉得浏览器的首要功能就是把用户想要的各种形式WEB资源确认无误的显示出来,通常我们见到的资源格式主要是HTML,当然还包括PDF,图片,视频等,资源的定位通过URI来实现(Uniform resource Identifier)。
W3C (World Wide Web Consortium) 组织制定了一套HTML/CSS规范,清楚的描述了浏览器如何解释HTML文件以及如何去显示它,W3C 也是WEB领域标准协议的制定组织。目前我们常见的HTML主要为 HTML4.01跟XHTML1.0,由1999年推出(http://www.w3.org/TR/html401/)。 HTML5 规范现在仍处于发展阶段,虽然已接近尾声且各大主流浏览器都有所支持,但仍不是很完善。目前CSS也主要是CSS2.0((http://www.w3.org/TR/CSS2/), 随着时间的推移,硬件的发展,软件行业的进步,HTML5/CSS3黄金组合一定会流行起来的。同样,CSS版本3进行中。以前的浏览器市场是百花争艳,百家齐鸣,往往只支持大部分的规范内容同时还在发展各自的拓展,这对于WEB开发人员和最终用户来说带来了严重的兼容性问题。幸好,现如今大多数的浏览器渐渐的修正了这一错误行为。
各大浏览器之间有很多共同点,其中公共的界面元素有:
从浏览器界面上来看,没有相关的规范竟然能做到如此的一致,确实很奇怪。这正是各大浏览器厂商多年来相互的模仿导致的。HTML5协议并未约束浏览器要有哪些界面元素,只是列出了一些常用的,比如地址栏,状态栏,工具栏。当然各浏览器都有一些各自的特性,如firefox的下载管理器。更多的介绍起参见以后的Browser User interface(浏览器界面元素)章节,此处不再累牍。
上面说了我们看到的浏览器大体情况,接下来再谈谈浏览器的主要组件有哪些,相互间的关系是怎样的。
浏览器的基础架构
需要注意的是,与其它浏览器不同chrome使用多个渲染引擎实例,每个Tab页一个,即每个Tab都是一个独立进程。
渲染过程
用户请求的HTML文本(text/html)通过浏览器的网络层到达渲染引擎后,渲染工作开始。每次渲染文档通常不会超过8K的数据块,其中基础的渲染流程图如下:
详细流程图
渲染引擎首先解析HTML文档,转换为一棵DOM树,此为第一步。接下来不管是内联式,外联式还是嵌入式引入的CSS样式也会被解析,同时生成另外一棵用于渲染DOM树的树-渲染树(render tree) ,渲染树包含带有颜色,尺寸等显示属性的矩形,这些矩形的顺序与显示顺序基本一致。然后就是对渲染树的每个节点进行布局处理,确定其在屏幕上的显示位置。最后就是遍历渲染树并用上一章提到的UI后端层将每一个节点绘制出来。
以上步骤是一个渐进的过程,为了提高用户体验,渲染引擎试图尽可能快的把结果显示给最终用户。它不会等到所有HTML都被解析完才创建并布局渲染树。它会在从网络层获取文档内容的同时把已经接收到的局部内容先展示出来。
DOM树
DOM对于前端JAVASCRIPT开发人员来说也许再熟悉不过了,DOM全称为Document Object Model,即我们所说的文档对象模型。我们可以把它看做是HTML元素对外的接口,有了这些接口javascript开发人员才能够实现复杂的页面功能。DOM树的根节点是Document对象。DOM也是有规范的,可见 http://www.w3.org/DOM/DOMTR。与XML解析器不同的是,HTML相对来说比较宽松,即使不标准的书写方式也会解析出来,不会抛出解析异常之类的错误。
浏览器利用HTML解析器,分析接收到的HTML文本构件出dom object添加到dom树相应位置上。解析的时候会利用DTD(Document Type Definition)规范描述,DTD中包含了所有允许的元素(element)以及这些元素的属性(attribute),以及元素之间可能的层次关系。市面上我们看到很多类型的DTD,那是为了兼容以前的书写的HTML文档,目前标准推荐的DTD规范定义可见http://www.w3.org/TR/html4/strict.dtd,解析HTML正是基于此规范,上头列举了支持的元素类型,元素的属性以及事件等信息。
所有HTML引用的外部资源默认都是异步加载的,即解析与下载资源同时进行,但由于脚本资源(.js)在解析过程中就有可能运行,如document.write之类的,所以默认脚本资源加载的时候是同步进行的,除非添加了defer或者asyn之类的属性。CSS由于不会更改DOM对象的结构,其资源的加载是异步的。这样就又会产生一个问题,譬如 然后