在浏览器整个渲染过程中,资源获取这一过程无疑是最消耗时间的,同时浏览器内核也通过了各种方式去减少事件,比如资源加载多线程、并发下载资源、DNS预处理、缓存资源、缓存网络请求等。下面介绍从用户输入URL到得到资源发生了什么,但是这个过程也是粗略的解读,对于详细的过程以及高性能的部分要去,相信《http 权威指南》可能会给你满意的答案。
在浏览器中对于每一种资源比如HTML、js、CSS、图片、视频、SVG、字体等资源都有一种内部类来表示管理这种资源,比如js就是cacheScript类进行管理,同时每一种类斗鱼一种资源加载器相对应,比如cacheScript就是ScriptLoader加载器。
当一个URL请求的时候,会根据URL请求的资源类型,创建相应的管理类,然后交给相应的资源加载器去加载资源。
各种资源加载器都会去调用资源缓存机制的加载器,这个资源缓存的加载器作用就是检测资源是否在资源池中存在。这个资源池实际是一个html文档来管理了缓存的资源,在这个资源加载阶段所有的资源缓存是缓存在内存中的不是磁盘中;同时每一种被缓存的资源都会通过唯一的URL进行标识,所以说如果出现两个资源一样但是URL不一样的资源在缓存池中核能都存在;这个资源池也不是无限大的通过LRU(最近最少使用)算法对资源进行管理,由于缓存池具有全局性,所以打开的网页过多的话可能导致最早的资源被删除。
当使用URL对资源池中进行查找发现没有这个资源,那么就会将这个URL传递给网络栈进行资源的加载操作,如果有这个资源,也不会马上返回使用它,因为可能这个资源“过期”,所以如果查找到存在这个资源的缓存的话,则请求网络栈给服务器发送一个确认是否使用缓存信息的请求,如果服务器返回304不需要更新可以使用,那么资源缓存加载器则直接从内存中取出资源返回,否则的话,将会重新对资源进行请求,请求得到的资源覆盖缓存中资源。这就是资源池的失效机制。
也就是说,如果一个资源,我非常确定这个资源每次请求都会重新请求的不会从缓存中判断的话,一般在请求URL尾部加一个随机数字,这样在缓存中匹配不到就直接请求了,不用担心存在相同的资源还要让浏览器确认增加网络负载。
还存在一个问题就是,当我请求的是js文件的额时候,会阻塞DOM树主进程的渲染过程,导致的直接后果是后面的资源无法准时请求加载,导致浪费时间。为了解决这个问题,chrome浏览器发现请求资源是、非异步的JS或其他阻塞渲染进程的资源的时候,加载js文件的同时,会单独开一个线程,浏览网页中后面的出现的URL提取出来进行资源的加载,同时chrome对资源的加载支持多进程机制,并且网络栈可以并发的下载资源。
进入网络栈模块进行资源网络下载,根据URL中的scheme创建相应的资源请求,然后从cookie中提取与这个url相关的cookie信息。Cookie分为两种,一种是会话型的,也就是说,只保存在内存中,浏览器退出的时候将消失。一种是持续型的,将cookie信息保存到本地,在有效期内,只要内次访问这个页面的话将提取cookie发送给服务器,服务器可以有效的跟踪用户的行为。
在htpp中添加cookie以后进入http事务链接阶段,这个阶段分为三种情况:
第一种就是上次该网页请求的时候得到的http回复要求将这个请求写入的本地磁盘中,可以设置失效时间,所以说,如果在磁盘中存在的话则直接将回复信息返回不需要创建链接。
第二种情况是,没有在磁盘中,但是已经创建了这个url的请求链接,那么只是静静的等待回复。
第三种情况就是要重新建立请求链接了,但是在建立请求链接之前,是要进行DNS解析的,DNS解析相比之嫌可能很耗时间,所以chrome会使用DNS预解析的优化方式进行处理。
(1)默认情况下,当用户正在浏览这个网页的时候会将这个网页中所有的地址提取出来,浏览器单独卡一个线程对这些地址进行DNS预解析。这种方式显然对于网页重定向的地址来说是不太实用的。
(2)程序员可以通过<link rel=”dns-prefetch” href=””/>方式显示的进行定义预解析的地址,这种方式可以提前发现重定向的问题提前解决。但是如果不是淘宝这种大企业有多个域名的情况下没有必要使用。如下淘宝网的预解析:
<link rel="dns-prefetch" href="//g.alicdn.com" />
<link rel="dns-prefetch" href="//img.alicdn.com" />
<link rel="dns-prefetch" href="//tce.alicdn.com" />
<link rel="dns-prefetch" href="//gm.mmstat.com" />
<link rel="dns-prefetch" href="//log.mmstat.com" />
<link rel="dns-prefetch" href="//tui.taobao.com" />
<link rel="dns-prefetch" href="//ald.taobao.com" />
<link rel="dns-prefetch" href="//gw.alicdn.com" />
<link rel="dns-prefetch" href="//atanx.alicdn.com"/>
<link rel="dns-prefetch" href="//dfhs.tanx.com"/>
<link rel="dns-prefetch" href="//ecpm.tanx.com" />
<link rel="dns-prefetch" href="//res.mmstat.com" />
<link rel="dns-prefetch" href="//log.mmstat.com" />
(3)当用户在地址栏输入地址,在回车之前就已经开始预解析了。最后是创建tcp链接开始请求信息,应该尽可能的少的建立请求的链接数量,这样显然是提高性能的,可以通过将资源合并压缩的方式减小资源的大小和请求的数量。