0%

浏览器输入网址到渲染出页面流程

详细阅读:github - 当你在浏览器中输入 google.com 并且按下回车之后发生了什么?

  1. 输入网址

  2. 浏览器进行地址解析,将解析出的域名进行 DNS 解析

    url解析:网络标准规定了URL只能是字母和数字,还有一些其它特殊符号(-_.~ ! * ‘ ( ) ; : @ & = + $ , / ? # [ ],但是有部分特殊字符需要进行编码否则会出现歧义。使用encodeURI(...)encodeURIComponent(...)进行编码。使用decodeURI(...)decodeURIComponent(...)进行解码。规则采用UTF-8

    请注意,encodeURI 自身无法产生能适用于HTTP GET 或 POST 请求的URI,例如对于 XMLHTTPRequests, 因为 “&”, “+”, 和 “=” 不会被编码,然而在 GET 和 POST 请求中它们是特殊字符。然而encodeURIComponent这个方法会对这些字符编码。

    DNS解析: 先查看浏览器 DNS 缓存中是否有域名对应的 IP ,如果没有,则看操作系统 DNS 缓存中是否有对应的 IP (例如Windows的hosts文件),依旧没有就对本地区DNS 服务器发起请求,如果还是没有,就直接到 Root Server域名服务器请求解析。(非转发模式)

    一般使用 UDP 协议向 DNS 服务器进行寻址。

    DNS查询有两种模式,转发模式和非转发模式。转发模式,第一台DNS服务器查找不到,会转发到其他DNS服务器上查找,如果其他DNS服务器上也没有就会到根服务器查找。

    前端DNS优化:可以在html页面头部写入dns缓存地址

    <meta http-equiv="x-dns-prefetch-control" content="on" />
    <link rel="dns-prefetch" href="http://bdimg.share.baidu.com" />
  3. 通过 IP 寻址和 ARP ,找到目标服务器地址。

    获取到 IP 后,直接通过 IP 寻址找到 IP 对应的服务器,然后通过 ARP 协议找到服务器的 MAC 地址。

  4. 进行 TCP 三次握手,建立 TCP 连接。

    • 第一次握手:主机A发送位码为SYN=1的TCP包给服务器,并且随机产生一个作为确认号(这是tcp包的一部分),主机B收到SYN码后直到A要求建立连接;
    • 第二次握手:主机B收到请求后,向A发送确认号(主机A的seq+1),syn=1,seq = 随机数 的TCP包;
    • 主机A收到后检查确认号是否正确,即第一次A发送的确认号是否+1了,以及位码ack是否为1,若正确,主机A会再发送确认号(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功。

    三次握手

  5. 浏览器发送数据请求,等待服务器响应。

    根据数据请求判断是否使用浏览器缓存

    如果使用浏览器强缓存,则不会对服务器进行请求,直接响应数据请求,返回浏览器缓存数据。

    如果是协商缓存机制,会向服务器进行询问缓存使用结果,注意启发式缓存。

    如果不使用缓存,则会向服务器请求数据。

  6. 服务器处理请求,并对请求做出响应。

  7. 浏览器收到服务器响应,得到网页代码。

  8. 渲染页面

    HTML解析:HTML词法分析和语法分析

    外部样式、脚本加载(async / defer)

    • 构建DOM树(DOM tree):从上到下解析HTML文档生成DOM节点树(DOM tree),也叫内容树(content tree);

      JS会阻塞DOM树的解析,但是CSS不会阻塞DOM树的解析。所以如果不得不将JS文件放在头部,可以将JS文件放在CSS文件引入之上。且JS文件中最好不要有修改样式的操作,不然会和预期结果不一致,同时也无法进行DOM操作。

    • 构建CSSOM(CSS Object Model)树:加载解析样式生成CSSOM树;

    • 构建渲染树(render tree):根据DOM树和CSSOM树,生成渲染树(render tree);

      渲染树:按顺序展示在屏幕上的一系列矩形,这些矩形带有字体,颜色和尺寸等视觉属性。

      • 浏览器从DOM树的根节点开始遍历每个可见节点。
      • 对于每个可见节点,找到CSSOM树中对应的规则,并应用它们。
      • 根据每个可见节点以及其对应的样式组合生成渲染树。
    • 布局(layout):根据渲染树将节点树的每一个节点布局在屏幕上的正确位置;

    • 绘制(painting):遍历渲染树绘制所有节点,为每一个节点适用对应的样式,这一过程是通过UI后端模块完成;

    • 执行JavaScript:加载并执行JavaScript代码(包括内联代码或外联JavaScript文件);

    • 回流(Reflow / 重排):当Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。

      回流操作:页面首次渲染、浏览器窗口大小发生改变、元素尺寸或位置发生改变、元素内容变化、元素字体大小变化、添加或删除可见的DOM元素等

      回流必将引起重绘,重绘不一定会引起回流。回流比重绘代价要更高

      获取 document.body.offsetHeight 等一些数据会引起浏览器重绘。

      参考资料:中文翻译:是什么导致重排英语原文

    • 重绘(Repaint):当页面中元素样式的改变并不影响它在文档流中的位置时(例如:colorbackground-colorvisibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。

      更多资料:基础系列-重绘与回流

    HTML词法分析和语法分析,CSS解析, 合成图层、合成线程调用光栅化线程池,生成位图后浏览器进程间通信过程,显卡缓存与显示器的关系

html渲染流程

  1. 浏览器断开连接,四次挥手。

    一个http请求-响应,就会触发一次三次握手,四次挥手。

    http 1.1 有相关长连接(keep-alive)设置。一个长连接会保持一段时间,重复用于发送一系列请求,节省了新建 TCP 连接握手的时间,还可以利用 TCP 的性能增强能力。当然这个连接也不会一直保留着:连接在空闲一段时间后会被关闭(服务器可以使用 Keep-Alive 协议头来指定一个最小的连接保持时间)。

    更多阅读:计算机网络-HTTP系列

阅读全文 »

常见的网络攻击

注入攻击(Injection)

常见的是SQL注入攻击。

前端传入用户输入的数据,后端不进行校验直接拼接SQL语句进行处理,容易发生注入攻击。

SQL注入漏洞可以让攻击者直接对网站数据库执行构造好的SQL语句,在无需用户权限的情况下即可实现对数据的访问、修改甚至是删除。

阅读全文 »

为什么会有跨域问题

确保Web安全是十分重要的,避免数据窃取和受到不必要的攻击。所以浏览器中的同源策略,限制了一个源(origin)中加载的文档或脚本与其他源(origin)中的资源交互的方式,是为了隔离潜在恶意文档的关键安全机制,减少可能被攻击的媒介,是重要的安全策略

同源:如果两个 URL 的 protocolport (如果有指定的话)和 host 都相同的话,则这两个 URL 是同源。这个方案也被称为“协议/主机/端口元组”,或者直接是 “元组”。(“元组” 是指一组项目构成的整体,双重/三重/四重/五重/等的通用形式)。

同源

跨源网络访问

阅读全文 »

《高性能HTML5》读书笔记

面试题

页面渲染优化

  • HTML文档结构层次尽量少,最好不深于六层;
  • 脚本加载放在;
  • 少量首屏样式内联放在标签内;
  • 样式结构层次尽量简单;
  • 在脚本中尽量减少DOM操作,尽量缓存访问DOM的样式信息,避免过度触发回流;
  • 减少通过JavaScript代码修改元素样式,尽量使用修改class名方式操作样式或动画;
  • 动画尽量使用在绝对定位或固定定位的元素上;
  • 隐藏在屏幕外,或在页面滚动时,尽量停止动画;
  • 尽量缓存DOM查找,查找器尽量简洁;
  • 涉及多域名的网站,可以开启域名预解析

浏览器缓存原理

浏览器向服务器首次发起请求后拿到请求结果,会根据响应报文中HTTP头的缓存标识,决定是否缓存结果。如果需要进行缓存,则将请求结果和缓存标识存入浏览器缓存中。

浏览器每次发起请求,都会在浏览器缓存中查找当前请求结果及缓存标识。

浏览器缓存策略

  • 浏览器在加载资源时,向浏览器缓存中查找请求结果。如果存在请求结果,则根据缓存标识expirescache-control来判断是否命中强缓存,是则直接从缓存读取资源,不会发请求到服务器。如果不存在请求结果,则发送请求到服务器。
  • 存在请求结果,但是不是强缓存或强缓存已失效,浏览器一定会发送一个请求到服务器,通过响应首部字段的last-modifiedetag验证资源是否命中协商缓存,如果是,服务器会将这个请求返回,但是不会返回这个资源的数据,依然是从缓存中读取资源。
  • 如果前面两者都没有命中,直接从服务器加载资源。
阅读全文 »

this

this 实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用

调用位置:函数在代码中被调用的位置。

当一个函数被调用时,会创建一个活动记录(执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方式、传入的参数等信息。this就是这个记录的一个属性,会在函数执行的过程中用到。

找到this的绑定,最重要的是要分析调用栈(就是为了到达当前执行位置所调用的所有函数)。

绑定规则

阅读全文 »