Web浏览器的主要功能是展示网页资源,即请求服务器并将结果展示在窗口中。工作原理大概如下:
地址栏输入URL
浏览器根据输入的URL查找域名的IP地址,DNS查找过程如下:
- 浏览器缓存——浏览器会缓存DNS记录一段时间,不同浏览器默认缓存时间不一样,IE默认为30分钟,Firefox默认是1分钟。
- 系统缓存——如果在浏览器缓存里没有找到需要的缓存记录,浏览器会到系统缓存中查找。
- 路由器缓存——如果系统缓存中也没有,就会将请求发给路由器并在其DNS缓存中查找。
- ISP缓存——如果路由器缓存中没有,就会将请求发给ISP的DNS缓存服务器并在其记录中查找。
- 访问根域名服务器——如果ISP缓存中没有,就会由ISP向根域名服务器进行递归搜索,查找到对应记录并返回。
浏览器与对应Web服务器建立TCP连接,并发送HTTP请求,Web服务器接收到请求后进行一系列分析处理(关于HTTP请求响应的详细过程以后再进行剖析)并返回HTML文件。
浏览器解析HTML
浏览器接收到服务器返回的HTML文件,解析<head>标签:
- 关于页面的一些配置标签,例如<title>、<meta>、<base>等,以后再进行剖析,这些会对页面属性进行设置。
- 碰到内联CSS和JS会立即解析执行。
- 碰到外部CSS和JS会并发请求相关资源,然后解析执行。不同浏览器针对同一域的同一时间默认并发连接数会有不同,一般在10个以内。
接着,浏览器开始解析<body>里的内容:
- 碰到需要获取其他地址内容的标签,例如<img>、<script>,会并发请求相关资源。
当HTML解析器遇到<script>标签时,默认必须先执行脚本,然后再恢复文档的解析和渲染。脚本的执行只在默认情况下是同步和阻塞的。<script>标签可以通过defer和async属性来改变脚本的执行方式。使用defer和async属性,可以让浏览器在下载脚本时继续解析和渲染文档。defer属性使浏览器延迟脚本的执行,直到文档的载入和解析完成。async属性使浏览器可以尽快地执行脚本,而不用在下载脚本时阻塞文档解析。如果<script>标签同时拥有这两个属性,同时支持这两者的浏览器会执行async属性并忽略defer属性。延迟脚本会按照他们在文档里的出现顺序来执行,而异步脚本在他们载入后执行,可能会无序执行。
浏览器渲染原理
关于浏览器的渲染原理,这里有篇流传很广很不错的文章——《How browsers work》(英文版,中文翻译版),就不细说了。简要分析几点:
-
浏览器的主要组件
1. 用户界面——包括地址栏、后退/前进按钮、书签目录等,也就是你所看到的除了用来显示你所请求页面的主窗口之外的其他部分。
2. 浏览器引擎——用来查询及操作渲染引擎的接口。
3. 渲染引擎——用来显示请求的内容,例如,如果请求内容为HTML,它负责解析HTML及CSS,并将解析后的结果显示出来。
4. 网络——用来完成网络调用,例如HTTP请求,它具有平台无关的接口,可以在不同平台上工作。
5. UI后端——用来绘制类似组合选择框及对话框等基本组件,具有不特定于某个平台的通用接口,底层使用操作系统的用户接口。
6. JS解释器——用来解释执行JS代码。
7. 数据存储——属于持久层,浏览器需要在硬盘中保存类似cookie的各种数据,HTML5定义了web database技术,这是一种轻量级完整的客户端存储技术。
图1:浏览器主要组件
Chrome为每个Tab分配了各自的渲染引擎实例,每个Tab就是一个独立的进程。
-
reflow和repaint
浏览器渲染过程中经常伴随着reflow和repaint,如果只是改变某个元素的背景色、文字颜色等不影响Dom布局的属性时会引起浏览器进行repaint,相对而言,如果改变影响Dom布局的属性时就会引起浏览器进行reflow,而reflow比repaint开销要大很多,因此应尽量避免。