浏览器从输入网址发生的事(前端优化)

监控网页与程序性能

当在浏览器地址栏输入一个网址开始,到最终页面的呈现,浏览器完成了他的工作。我们要优化这个程序呈现的速度,首先就得弄明白这其中都发生了 什么事?

1.处理环节与顺序

这张图大致的描述了浏览器的一系列工作。

2.chrome中的performance属性

在chrome 浏览器的console中输入window.performace会得到下图的内容

  • usedJSHeapSize  js对象占用的内存一定小于totalJSHeapSize
  • totalJSHeapSize  可使用的内存
  • jsHeapSizeLimit  内存大小限制

navigation 对象(描述页面从哪里来)

  • redirectCount  如果有重定向的话,页面通过几次重定向跳转而来
  • type 

    type  取值
    
    0:即 TYPE_NAVIGATENEXT  正常进入的页面(非刷新、非重定向等)
    1:即 TYPE_RELOAD 通过window.location.reload 刷新页面
    2:即 TYPE_BACK_FORWARD  通过浏览器的前进后退按钮
    255:即 TYPE_UNDEFINED 非以上方式进入页面

timing 对象

  • navigationStart 初始化页面,在同一个浏览器上下文中前一个页面unload的时间戳,如果没有前一个页面的unload,则与fetchStart值相等
  • unloadEventStart 前一个页面的unload的时间戳 如果没有则为0、
  • unloadEventEnd 与unloadEventStart 相对应,返回的是unload函数执行完成的时间戳
  • redirectStart  第一个http重定向发生的时间 有跳转且是同域的重定向 否则为0
  • redirectEnd 最后一个重定向完成时的时间,否则为0
  • fetchStart 浏览器准备好使用http请求抓取文档的时间,这发生在检查缓存之前
  • domainLookupStart DNS域名开始查询的时间,如果有本地的缓存或keep-alive  时间为0.
  • domianLookupEnd
  • connectStart Http(TCP) 开始建立连接的时间,如果是持久连接,则与fecthStart 值相等。  (注意 如果在传输层发生了错误且重新建立了连接,则这里显示的是新建立的连接开始时间)
  • connectEnd  Http(Tcp) 完成握手的时间,如果是持久连接则与fecthStart 值相等。(注意 如果在传输层发生了错误且重新建立了连接,则这里显示的是新连接完成的时间。 这里包括ssl等授权通过)
  • secureConnectionStart https 连接开始的时间,如果不是安全连接 则为0
  • requestStart http请求读取真实文档开始的时间(完成建立连接),包括从本地缓存读取。 连接错误时这里也显示重新建立连接的时间。
  • requestEnd 包括本地缓存
  • responseStart
  • responseEnd
  • domloading 开始解析渲染dom树的时间,此时Document.readyState 变成loading ,并将抛出readyStateChange 事件
  • dominteractive 完成解析DOM树的时间,Document.readyState 变成interactive,并将抛出readyStateChange事件(注意 只是DOM树解析完成,这时候并没有开始加载网页内的资源)
  • domContentLoadedEventStart  在DOM树解析完成后,网页内资源加载开始的时间。在DOMcontentLoaded事件抛出前发生
  • domContentLoadedEventEnd   DOM树解析完成后,网页内资源加载完成时间(如JS脚本加载执行完成)  这个阶段会可能会触发 domcontentLoaded 事件
  • domCompelete Dom树解析完成,且资源也准备就绪的时间,Document.readyState变成complete.并将抛出readystatechange 事件
  • loadEventStart load 事件发送给文档,也即load回调函数开始执行的时间
  • loadEventEnd load回调函数执行完成的时间

