输入url 到页面渲染完成(四处抄)

开始上网,输入 url

当我们开始输入 url 的时候,浏览器就已经开始匹配 url ,从历史纪录,书签等,找到已经输入的字符串可能对应的 url ,然后给出智能提示,自动补全等。


解析URL

  • 浏览器通过 URL 能够知道下面的信息:

  • Protocol "http"
    使用HTTP协议

  • Resource "/"
    请求的资源是主页(index)

输入的是 URL 还是搜索的关键字?

当协议或主机名不合法时,浏览器会将地址栏中输入的文字传给默认的搜索引擎。大部分情况下,在把文字传递给搜索引擎的时候,URL会带有特定的一串字符,用来告诉搜索引擎这次搜索来自这个特定浏览器。

转换非 ASCII 的 Unicode 字符

  • 浏览器检查输入是否含有不是 a-z, A-Z,0-9, - 或者 . 的字符
  • 这里主机名是 google.com ,所以没有非ASCII的字符;如果有的话,浏览器会对主机名部分使用 Punycode 编码

检查 HSTS 列表

  • 浏览器检查自带的“预加载 HSTS(HTTP严格传输安全)”列表,这个列表里包含了那些请求浏览器只使用HTTPS进行连接的网站
  • 如果网站在这个列表里,浏览器会使用 HTTPS 而不是 HTTP 协议,否则,最初的请求会使用HTTP协议发送
  • 注意,一个网站哪怕不在 HSTS 列表里,也可以要求浏览器对自己使用 HSTS 政策进行访问。浏览器向网站发出第一个 HTTP 请求之后,网站会返回浏览器一个响应,请求浏览器只使用 HTTPS 发送请求。然而,就是这第一个 HTTP 请求,却可能会使用户受到 downgrade attack 的威胁,这也是为什么现代浏览器都预置了 HSTS 列表。

