输入一个网址回车后发生了什么

211 阅读3分钟

DNS解析, 将域名解析成ip地址

TCP3次握手

TCP

三次握手

  • 第一次: 确保client能向server发送数据
  • 第二次: 确保serve能够收到client发来的数据, 确保server能向client发送数据
  • 第三次: 确保client能够收到server的数据

四次挥手

  • 第一次: client@server: 数据发送完毕
  • 第二次: server回复client: 收到,数据接收中......
  • 第三次: server@client: 数据接收完毕
  • 第四次: client回复server: 收到

通过微信聊天理解4次挥手

_cgi-bin_mmwebwx-bin_webwxgetmsgimg??&MsgID=5375522111797134824&skey=@crypt_af27056f_f96c0ef480de27e0dc191daea0c74100&mmweb_appid=wx_webfilehelper.jpg

UDP

  • UDP类似发短信,就算对方关机,也能将数据发出去
  • TCP类似打电话,需要先拨通,建立连接后再传输数据
  • http是基于tcp的

浏览器发送http请求获取数据

服务器根据http请求返回数据

浏览器接收数据

浏览器渲染数据(如下图)

graph LR

构建dom树 --> 渲染树

构建cssom树 --> 渲染树

渲染树 --> 布局树
布局树 --> 分层
分层 ---> 绘制渲染树

  • 网络线程收到html文件后会产生一个渲染任务
  • 渲染主线程 通过事件循环的方式处理这个渲染任务

html解析

两颗树

  • 生成 document object model tree
  • 生成 css object model tree

阻塞解析

css不会阻塞解析

渲染主线程 在解析html的过程中遇到 css 不会暂停

js会阻塞解析

远古时期的 <script/>

  • 渲染主线程 在解析html的过程中遇到 javaScript 会暂停
  • 需要等待js下载
  • 需要等待js执行完毕
  • 一般将这种标签放到html文件的最下面
 <script src="myscript.js"></script>

async

  • 不需要等待js下载
  • 需要等待js执行完毕
 <script async src="myscript.js"></script>

defer

  • 不需要等待js下载
  • 不需要等待js执行完毕
  • js的执行会在所有元素解析完成之后
 <script defer src="myscript.js"></script>

样式计算

DOM树🌲 + CSSOM树🌲 => 带有样式的DOM树🌲(样式树)

布局

  • 确定尺寸
  • 确定位置

分层

将经常变动的元素单独放到一个图层,防止其对别的元素造成影响

绘制

  • 对每一图层生成绘制指令
  • 渲染主线程任务到此结束
  • 接下来会将绘制指令发送给合成线程处理

重绘重排

重排: reflow

  • reflow的本质是重新构建布局树
  • reflow 一定会导致 repaint
  • 修改元素大小,读取元素大小都会引起重排

为什么读取元素尺寸会引起重排

  • 为了防止连续触发重排
  • 修改元素大小时,触发的重排是异步的
  • 因为修改元素大小时,触发的重排是异步的,
  • 为了读到正确的宽度
  • 读取元素尺寸会立马引起重排,确保读取的是最新值
  • 修改元素大小会引起异步重排
  • 读取元素大小会引起同步重排
// `修改元素大小`会引起`异步重排`, 防止连续触发重排
dom.style.width = '900px'
dom.style.width = '800px'
dom.style.width = '700px'
dom.style.width = '600px'
// 读取元素尺寸会立马引起重排,确保读取的是最新值
const w = dom.clientWidth
console.log(w)

重绘: repaint

  • 改变了字体颜色
  • 改变了背景颜色

为什么transform效率高

  • transform 的处理不在 渲染主线程上
  • transform 的处理在 合成线程上线程上
  • transform 不会引起重绘重排
  • 就算js卡死,也不会影响到 transform
  • 因为js的执行在渲染主线程上, transform 的执行在 合成线程上线程上互不影响

<!DOCTYPE html>
<html>
    <style>
        .ball {
            width: 100px;
            height: 100px;
            background: red;
            border-radius: 50%;
        }
        .b1 {
            animation: b1 1s alternate infinite;
        }
        .b2 {
            animation: b2 1s alternate infinite;
            position: fixed;
            left: 0;
        }
        @keyframes b1 {
            to {
                transform: translate(100px)
            }
        }
        @keyframes b2 {
            to {
                left: 100px
            }
        }
    </style>


    <body>
        <button onclick="sleep()" >卡死</butto>
        <p class="ball b1"></p>
        <p class="ball b2"></p>
    </body>
</html>

<script>
function sleep(time=3000) {
    const start = getTime()
    while(getTime() - start < time) {}
    console.log('week up!!!')
}

function getTime() {
	return new Date().getTime()
}
</script>