乐趣区

关于javascript:网红面试题从输入-url-到看到页面发生了什么

流程图

这题刺眼看上去没问题,无非是 HTTP 申请到浏览器渲染,但能够聊的货色很多。我想它的执行程序是,用户输出——开始导航——HTTP 申请——浏览器渲染。其中用户输出、开始导航、浏览器渲染是浏览器方面的知识点,HTTP 申请是 HTTP 方面的知识点

以下就是从输出 url 到看到页面的整个流程图

原图地址:https://s2.loli.net/2022/04/2…

前言

理解 ” 开始导航 ” 之前,须要先晓得浏览器架构,简略来说,古代浏览器由 1 个浏览器主过程、1 个 GPU 过程、多个渲染过程、多个插件过程、网络过程、音频过程、存储过程组成

下图是李兵在《浏览器工作原理与实际》中所示,展现 Chrome 浏览器的架构

以及将来古代浏览器架构示意图:

文章古代浏览器外部揭秘中有一张图,是这样形容的

图中表明浏览器主过程蕴含了 UI 线程、网络线程、存储线程,与李兵的观点有所不同。那以谁为准呢?以工夫为准,李兵的专栏是 19 年所写,而《古代浏览器外部解密》是 18 年的文章,站在 2022 年的背景,古代浏览器,UI、网络、存储等都已降级为过程,而非是浏览器主过程中的线程

用户输出

当用户在地址栏中输出一个字符串时,地址栏会判断输出的关键字是搜寻内容,还是申请的 URL

  • 如果是搜寻内容,地址栏会应用浏览器默认的搜索引擎,合成新的带搜寻关键字的 URL

    • 例如在 chrome 中搜长泽雅美
  • 如果输出内容合乎 URL 规定,例如输出azhubaby.com,那么地址栏会依据规定,把这段内容加上协定合成实现的 URL,如 https://azhubaby.com

当用户输出关键字并键入回车之后,意味着以后页面将替换为新的页面,此时浏览器中有个 API——beforeunload,它容许页面在来到之前触发是否一个确认对话框。这里应用此 API,可让浏览器不再导航

// 监听来到页背后的事件
window.addEventListener('beforeunload', (event) => {event.preventDefault();
    event.returnValue = '';
})

可在这里看看 beforeunload 的 demo

从浏览器架构分工上讲,当用户输出字符串时是 UI 过程(老一点的浏览器是浏览器主过程)在运作

开始导航

当敲下 Enter 键时,UI 过程将指挥权交接给了网络过程。网络过程承受申请指令前,会先查找本地缓存是否有缓存。如果有缓存该资源,那么间接返回资源给浏览器过程;如果在缓存中没找到该资源,那么则正式进入 HTTP 申请阶段

对于 HTTP 缓存方面的常识能够看看这篇——面试常客:HTTP 缓存

HTTP 申请

之前写过一篇 TCP/IP 协定及网络分层模型,讲述了 TCP/IP 网络分层协定,它就像搭积木一样,每一层须要下一层的撑持,咱们的 HTTP 申请是其 HTTP 协定的利用,须要先连贯传输层(TCP)以及更底层网络互连层(IP)

而 IP 从哪里来,通过 DNS,使其域名 和 IP 做映射

咱们应用倒推法能够理清“路线”:

HTTP 申请 —— HTTP 协定连贯 —— TCP 协定连贯 —— IP 协定连贯 —— 须要晓得 IP——DNS 做 域名 /IP映射

所以进入 HTTP 申请的第一步是 DNS 解析

DNS 解析

这里对 DNS 不做过多概述,简略来说,它的作用是用域名代替 IP 地址,合乎人的记忆。输出du.azhubaby.com,示意 IP 地址 47.102.152.19,你能够在命令行中 ping 一个域名,来求证一下后果

HTTP 申请之前的第一步是判断 DNS 中是否有缓存,如果有,间接返回 IP 地址;如果没有,则进行 DNS 解析,并把后果 IP 缓存到 DNS

