深入理解从输入一个url到页面展示都发生了什么

338 阅读3分钟

协议

URL:url - 资源定位符

三种
1. http://
追问:http和tcp
2. https://
3. file:///c:/User   本地文件地址,只在本机打开

http://

追问:http和tcp

  1. http - 应用层 tcp - 传输层
  2. 关联:http是基于tcp来实现连接的 => http请求、发送、断开
    • http:1.0
      浏览器每次请求都与服务器建立一次TCP连接
    • http:1.1
      keep-alive - 保持tcp的连续畅通,不用反复的建立连接(复用同一条tcp通道)
    • http:2.0
      多条并发请求复用同一条通路 - 复用通路(无并发限制) chrome限定了最大通路是6条
  3. 差异:
    • http - 无状态连接
    • tcp有状态 优化点:
    • socket 连接 封装化的tcp,让我们的应用更加方便的调用
    • socket是长连接,可以及时通讯,服务端可以及时通知客户端

https://

追问:http和https

  1. https是什么? https = http + ssl(TLS) 位于TCP协议与各种应用层协议之间
  2. 原理: 加密逻辑

image.png 3. HTTPS多次连接:导致网络请求加载时间延长,增加开销和功耗 优化: => 和并请求和长连接

中间层 整合请求时 - 异常处理

域名解析

  1. 浏览器缓存中 - 浏览器中会缓存DNS一段时间
  2. 系统缓存 - 系统中找缓存 -> HOST
  3. 路由器缓存 - 各级路由器缓存域名信息
  4. 运营商地方站点的缓存信息 - partner
  5. 根域名服务器

优化:CDN - Content Delivery Network

作用:

  1. 给同一个主机配置多个IP地址
  2. 负载均衡 => 缓存 => 各级缓存 => 浏览器区分缓存(强缓存 弱缓存)

web服务器

apache ngnix

  1. 接收请求 => 传递给服务端代码
  2. 通过反向代理 => 传递给其他服务器
  3. 不同的域名 => 指向相同ip的服务器 => ngnix域名解析 => 引导到不同的服务监听端口

服务 涉及到网络优化

手写并发 QPS

面试:并发优化 10个请求,由于后台或者业务需求,只能同时执行三个

分析:

  1. 输入:promise数组,limit参数
  2. 存储:reqpool - 并发池
  3. 思路:塞入+执行
function qpsLimit(requestPipe, limitMax) {
    let reqPool = []
    let reqMap = new Map()

    // 往并发池里塞入promise
    const add = () => {
        // shift: 把数组的第一个元素从其中删除,并返回第一个元素的值
        let _req = requestPipe.shift();
        reqPool.push(_req)
    }
    // 执行实际请求
    const run = () => {
        if (requestPipe.length === 0) return;
        // 池子满了发车后,直接race,但凡有一个请求完成
        let _finish = Promsie.race(reqPool)
        _finish.then(res => {
            // 做一个id整理
            let _done = reqPool.indexOf(_finish)
            reqPool.splice(_done, 1);
            add();
        })
        run();
    }

    while (reqPool.length < limitMax) {
        add()
    }
    run()
}

浏览器渲染时

image.png

浏览器执行顺序

主线: HTML => DOM + CSSOM => renderTree + js => layout => paint
支线: repaint - 改变文本颜色等
reflow - 元素集合尺寸变了
=> 优化点:减少repaint 避免reflow
display:none => reflow
visibility:hidden => repaint

脚本执行时 - JS

mark & sweep => 触达标记,锁定清空,未触达直接抹掉

    const zhaowa = {
        js: {
            performance: 'good',
            teacher: '云隐'
        }
    }

    // 建立引用关系
    const _obj = zhaowa

    // 引用源给替换掉了 - 暂未gc
    zhaowa = 'best'

    // 深入层级做引用 - 暂未gc
    const _class = _obj.js

    // 引用方替换 - 暂未gc
    _obj = 'over'

    // gc 完成
    _class = null

垃圾回收

  1. 内存分配:申明变量、函数、对象
  2. 内存使用:读写内存
  3. 内存释放

注意点:

  1. 对象层级,宜平不宜深
  2. 深层引用最好深拷贝,或者用完直接销毁
  3. 避免循环引用

内存泄漏

  1. 全局变量
    function foo() {
        bar1 = ''
        this.bar2 = ''
    }
  1. 未清理的定时器
setInterval(() => {}, 1000)
  1. 使用后的闭包
    function zhaowa() {
        const _no = 1
        return {
            number: _no
        }
    }

打包配置优化

  1. 懒加载
  2. 按需加载
  3. 抽离公共