使用 performance.timing 信息简单计算出网页性能数据

  // 计算加载时间

  function getPerformanceTiming() {

    var performance = window.performance;

    if (!performance) {

      // 当前浏览器不支持

      console.log(‘你的浏览器不支持 performance 接口‘);

      return;

    }

    var t = performance.timing;

    var times = {};

    //【重要】页面加载完成的时间

    //【原因】这几乎代表了用户等待页面可用的时间

    times.loadPage = t.loadEventEnd - t.navigationStart;

    //【重要】解析 DOM 树结构的时间

    //【原因】反省下你的 DOM 树嵌套是不是太多了!

    times.domReady = t.domComplete - t.responseEnd;

    //【重要】重定向的时间

    //【原因】拒绝重定向!比如,http://example.com/ 就不该写成 http://example.com

    times.redirect = t.redirectEnd - t.redirectStart;

    //【重要】DNS 查询时间

    //【原因】DNS 预加载做了么?页面内是不是使用了太多不同的域名导致域名查询的时间太长?

    // 可使用 HTML5 Prefetch 预查询 DNS ,见:[HTML5 prefetch](http://segmentfault.com/a/1190000000633364)            

    times.lookupDomain = t.domainLookupEnd - t.domainLookupStart;

    //【重要】读取页面第一个字节的时间

    //【原因】这可以理解为用户拿到你的资源占用的时间,加异地机房了么,加CDN 处理了么?加带宽了么?加 CPU 运算速度了么?

    // TTFB 即 Time To First Byte 的意思

    // 维基百科:https://en.wikipedia.org/wiki/Time_To_First_Byte

    times.ttfb = t.responseStart - t.navigationStart;

    //【重要】内容加载完成的时间

    //【原因】页面内容经过 gzip 压缩了么,静态资源 css/js 等压缩了么?

    times.request = t.responseEnd - t.requestStart;

    //【重要】执行 onload 回调函数的时间

    //【原因】是否太多不必要的操作都放到 onload 回调函数里执行了,考虑过延迟加载、按需加载的策略么?

    times.loadEvent = t.loadEventEnd - t.loadEventStart;

    // DNS 缓存时间

    times.appcache = t.domainLookupStart - t.fetchStart;

    // 卸载页面的时间

    times.unloadEvent = t.unloadEventEnd - t.unloadEventStart;

    // TCP 建立连接完成握手的时间

    times.connect = t.connectEnd - t.connectStart;

    return times;

  }

使用performance.getEntries() 获取所有资源请求的时间数据

  这个函数返回的将是一个数组, 包含了页面中所有的 HTTP 请求, 这里拿第一个请求 window.performance.getEntries()[0] 举例。 注意 HTTP 请求有可能命中本地缓存, 所以请求响应的间隔将非常短 可以看到, 与 performance.timing 对比: 没有与 DOM 相关的属性:

  navigationStart

  unloadEventStart

  unloadEventEnd

  domLoading

  domInteractive

  domContentLoadedEventStart

  domContentLoadedEventEnd

  domComplete

  loadEventStart

  loadEventEnd

  新增属性:

  name

  entryType

  initiatorType

  duration

  与 window.performance.timing 中包含的属性就不再介绍了:

  var entry = {

    // 资源名称,也是资源的绝对路径

    name: "http://cdn.alloyteam.com/wp-content/themes/alloyteam/style.css",

    // 资源类型

    entryType: "resource",

    // 谁发起的请求

    initiatorType: "link", // link 即 <link> 标签

    // script 即 <script>

    // redirect 即重定向

    // 加载时间

    duration: 18.13399999809917,

    redirectStart: 0,

    redirectEnd: 0,

    fetchStart: 424.57699999795295,

    domainLookupStart: 0,

    domainLookupEnd: 0,

    connectStart: 0,

    connectEnd: 0,

    secureConnectionStart: 0,

    requestStart: 0,

    responseStart: 0,

    responseEnd: 442.7109999960521,

    startTime: 424.57699999795295

  };

  可以像 getPerformanceTiming 获取网页的时间一样, 获取某个资源的时间:

  // 计算加载时间

  function getEntryTiming(entry) {

    var t = entry;

    var times = {};

    // 重定向的时间

    times.redirect = t.redirectEnd - t.redirectStart;

    // DNS 查询时间

    times.lookupDomain = t.domainLookupEnd - t.domainLookupStart;

    // 内容加载完成的时间

    times.request = t.responseEnd - t.requestStart;

    // TCP 建立连接完成握手的时间

    times.connect = t.connectEnd - t.connectStart;

    // 挂载 entry 返回

    times.name = entry.name;

    times.entryType = entry.entryType;

    times.initiatorType = entry.initiatorType;

    times.duration = entry.duration;

    return times;

  }