有了 IP 地址后,IP 层连贯胜利,接下来就是 TCP 传输层

TCP 连贯

这里要看 HTTP 协定的版本,如果是 HTTP/1.1 的话,就要思考 TCP 队列否丰满,因为 HTTP/1.1 最多容许一个域名连贯 6 条 TCP,太多了就要在期待 TCP 队列中排队;如果是 HTTP/2 的话,那就没事,它容许 TCP 并发

这里还要思考到如果协定是 HTTPS 协定的话,还须要建设一条 TLS 连贯

等真正 TCP 连贯时,就联想到网红面试题:三次握手、四次挥手

三次握手、四次挥手

为什么是三次握手和四次挥手,因为只有这样能力让单方(客户端和服务端)晓得彼此的接管能力和发送能力是没问题的

步骤为:

  • 客户端提出建设连贯,收回客户端 seq:seq=client_isn
  • 服务端收到音讯后返回 ack=client_isn+1 和服务端 seq:seq=server_isn
  • 客户端收到后返回ack=server_isn+1 示意收到了

能够了解为男女双方确认关系,男女双方要结婚,怎么办?先见父母失去父母认同,之前听过这样一句话:得不到父母祝愿的婚姻是不幸福的(当然,不见父母间接结婚的也有,但不支流)

  • 男方提出去女方家,带上见面礼 seq:seq= 男方的诚意
  • 女方家收到见面礼后返回(给男方)红包 ack= 咱们认可你啦 以及女方去男方家也带上见面礼 seq:seq= 女方的诚意
  • 男方家收到见面礼后返回(给女方的)红包 ack=server_isn+1

这个叫确定关系。所以要又来又回三次,单方都确保晓得对方的诚意和本人的诚意

那什么是四次挥手呢?

在断开之前,须要进行四次挥手

为什么要有四次挥手?

次要是为了确保单方都晓得对方断开连接

具体步骤为:

  • 客户端第一次发送音讯给服务端通知它须要断开连接
  • 服务端收到音讯后返回音讯通知客户端:晓得了,为了确保服务端收到了之前所有的 HTTP 申请,服务端须要等一等再断开连接
  • 服务端确认所有的 HTTP 申请都收到了,被动发消息给客户端:我这边所有的申请都解决完了,我也能够断开连接了
  • 客户端收到这个申请后,返回音讯通知服务端:我晓得,断开连接吧

次要是为了确认单方的接管能力和发送能力是否失常、制订本人的初始化序列号为前面的可靠性传送做筹备

能够了解为一对男女要离别

  • 女方提出离别,说你对我不好,我要离别
  • 男方感觉需要正当,批准离别,但离别之前要把联系方式、合照、各种乌七八糟的的事件算清楚再离别
  • 男方理分明后,被动发消息给女方,说这边都解决分明了,当前你是你,我是我,咱们能够离别了
  • 女方收到音讯后,返回通知男方:我晓得了,离别吧

于是乎,它们就断了,离别手续实现。具体具体的信息可看猿人谷的面试官,不要再问我三次握手和四次挥手,一个字:细

发送 HTTP 申请

TCP 连贯曾经通了,当初正式发送 HTTP 申请,这里又有的聊了,如 HTTP 的报文内容、申请头、响应头、申请办法、状态码等知识点

首先 HTTP 的报文构造由 起始行 + 头部 + 空行 + 实体 组成,简略来说就是 header+body,HTTP 的报文能够没有 body(get 办法),但必须要有 header

申请头由 申请行 + 头部字段 形成,响应头由 状态行 + 头部字段 形成

申请行有三局部:申请办法、申请指标和版本号

  • 例如 GET / HTTP/1.1

状态行也有三局部:版本号、状态码和起因字符串

  • 例如 HTTP/1.1 200 OK

在浏览器中,关上 F12,在 NetWork 中任何一个申请中,你都会看到这样的构造