浏览器查找 url 的 Ip 地址

  1. 浏览器检查域名是否在缓存当中(要查看 Chrome 当中的缓存, 打开 chrome://net-internals/#dns)。
  2. 首先查看本地硬盘的 host 文件,查看其中有没有和这个域名对应的规则,如果找到,就直接使用 host 中的 ip 地址。
  3. 如果 host 中没能找到对应的 ip 地址,浏览器会发出一个 DNS 请求到本地 DNS 服务器,即网络接入提供商(中国移动,中国电信等)
  4. 本地 DNS 服务器查询它的缓存记录,如果有就直接返回查询结果,此过程是递归查询,如果没有则会向 DNS 根服务器查询
  5. 跟服务器没有相应的记录时,就告诉本地 DNS 服务器可以去域名服务器查询,并告知域名服务器的 IP,
  6. 本地服务器向域名服务器发出请求,在下图中请求的对象是 .com 服务器, .com 服务器收到请求后,也不会直接返回对应关系,而是告诉本地 DNS 服务器,你所查询的域名的服务器的地址。
  7. 本地服务器向查询的域名服务器发出请求,此时能收到相应的域名和 IP 的地址,本地 DNS 不仅要把返回的 IP 和域名返回给用户还要把这个关系保存到缓存中,以防下次用户请求时,可以快速返回结果,加快了网络的访问。
域名解析-盗图
域名解析-盗图

关于 DNS

浏览器向 Web 服务器发出 HTTP 请求

拿到域名对应的 IP 地址之后,浏览器会以随机一个( 1024 < 端口号 < 65535 ) 向 Web 服务器 ( nginx ) 的 80 端口号发出 TCP 的连接请求,经过各种路由设备(局域网除外),
到达网卡,进入到内核的 TCP/IP 协议栈( 识别连接请求,解封包等 ),最终到达 Web 应用程序,建立起了 TCP/IP 连接。

建立起 TCP 连接之后,发起一个 HTTP 请求 ( 一般常用是 get post )。
一般一个 HTTP 请求包含:

  • 请求的 url 协议/版本
  • 请求头 request header
  • 请求体 request body

最后一个请求头后面是空行,发送回车符和换行符,通知服务器以下不再是请求头

TCP 三次握手与四次挥手
TCP协议中的三次握手和四次挥手(图解)

服务器的永久重定向响应

服务器给浏览器响应一个 301 的永久重定向,这样浏览器访问 http://www.google.com 而不是 http://google.com ,这是由于搜索引擎排名的原因,比如我的网站为了输入方便,在进行 DNS 解析时,将 http://www.hexin.lifehttp://hexin.life 定位到了同一网站下,搜素引擎会认为他们是俩个网站,从而造成搜索排名下降。而当 301 重定向之后,搜素引擎便会把含 www 的和不含的放在同一个网站排名中,而且使用 www 和非 www 时,也会缓存多次,所以会进行 301 的重定向。

你所知道的3xx状态码

浏览器跟踪重定向地址

再次向正确地址发送 HTTP 请求

服务器处理请求

经过千辛万苦,终于将 http 发送到了我们的服务器。后端接到 TCP 报文开始,他会对 tcp 连接进行处理,对 HTTP 根据协议进行解析,按照报文格式一步一步封装成 HTTP request 对象,供上层使用。

大一点的网站会请求到反向代理中,因为网站访问量越来越大,网站速度也就变慢了,此时客户端不再直接通过 HTTP 协议访问某网站的应用服务器,而是先请求到 Nginx , Nginx 再请求应用服务器,然后再将结果返回给客户端,这里 Nginx 的作用时反向代理服务器,同时如果一台服务器挂了,只要其他服务器还在正常运行,网站就能正常使用。

服务器返回 HTTP 请求

响应类似请求:

  • 状态行
  • 响应头
  • 响应体

响应状态码

  1. 1xx:信息性状态码,表示服务器已接收了客户端请求,客户端可继续发送请求。
  • 100 Continue

  • 101 Switching Protocols

  1. 2xx:成功状态码,表示服务器已成功接收到请求并进行处理。
  • 200 OK 表示客户端请求成功

  • 204 No Content 成功,但不返回任何实体的主体部分

  • 206 Partial Content 成功执行了一个范围(Range)请求

  1. 3xx:重定向状态码,表示服务器要求客户端重定向。
  • 301 Moved Permanently 永久性重定向,响应报文的Location首部应该有该资源的新URL

  • 302 Found 临时性重定向,响应报文的Location首部给出的URL用来临时定位资源

  • 303 See Other 请求的资源存在着另一个URI,客户端应使用GET方法定向获取请求的资源

  • 304 Not Modified 服务器内容没有更新,可以直接读取浏览器缓存

  • 307 Temporary Redirect 临时重定向。与302 Found含义一样。302禁止POST变换为GET,但实际使用时并不一定,307则更多浏览器可能会遵循这一标准,但也依赖于浏览器具体实现

  1. 4xx:客户端错误状态码,表示客户端的请求有非法内容。
  • 400 Bad Request 表示客户端请求有语法错误,不能被服务器所理解

  • 401 Unauthonzed 表示请求未经授权,该状态代码必须与 WWW-Authenticate 报头域一起使用

  • 403 Forbidden 表示服务器收到请求,但是拒绝提供服务,通常会在响应正文中给出不提供服务的原因

  • 404 Not Found 请求的资源不存在,例如,输入了错误的URL

  1. 5xx:服务器错误状态码,表示服务器未能正常处理客户端的请求而出现意外错误。
  • 500 Internel Server Error 表示服务器发生不可预期的错误,导致无法完成客户端的请求

  • 503 Service Unavailable 表示服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常

HTTP状态码
HTTP response codes
HTTP,HTTP2.0,SPDY,HTTPS你应该知道的一些事

浏览器渲染 html

浏览器在解析html文件时,会”自上而下“加载,并在加载过程中进行解析渲染。在解析过程中,如果遇到请求外部资源时,如图片、外链的CSS、iconfont等,请求过程是异步的,并不会影响html文档进行加载。

  1. 首先是解析 HTML 构建 DOM 树 =>
  2. 解析 CSS 解析为 CSSOM =>
  3. 结合 DOM 和 CSSOM 生成 render tree(每个节点的视觉信息) =>
  4. 生成布局 layout =>
  5. 将布局绘制到屏幕

这五步中,三四步比较慢生成布局和绘制合成渲染


当文档加载过程中遇到js文件,html文档会挂起渲染(加载解析渲染同步)的线程,不仅要等待文档中js文件加载完毕,还要等待解析执行完毕,才可以恢复html文档的渲染线程。因为JS有可能会修改DOM,最为经典的document.write,这意味着,在JS执行完成前,后续所有资源的下载可能是没有必要的,这是js阻塞后续资源下载的根本原因。所以我明平时的代码中,js是放在html文档末尾的。

DOM 树


DOM 树中的每一个需要显示的节点再渲染树中至少存在一个对应的节点,隐藏的 DOM 元素则没有对应节点,渲染树中的节点被称为 “帧(frames)”或“盒(boxes)”,
符合 CSS 模型的定义,一旦DOM 树和渲染树构建完成,浏览器就开始显示绘制元素

很多时候,密集的重新渲染是无法避免的,比如scroll事件的回调函数和网页动画。
网页动画的每一帧(frame)都是一次重新渲染。每秒低于24帧的动画,人眼就能感受到停顿。一般的网页动画,需要达到每秒30帧到60帧的频率,才能比较流畅。如果能达到每秒70帧甚至80帧,就会极其流畅。

大多数显示器的刷新频率是60Hz,为了与系统一致,以及节省电力,浏览器会自动按照这个频率,刷新动画(如果可以做到的话)。
所以,如果网页动画能够做到每秒60帧,就会跟显示器同步刷新,达到最佳的视觉效果。这意味着,一秒之内进行60次重新渲染,每次重新渲染的时间不能超过16.66毫秒。

一秒之间能够完成多少次重新渲染,这个指标就被称为"刷新率",英文为FPS(frame per second)。60次重新渲染,就是60FPS。
如果想达到60帧的刷新率,就意味着JavaScript线程每个任务的耗时,必须少于16毫秒。一个解决办法是使用Web Worker,主线程只用于UI渲染,然后跟UI渲染不相干的任务,都放在Worker线程。

DOM 解析

<html>
<html>
<head>
    <title>Web page parsing</title>
</head>
<body>
    <div>
        <h1>Web page parsing</h1>
        <p>This is an example Web page.</p>
    </div>
</body>
</html>

DOM 解析成这样


CSS 解析

假设有下面这样的 DOM 结构

<doc>
<title>A few quotes</title>
<para>
  Franklin said that <quote>"A penny saved is a penny earned."</quote>
</para>
<para>
  FDR said <quote>"We have nothing to fear but <span>fear itself.</span>"</quote>
</para>
</doc>

CSS 文档

 /* rule 1 */ doc { display: block; text-indent: 1em; }
/* rule 2 */ title { display: block; font-size: 3em; }
/* rule 3 */ para { display: block; }
/* rule 4 */ [class="emph"] { font-style: italic; }

CSS Rule tree 时这样


  • 图中的第4条规则出现了两次,一次是独立的,一次是在规则3的子结点。所以,我们可以知道,建立CSS Rule Tree是需要比照着DOM Tree来的。CSS匹配DOM Tree主要是从右到左解析CSS的Selector,好多人以为这个事会比较快,其实并不一定。关键还看我们的CSS的Selector怎么写了。
  • CSS匹配HTML元素是一个相当复杂和有性能问题的事情。所以,你就会在N多地方看到很多人都告诉你,DOM树要小,CSS尽量用id和class,千万不要过渡层叠下去

通过这俩个树我们可以得到一个叫 Style Context Tree


所以,Firefox基本上来说是通过CSS 解析 生成 CSS Rule Tree,然后,通过比对DOM生成Style Context Tree,然后Firefox通过把Style Context Tree和其Render Tree(Frame Tree)关联上,就完成了。注意:Render Tree会把一些不可见的结点去除掉。而Firefox中所谓的Frame就是一个DOM结点,不要被其名字所迷惑了。


在 Firefox 中,系统会针对 DOM 更新注册展示层,作为侦听器。展示层将框架创建工作委托给FrameConstructor,由该构造器解析样式(请参阅样式计算)并创建框架。
在 WebKit 中,解析样式和创建呈现器的过程称为“附加”。每个 DOM 节点都有一个“attach”方法。附加是同步进行的,将节点插入 DOM 树需要调用新的节点“attach”方法

渲染

  1. 计算 CSS 样式
  2. 构建 render tree
  3. Layout
  4. 开始绘制

上图流程中有很多连接线,这表示了Javascript动态修改了DOM属性或是CSS属会导致重新Layout,有些改变不会,就是那些指到天上的箭头,比如,修改后的CSS rule没有被匹配到,等。

Repaint

屏幕的一部分要重画,比如某个元素的 CSS 背景变了,但尺寸没有变

Reflow

当 DOM 的变化影响了元素的几何属性 => 比如改变边框宽度或者给段落增加文字,导致行数增加 => 浏览器需要重新计算元素的几何属性,同样其他元素的几何属性和位置也会收到影响,浏览器会使渲染树中受到影响部分失效,并重新构造渲染树,发生重排,完成重排后,浏览器会重新绘制受影响部分的元素到屏幕中,也会发生重绘。

  • 样式表越简单,重排和重绘就越快。
  • 重排和重绘的DOM元素层级越高,成本就越高。
  • table元素的重排和重绘成本,要高于div元素

发生重绘

  • 当你增加、删除、修改DOM结点时,会导致Reflow或Repaint
  • 当你移动DOM的位置,或是搞个动画的时候。(元素位置发生改变)
  • 当你修改CSS样式的时候。或者页面渲染初始化
  • 当你Resize窗口的时候(移动端没有这个问题),或是滚动的时候。
  • 当你修改网页的默认字体时。
  • 元素尺寸发生改变(边距, 高度等)
  • 注:display:none会触发reflow,而visibility:hidden只会触发repaint,因为没有发现位置变化。

渲染树的变化的排队与刷新

由于每次重排都行会产生消耗,大多数浏览器通过队列化修改并批量执行来优化重排过程,然而,你可能会不知不觉的强制刷新对了要求计划立刻执行,获取布局的信息会导致队列刷新

  • offsetTop, offsetBottom, offsetWidth, offsetHeight
  • scrollTop, scrollBottom, scrollWidth, scrollHeight
  • clientTop, clientBottom, clientWidth, clientHeight
  • getComputedStyle() =>( currentStyle in IE)
    以上属性和方法需要返回最新的布局信息,因此浏览器不得不执行渲染队列中的‘待处理变化’并触发重排以返回正确的值。

"重绘"不一定需要"重排" ---- "重排"必然导致"重绘"

最小化重绘和重排

  • 改变样式 => 不要一条条地改变样式,多个改变合并 => 直接更换 CSS 的 Class
  • 批量修改 DOM => 使元素脱离文档流(隐藏显示,使用文档片段,拷贝到一个脱离文档的节点中完成后再替换) => 修改 => 带回文档
  • 动画使用绝对定位,使用拖放代理
  • 缓存布局信息 => 偏移量,滚动位置, 计算出的样式等 获取一次后赋值给局部遍历
  • 事件委托 => 减少事件处理器的数量

浏览器请求嵌在 HTML 中的资源(图片,视频音频, CSS, JavaScript 等)

其实这个步骤可以并列在步骤8中,在浏览器显示HTML时,它会注意到需要获取其他地址内容的标签。这时,浏览器会发送一个获取请求来重新获得这些文件。比如我要获取外图片,CSS,JS文件等,类似于下面的链接:

图片:http://or3233yyd.bkt.clouddn.com//17-8-9/67016800.jpg

CSS式样表:https://cdn.bootcss.com/animate.css/3.5.2/animate.css

JavaScript 文件:https://cdn.bootcss.com/jquery/3.2.1/core.js

这些地址都要经历一个和HTML读取类似的过程。所以浏览器会在DNS中查找这些域名,发送请求,重定向等等...

不像动态页面,静态文件会允许浏览器对其进行缓存。有的文件可能会不需要与服务器通讯,而从缓存中直接读取,或者可以放到CDN中

转载整理:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,176评论 5 469
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,190评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,232评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,953评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,879评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,177评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,626评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,295评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,436评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,365评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,414评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,096评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,685评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,771评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,987评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,438评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,032评论 2 341

推荐阅读更多精彩内容