浏览器中timeline 时间线说明

  • Stalled是浏览器得到要发出这个请求的指令,到请求可以发出的等待时间,一般是代理协商、以及等待可复用的TCP连接释放的时间,不包括DNS查询、建立TCP连接等时间等
  • Request sent 请求第一个字节发出前到最后一个字节发出后的时间,也就是上传时间
  • Waiting 请求发出后,到收到响应的第一个字节所花费的时间(Time To First Byte)
  • Content Download 收到响应的第一个字节,到接受完最后一个字节的时间,就是下载时间

浏览器允许的并发请求资源数

首先,是基于端口数量和线程切换开销的考虑,浏览器不可能无限量的并发请求,因此衍生出来了并发限制和HTTP/1.1的Keep alive。 所以,IE6/7在HTTP/1.1下的并发才2,但HTTP/1.0却是4。 而随着技术的发展,负载均衡和各类NoSQL的大量应用,基本已经足以应对C10K的问题。 但却并不是每个网站都懂得利用domain hash也就是多域名来加速访问。因此,新的浏览器加大了并发数的限制,但却仍控制在8以内。
浏览器即使放弃保护自己,将所有请求一起发给服务器,也很可能会引发服务器的并发阈值控制而被BAN,而另外一个控制在8以内的原因也是keep alive技术的存在使得浏览器复用现有连接和服务器通信比创建新连接的性能要更好一些。

所以,浏览器的并发数其实并不仅仅只是良知的要求,而是双方都需要保护自己的默契,并在可靠的情况下提供更好的性能。

前端技术的逐渐成熟,还衍生了domain hash, cookie free, css sprites, js/css combine, max expires time, loading images on demand等等技术。这些技术的出现和大量使用都和并发资源数有关。

  1. 按照普通设计,当网站cookie信息有1 KB、网站首页共150个资源时,用户在请求过程中需要发送150 KB的cookie信息,在512 Kbps的常见上行带宽下,需要长达3秒左右才能全部发送完毕。 尽管这个过程可以和页面下载不同资源的时间并发,但毕竟对速度造成了影响。 而且这些信息在js/css/images/flash等静态资源上,几乎是没有任何必要的。 解决方案是启用和主站不同的域名来放置静态资源,也就是cookie free。
  2. 将css放置在页面最上方应该是很自然的习惯,但第一个css内引入的图片下载是有可能堵塞后续的其他js的下载的。而在目前普遍过百的整页请求数的前提下,浏览器提供的仅仅数个并发,对于进行了良好优化甚至是前面有CDN的系统而言,是极大的性能瓶颈。 这也就衍生了domain hash技术来使用多个域名加大并发量(因为浏览器是基于domain的并发控制,而不是page),不过过多的散布会导致DNS解析上付出额外的代价,所以一般也是控制在2-4之间。 这里常见的一个性能小坑是没有机制去确保URL的哈希一致性(即同一个静态资源应该被哈希到同一个域名下),而导致资源被多次下载。
  3. 再怎么提速,页面上过百的总资源数也仍然是很可观的,如果能将其中一些很多页面都用到的元素如常用元素如按钮、导航、Tab等的背景图,指示图标等等合并为一张大图,并利用css background的定位来使多个样式引用同一张图片,那也就可以大大的减少总请求数了,这就是css sprites的由来。
  4. 全站的js/css原本并不多,其合并技术的产生却是有着和图片不同的考虑。 由于cs/js通常可能对dom布局甚至是内容造成影响,在浏览器解析上,不连贯的载入是会造成多次重新渲染的。因此,在网站变大需要保持模块化来提高可维护性的前提下,js/css combine也就自然衍生了,同时也是minify、compress等对内容进行多余空格、空行、注释的整理和压缩的技术出现的原因。
  5. 随着cookie free和domain hash的引入,网站整体的打开速度将会大大的上一个台阶。 这时我们通常看到的问题是大量的请求由于全站公有header/footer/nav等关系,其对应文件早已在本地缓存里存在了,但为了确保这个内容没有发生修改,浏览器还是需要请求一次服务器,拿到一个304 Not Modified才能放心。 一些比较大型的网站在建立了比较规范的发布制度后,会将大部分静态资源的有效期设置为最长,也就是Cache-Control max-age为10年。 这样设置后,浏览器就再也不会在有缓存的前提下去确认文件是否有修改了。 超长的有效期可以让用户在访问曾访问过的网站或网页时,获得最佳的体验。 带来的复杂性则体现在每次对静态资源进行更新时,必须发布为不同的URL来确保用户重新加载变动的资源。
  6. 即使是这样做完,仍然还存在着一个很大的优化空间,那就是很多页面浏览量很大,但其实用户直接很大比例直接就跳走了,第一屏以下的内容用户根本就不感兴趣。 对于超大流量的网站如淘宝、新浪等,这个问题尤其重要。 这个时候一般是通过将图片的src标签设置为一个loading或空白的样式,在用户翻页将图片放入可见区或即将放入可见区时再去载入。 不过这个优化其实和并发资源数的关系就比较小了,只是对一些散布不合理,或第一页底部的资源会有一定的帮助。 主要意图还是降低带宽费用。