这里咱们也常会遇到一些例如 GET 和 POST 申请形式的区别、HTTP 状态码等相干的衍生问题

GET 和 POST 申请形式的区别

  • 从缓存角度看,GET 会被缓存,POST 不会被缓存
  • 从参数角度看,GET 通过在 URL 的 ”?” 后以 key=value 形式传参,数据之间以“&”相连接;POST 则要将数据封装到申请体中发送,这个过程不可见
  • 从平安角度看,GET 不平安,因为 URL 可见;POST 较 GET 平安度高
  • 从编码角度看,GET 只承受 ASCII 字符,向服务器发送中文字符可能会呈现乱码;POST 反对规范字符集,能够正确传递中文
  • 从数据长度的限度看,GET 个别受 URL 长度限度(URL 的最大长度是 2048 个字符),POST 无限度

HTTP 状态码

RFC 规范把状态码分成了五类,用数字的第一位示意分类,而 0~99 不必,这样状态码的理论可用范畴就大大放大了,由 000~999 变成了 100~599。

这五类的具体含意是:

  • 1××:提示信息,示意目前是协定解决的中间状态,还须要后续的操作;
  • 2××:胜利,报文曾经收到并被正确处理;
  • 3××:重定向,资源地位产生变动,须要客户端从新发送申请;
  • 4××:客户端谬误,申请报文有误,服务器无奈解决;
  • 5××:服务器谬误,服务器在解决申请时外部产生了谬误。

目前 RFC 规范里总共有 41 个状态码

101 – Switching Protocols,客户端应用 Upgrade 头字段

200 – 申请胜利

204 – 无内容,服务器胜利解决了申请,但没有返回任何内容。

206 – 个别用来做断点续传,或者是视频文件等大文件的加载

301 – 永恒重定向

302 – 长期重定向

304 – 未修改协商缓存,返回缓存中的数据。它不具备通常的跳转含意,但能够了解成 重定向到缓存的文件(即缓存重定向)

400 – 申请中语法错误

401 – 未受权

403 – 服务器收到申请,然而回绝提供服务,即资源不可用

404 – 无奈找到申请资源

408 Request Timeout – 申请超时

414 – 申请 URI 过长(如图一新浪常有)

500 – 服务器外部谬误

501 – 尚未施行:服务器不具备申请性能

502 – 网关谬误

503 – 服务器不可用,被动用 503 响应申请或 Nginx 设置限速,超过限速,会返回 503

504 – 网关超时

这里要对 304 做一下阐明,当申请头 If-Modified-SinceIf-None-Match 中判断批改工夫是否统一(或惟一标识是否统一),是,则返回 304,应用浏览器内存中的本地缓存;不统一则阐明要更新,持续申请资源放回给客户端,并带上 Last-ModifiedETag

申请形式

HTTP/1.1 规定了八种办法,都必须是大写模式

  • GET:获取资源,能够了解为读取或者下载数据。只有 GET 申请能力起到缓存成果
  • HEAD:获取资源的元信息
  • POST:像资源提交数据,相当于写入或上传数据
  • PUT:相似 POST
  • DELETE:删除资源
  • CONNECT:建设非凡的连贯隧道
  • OPTIONS:列出可对资源履行的形式
  • TRACE:追踪申请 – 响应的传输门路

浏览器渲染

当 HTTP 申请结束后,断开 TCP 连贯,将资源返回给客户端(浏览器)。此时浏览器要判断是否与关上的网站是同一个站点。因为如果是同一个站点的话,则可应用同站点的渲染过程渲染页面,如果不是,浏览器则关上新的渲染过程解析资源

浏览器渲染的大抵流程如下图所示:

咱们能够将页面渲染分为三个步骤:

解析

  • HTML 被解析为 DOM 树,CSS 被解析为 CSS 规定树,JavaScript 通过 DOM API 和 CSSOM API 来操作 DOM Tree 和 CSS Rule Tree

