地址栏输入 URL 敲下回车后发生了什么?

第一步 URL解析

URI:URL+URN

  • URI 统一资源标识符
  • URL 统一资源定位符
  • URN 统一资源名称

传输协议:

  • HTTP 超文本传输协议
  • HTTPS HTTP+SSL(加密证书) 相对于HTTP来讲会更加安全
  • FTP 文件的传输,例如:FTP上传工具、FTP资源共享
    HTTP明文传输 HTTPS密文传输 SSL整数中定义了加密解密的方式

域名:服务器有一个外网IP,基于外网IP,而域名就是给外网IP设置一个好记的名字

  • 购买的是baidu.com顶级域名
  • www.baidu.com一级域名
  • img.baidu.com二级域名
  • xx.img.baidu.com三级域名

端口号:区分同一台服务器上的不用服务(或项目)的值

  • 取值范围:0~65535
  • 默认值:我们自己不写端口号,浏览器默认加的 HTTP->80 HTTPS->443 FTP->21

编码问题:如果URL地址或者问号传参的信息中,出现中文或者某些特殊符号,传输中可能会乱码,此时需要客户端先进行编码,服务器再解码

  • encodeURI/decodeURI 一般用于对整个URL的编码,它只编码中文和部分特殊符号,对URL地址中的有效符号不编码
  • encodeURIComponent/decodeURIComponent 一般用于对URL问号传参的值进行部分编码,因为除了encodeURI可以编码的东西外,对于URL地址中的有效符号也能编码,所以不适合整个URL
  • escape/unescape(服务器端没有这个) 不是所有后端语言都支持这个API,所以只用于客户端两个页面间数据传输的编译
let url = `http://www.xx.com/首页.html?lx=0&name=张三`
console.log(encodeURI(url));//只对中文进行编码
let url = `http://www.xx.com/?lx=0&name=${encodeURIComponent('张@三')}&form=${encodeURIComponent('http://www.wx.com/')}`
console.log(url);
console.log(escape('黑马@培训::/'));//:编码 /没有编码

第二步 缓存检查

“缓存”存储在哪?

  • 虚拟内存(内存条):页面关闭,存储的东西会消失 临时缓存 Mermory Cache
  • 物理内存(硬盘):持久存储 Disk Cache
    (读内存的东西时间会更快)
    关闭页面,内存里的就没了。
    打开页面,查找disk cache中是否有匹配的,如有则使用,如没有则发送网络请求
    普通刷新(F5):因TAB没关闭,所以mermory cache是可用的,会被优先使用,其次才是disk Cache
    强制刷新(Ctrl+F5):浏览器不使用缓存,因此发送的请求头部均带有Cache-control:no-cache,服务器直接返回200和最新内容
    关于静态资源文件的缓存有两种:强缓存、协商缓存
  • 不论哪一种,都是服务器设置规则,客户端浏览器会自动配合完成,无需我们写代码
  • 一般真实项目中,强缓存、协商缓存都会设置[也可以只设置一个],强缓存失效的情况下,再去走协商缓存的机制。
    强缓存:Cache-Control(HTTP/1.1)、Expires(HTTP/1.0)服务器设置的响应头信息
  • cache-control: max-age=2592000
  • expires: Wed, 17 Aug 2022 06:14:14 GMT
  • 不论是从服务器获取还是从缓存中读取,HTTP状态码都是200
    浏览器对于强缓存的处理:根据第一次请求资源时返回的响应头来确定的
    • Expires:缓存过期时间,用来指定资源到期的时间HTTP/1.0
    • Cache-Control:cache-control: max-age=2592000第一次拿到资源后的2592000秒内,再次发送请求,读取缓存中的信息(HTTP/1.1)
    • 两者同时存在的话,Cache-Control优先级高于Expires
    • 把请求结果和缓存标识存储到浏览器中
      存在问题:如果本地缓存生效,但是服务器更新了这个资源,如何保证客户端可以获取最新的?
      HTML页面资源“绝对不能”做强缓存,因为其是页面渲染的入口,所有其他资源也是在渲染解析HTML代码的时候,再去请求的
  • 如果服务器某个资源更新,生成新的文件名,html中导入新的文件,webpack搞定
  • 或者文件名一样,但是一更新,会在后面拼接一个新的时间戳
    协商缓存:哪怕本地有缓存,也要去和服务器进行协商
    第一次请求页面,本地没有缓存,向服务器发送请求,如果需要设置协商缓存,服务器会在响应头中返回:
    Last-Modified(记录资源最后一次更新时间)/ETag(记录资源最后一次更新的标识);客户端浏览器看到标识后,把标识和资源都缓存起来
    第二次请求,也会向服务器发送请求,并且在请求头中,基于If-Modified-Since/If-None-Match分别把存储的Last-Modified/ETag值传递给服务器,服务器获取标识后,和本地资源(最新更新时间/标识)作对比
    • 如果资源没有更新过,则时间/标识是一致的,服务器返回304;客户端发现是304,则从本地缓存中获取
    • 如果资源更新了,则时间/标识是不一致的,服务器返回200和最新的内容以及最新的Last-Modified/ETag,客户端把最新的信息存储起来
      好处:保证服务器资源一旦更新,就会发现。
      真实项目开发:建议大家:HTML只设置协商缓存,其余资源强缓存和协商缓存都去设置(都是由服务器设置的)
      强缓存没有失效,不会在请求头携带那些东西,协商缓存不会生效。