script 标签的阻塞

说到无阻塞加载JavaScript要点,我们就有必要知道,为什么在html中不管是内联JavaScript还是外联,会影响到页面的性能?

原因是:JavaScript是单线程,在JavaScript运行时其他的事情不能被浏览器处理。事实上,大多数浏览器使用单线程处理UI更新和JavaScript运行等多个任务,而同一时间只能有一个任务被执行。所以在执行JavaScript时,会妨碍其他页面动作。这是JavaScript的特性,我们没法改变。

就JavaScript而言,当html解析器遇到<script>标签,无论它是内联还是外联,页面中的下载和解析过程都必须停止,直到<script>从外部加载进来的JavaScript或内联的JavaScript运行完毕,方可继续解析。在高版本的浏览器当中,允许并行下载JavaScript文件,当一个<script>标签正在下载外部资源时,不必阻塞其他<script>标签,但是不幸地是,JavaScript的下载仍然会阻塞其他资源的下载,例如图片。

改善:

1.为了让html文档在解析时,尽量地快,常规的做法是将<script>标签放到</body>标签的前面,这样就不会阻塞html中其他资源的下载了。2.HTML5中的defer和async
<script src="file1.js" defer></script>
<script src="file2.js" async></script>

defer和async区别:

就defer和async的区别而言,使用defer的<script>标签是按照他们排列的顺序执行的,而使用async的<script>标签是不按他们在HTML中的排列顺序执行的;

就执行时间而言,defer是在DOMContentloaded事件之前执行,而async是在window.onload事件之前执行的,且只支持IE10+。当defer和async同时存在时,会忽略defer而遵循async。

3.动态加载

时间: 2024-10-20 19:01:34

浏览器从输入网址发生的事(前端优化)的相关文章

ASP.NET平台下从浏览器地址栏输入之后发生的事

浏览器一般内嵌两个模块: Socket通信模块 → 浏览器将地址栏的数据及其他的数据放入http协议的请求头文件中,Socket将此http请求数据发送到远程服务器端 浏览器引擎渲染模块 → 浏览器接受从服务器返回的http响应头数据以及用户请求的数据渲染成用户所见的界面 ASP.NET开发人员和HttpApplication,HttpContext,HttpRequest,HttpResponse这四个类应该是老熟人了,而ASP.NET事件管道也是ASP.NET程序员耳熟能详的,就笔者自己而言

web工作方式,浏览网页,打开浏览器,输入网址按下回车键,然后会显示出内容,这个过程是怎样的呢?

以下内容摘自<Go Web编程>,介绍的通俗易懂. 我们平时浏览网页的时候,会打开浏览器,输入网址后按下回车键,然后就会显示出你想要浏览的内容.在这个看似简单的用户行为背后,到底隐藏了些什么呢?对于普通的上网过程,系统其实是这样做的:浏览器本身是一个客户端,当你输入URL的时候,首先浏览器会去请求DNS服务器,通过DNS获取相应的域名对应的IP,然后通过IP地址找到IP对应的服务器后,要求建立TCP连接,等浏览器发送完HTTP Request(请求)包后,服务器接收到请求包之后才开始处理请求包

从浏览器地址栏输入网址,到网页彻底打开,中间都发生了什么?