渲染

  • 浏览器引擎通过 DOM Tree 和 CSS Rule Tree 构建 Rendering Tree(渲染树),这其中进行大量的 回流(Reflow)和 重绘(Repaint)
  • 回流和重绘

    • 回流:意味着元件的几何尺寸变了,须要从新验证并计算 Render Tree
    • 重绘:屏幕的一部分须要重画,比方某个 CSS 的背景色变了,但元件的几何尺寸没有变
    • 回流的老本要比重绘大

绘制

  • 最初通过操作系统(浏览器)的 Native GUI 的 API 绘制

其中,衍生出重绘和回流的问题,进步性能的办法之一就是缩小浏览器的渲染工夫,其中的一个优化点就是缩小重绘和回流

缩小回流和重绘的办法

  1. 不要一条条批改 DOM 款式,与其这样,不如预约义好 CSS 的 class,而后批改 DOM 的款式
  2. 把 DOM“离线”后批改

    1. 应用 documentFragment 对象在内存里操作 DOM
    2. 先把 DOM 给 display:none(有一次 Reflow),而后你想怎么改就怎么改,再把它显示进去
    3. clone 一个 DOM 节点到内存里,而后想怎么改就怎么改,改完后和在线的那个替换一下
  3. 不要把 DOM 节点的属性值放在一个循环中当作循环的变量,不然这会导致大量地读写这个节点的属性
  4. 尽可能地批改层级比拟低的 DOM
  5. 不要应用 table 布局

造成回流的属性:

width、height、padding、margin、border、position、top、left、bottom、right、float、clear、text-align、vertical-align、line-height、font-weight、font-size、font-family、overflow、white-space

造成重绘的属性:

color、border-style、border-radius、text-decoration、box-shadow、outline、background

记住一点,回流是与几何大小相干,重绘与大小无关

如此,从输出 url 到看到页面的整个流程就走完了

总结

这道题能衍生很多问题,从一题能够测试出面试者的 HTTP、浏览器相干常识。正所谓”鹏怒而飞,其翼若垂天之云;水击三千里,碧空九万丈;好风凭借力,送我上青云。“。这道题之所以能成为经典题,不是没有它的起因的

笔者这里做一个总结,把这题能够衍生的知识点逐个列出,待君考虑

浏览器方面

  • 浏览器架构

    • 由什么组成?浏览器主过程、GPU 过程、多个渲染过程、多个插件过程、网络过程、音频过程、存储过程等
    • 渲染过程中有哪些过程?GUI 渲染线程、JS 引擎线程、事件触发线程、网络异步线程、定时器线程
    • 过程和线程的区别?过程是应用程序创立的实例,而线程依靠于过程,它是计算机最小的运行单位
  • 浏览器渲染

    • 渲染流程?解析、渲染、绘制
    • 重绘和回流

      • 两者的区别
      • 重绘和回流的属性
      • 如何缩小重绘和回流,进步渲染性能

HTTP 方面

  • HTTP 缓存

    • 强缓存

      • HTTP/1.1 Cache-Control
      • HTTP/1.0 Expires
      • Cache-Control > Expires
    • 协商缓存

      • HTTP/1.1 ETag/If-None-Match
      • HTTP/1.0 Last-Modified/If-Modified-Since
      • 精准度:ETag > Last-Modified
      • 性能:Last-Modified > ETag
  • TCP/IP 连贯

    • 三次握手、四次挥手
  • 网络层面的性能优化

    • HTTP/1.1 的做法
    • HTTP/2 的做法
    • HTTP/3 的做法
    • 每个阶段采纳的性能优化是有所不同的

参考资料

  • 浏览器的渲染原理简介
  • 深刻了解古代浏览器
  • 万字详文:深刻了解浏览器原理
  • 古代浏览器外部工作原理(附具体流程图)
  • 前端都该懂的浏览器工作原理
退出移动版