数据缓存:前端开发者,基于本地存储方案,对于不经常更新的数据请求,做的缓存处理

  • 第一次从服务器获取数据,存储在本地[设置一个有效周期]
    本地存储方案:受“源”和“浏览器”的限制
    • cookie
      具备有效期,设置cookie的时候自己设置
      最多只允许存储4kb
      cookie和服务器:在非跨域请求下,如果本地有cookie,不论服务器是否需要,每一次发送请求,都默认把cookie基于请求头传递给服务器[好处:如果需要把cookie传递给服务器,比较省事;坏处:如果cookie比较多,每一次请求都携带大量的信息进行传递,把请求变慢]
      cookie不稳定:清除历史记录,可能会清掉cookie,浏览器的无痕模式,不会记录cookie
    • localStorage
      持久化存储,除非自己手动删除或者写在浏览器
      最多允许存储5mb的内容
      localStorage默认和服务器是没有关系,除非自己手动把它存的信息传递给服务器,否则就是客户端存储
      localStorage相对比较稳定一些
    • sessionStorage
      会话存储,页面刷新存储的信息会在;页面关闭,存储的信息会消失
    • 虚拟内存存储[例如:全局变量,vuex]
      页面刷新或者关闭,存储的信息都会释放(内存释放了)
  • 以后再发送请求,我们校验本地是否有此数据的缓存(而且是否在有效期内)
    • 如果没有:向服务器发送新的请求,获取最新的数据
    • 如果有:直接从本地存储的数据中拿出来渲染
//设定具备有效期的localStorage存储方案
const storage = {
    set(key, value) {
        localStorage.setItem(key, JSON.stringify({
            time:+new Date(),
            value,
        }));
    },
    get(key, cycle=60000) {
        //默认1分钟
        cycle = +cycle;
        if(isNaN(cycle)) cycle = 6000;
        let data = localStorage.getItem(key);
        if(!data) return null;
        let {time, value} = JSON.parse(data);
        if((+new Date() - time) > cycle) {
            //超过有效期 也不获取值
            storage.remove(key);
            return null;
        } 
        //在有效期内,才获取值
        return value;
    },
    remove(key) {
        localStorage.removeItem(key);
    }
}

第三步 DNS解析[域名解析]

浏览器地址栏输入域名,会去DNS服务器上找到对应的外网IP,然后基于服务器的外网IP,找到服务器
DNS解析本身也有缓存,DNS解析记录也会有缓存[谷歌浏览器大概记录1min]
前端优化:尽可能减少DNS解析需要的时间

  • 正常:减少DNS解析的次数(也就是所有资源,尽可能都部署到,相同服务器的相同服务下)
  • 真实:我们会把不同资源分不同的服务器部署[web服务器 图片服务器 数据服务器]
    • 合理使用资源
    • 提高并发数
      导致域名解析的次数增加,DNS解析需要的时间也会增加
      DNS Prefetch:DNS预解析,利用的异步性,在GUI渲染过程中,同时去解析域名

第四步 TCP的三次握手[让客户端和服务器端建立一个’稳定可靠’的传输通道]

  • TCP:稳定可靠,因为经过三次握手确定传输的稳定性,消耗时间久
  • UDP:快速传输,省略三次握手的步骤,直接进行传输,可能存在丢包的情况

第五步 数据传输

  • HTTP请求报文:请求头、请求起始行、请求主体
  • HTTP响应报文:响应头、响应起始行、相应主题
    在控制台的NetWork中都可以看到

第六步 TCP的四次挥手[断开客户端和服务器端的链接通道]

  • HTTP/1.1版本开始,默认了开启Connection:keep-alive长连接,当前请数据传输完成后,建立的通道不会被立即释放,下一次请求,继续基于这个通道传输,减少了TCP四挥三卧的规程,加快数据传输的速度

第七步 页面渲染

  • DOM TREE
  • CSSOM TREE
  • RENDER TREE
  • Layout [回流/重排]
  • 分层
  • painting

性能优化汇总
1.利用缓存

  • 对于静态资源文件实现强缓存和协商缓存(扩展:文件有更新,如何保证及时刷新?)
  • 对于不经常更新的接口数据采用本地存储做数据缓存(扩展:cookie / localStorage / vuex|redux 区别?)

2.DNS优化

  • 分服务器部署,增加HTTP并发性(导致DNS解析变慢)
  • DNS Prefetch

3.TCP的三次握手和四次挥手

  • Connection:keep-alive

4.数据传输

  • 减少数据传输的大小
    • 内容或者数据压缩(webpack等)
    • 服务器端一定要开启GZIP压缩(一般能压缩60%左右)
    • 大批量数据分批次请求(例如:下拉刷新或者分页,保证首次加载请求数据少)
  • 减少HTTP请求的次数
    • 资源文件合并处理
    • 字体图标
    • 雪碧图CSS-Sprit
    • 图片的BASE64

5.CDN服务器“地域分布式”
6.采用HTTP2.0

  • 网络优化是前端性能优化的中的重点内容,因为大部分的消耗都发生在网络层,尤其是第一次页面加载,如何减少等待时间很重要“减少白屏的效果和时间”
    • LOADDING 人性化体验
    • 骨架屏:客户端骨屏 + 服务器骨架屏
      • 首屏数据由服务器渲染 SSR
      • 其他屏的数据还是客户端渲染,在没有获取到数据之前,我们基于灰色的框框占位,拿到数据之后替换掉
    • 图片延迟加载
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值