这是一道经典面试题,以前我以为只有我喜欢出这道题,后来在微博上发现其他技术大牛也出这道题. 这道题其实测试的不是具体特定的技术,而是对整个上网这个概念以及背后流程的理解. 我先说一下我所理解或者说我所期待的大概的答题要点,后面再解释这道题的目的和意义,实际上所谓上网这个过程分为三个大的区块,一块是客户端,一块是网络传输层,一块是服务端. 从输入网址开始,这个网址在客户端就会有一个解析,首先浏览器如果有钩子,可能会直接对这个网址做出判断和反馈,比如国内大部分第三方浏览器(IE浏览器基础上加壳的那种

在浏览器中输入网址后是怎么跳转到指定的服务器的

1. 首先,在浏览器里输入要网址 2. 浏览器查找域名的IP地址 DNS查找过程如下: 浏览器缓存 – 浏览器会缓存DNS记录一段时间. 有趣的是,操作系统没有告诉浏览器储存DNS记录的时间,这样不同浏览器会储存个自固定的一个时间(2分钟到30分钟不等). 系统缓存 – 如果在浏览器缓存里没有找到需要的记录,浏览器会做一个系统调用(windows里是gethostbyname).这样便可获得系统缓存中的记录. 路由器缓存 – 接着,前面的查询请求发向路由器,它一般会有自己的DNS缓存. ISP

浏览器输入网址到浏览器渲染页面的过程

1) 在客户端浏览器中输入网址URL. 2) 发送到DNS(域名服务器)获得域名对应的WEB服务器的IP地址. 3) 客户端浏览器与WEB服务器建立TCP(传输控制协议)连接. 4) 客户端浏览器向对应IP地址的WEB服务器发送相应的HTTP或HTTPS请求. 5) WEB服务器响应请求,返回指定的URL数据或错误信息:如果设定重定向,则重定向到新的URL地址. 6) 客户端浏览器下载数据,解析HTML源文件,解析的过程中实现对页面的排版,解析完成后,在浏览器中显示基础的页面. 7) 分析页面中

从输入网址到网页显示过程是什么?

在监测网站前,我们应先了解网络(Web)基本的运作方式.也就是从我们在浏览器中输入网址到浏览器显示页面,这个过程中到底发生了什么事?一般可分为如下7个步骤:1.浏览器中输入网址.2.发送至DNS服务器并获得域名对应的WEB服务器的ip地址. 3.与WEB服务器建立TCP连接.4.浏览器向WEB服务器的ip地址发送相应的http请求.5.WEB服务器响应请求并返回指定URL的数据,或错误信息,如果设定重定向,则重定向到新的URL地址.6.浏览器下载数据后解析HTML源文件,解析的过程中实现对页面的

web应用后台发生的事

浏览器里输入网址后浏览器会通过访问的域名找出其IP地址,给Web服务器发送一个HTTP请求,得到一个服务的永久重定向响应,然后浏览器跟踪重定向地址,发送另一个请求,服务器接收到获取请求,然后处理并返回一个响应,发回一个HTML响应,然后浏览器就显示HTML,在浏览器显示HTML时,它会注意到需要获取其他地址内容的标签.这时,浏览器会发送一个获取请求来重新获得这些文件.浏览器发送异步(AJAX)请求,页面显示完成后客户端仍与服务器端保持着联系. 过程: 1.发送http请求 2.找到目标服务器 3

HTTP-点开浏览器输入网址背后发生的那点事

前言 Internet最早来源于美国国防部ARPANet,1969年投入运行,到现在已有很长一段路了,各位想要了解发展史可以百度下,这里就不多说了. 现如今当我们想要获取一些资料,首先是打开某个浏览器,在地址栏输入地址,想要的信息出现在你的面前. 大家有没有想过输入地址就能返回给你想要的信息是怎么实现的呢? 下面就来简单说下它的实现流程,不过在这之前先来了解下HTTP基本概念如下 HTTP基本概念 在这引用http://www.zsythink.net/archives/76 这是一篇为初学者准

在浏览器输入网址到页面加载完毕中间到底发生了什么?(Browser--&gt;Server)

最近在学习韩老师的php视频,中间有讲到发送请求到服务器返回内容,以前对这个理解并不深刻,虽然以前也知道一部分,这次听了之后收获良多:所以我就画了个流程图,从浏览器输入网址到服务器返回信息,浏览器渲染,呈现页面的具体过程. 今天是国庆节,明天才会出去玩,所以今天还是得学习,学习根本不能停啊,哈哈! 中间有错误的欢迎各位,不吝赐教,谢谢! 下面这个是韩老师画的图,内容也比较相似,所以我也放在上面,以便以后回顾: 其中有涉及到,http的状态码,我这个好多也确实记不住,所以为了以后需要的时候来看,我