【JavaScript】高频面试题-在地址栏输入网址之后都干了什么?

1,831 阅读10分钟

1. 客户端、服务器端

  • 客户端:可以向服务器发请求,并接收返回的内容进行处理
  • 服务器端:能够接收客户端请求,并且把相关资源信息返回给客户端的

=> 当前电脑既可以充当服务端又可以充当客户端。因此,如何区分是服务端还是客户端:不是针对于某一台机器的,而是针对于功能、需求的

2. 地址栏输入网址之后都发生了哪些操作?

  • 请求阶段
    • URL地址解析
    • DNS域名解析
    • 客户端与服务端建立TCP连接(三次握手)
    • 把客户端信息传递给服务器端(发送HTTP请求)
    • 服务器得到并处理请求(HTTP响应内容)
  • 响应阶段
    • 客户端渲染服务器返回的内容
    • 和服务端断开TCP连接(四次挥手)
七步
七步

2.1 URL/URI地址解析

2.1.1 URL/URI/URN

  • URI(Uniform Resource Identifier):统一资源标识符,URL和URN是URI的子集
  • URL(Uniform Resource Locator):统一资源定位符,根据这个地址能找到对应的资源
  • URN(Uniform Resource Name):统一资源名称,一般指国际上通用的(标准的)名字(例如:国际统一发版的编号)不常用

2.2.2 一个完整的URL所包含的内容

http://www.baidu.com/s?wd=index&name=ll#hash

协议 (http://): 传输协议就是,能够把客户端和服务端通信的信息,进行传输的工具(类似于快递员)

  • http:超文本传输协议 ,除了传递文本之外,还可以传递媒体资源文件(或者流文件)及XML格式数据
  • https:更加安全的HTTP,一般涉及支付的网站都要采用https协议(支付宝、淘宝、天猫、GitHub、百度等网站),s是SSL,加密传输
  • ftp:文件上传协议(大资源的东西),一般应用于把本地资源上传或下载到服务器端
    • filezilla:ftp上传工具,通过这个工具基于ftp传输协议,可以把本地的文件上传到服务器上

域名(www.baidu.com): 一个让用户方便记忆的名字

  • 顶级域名 qq.com 买域名买的就是顶级域名-万网
  • 一级域名 www.qq.com
  • 二级域名 sports.qq.com
  • 三级域名 kbs.sports.qq.com
  • .com 国际域名
  • .cn 中文域名
  • .com.cn
  • .edu 教育
  • .gov 政府
  • .io 博客
  • .org 官方组织
  • .net 系统类

端口号(80): 端口号的取值范围0~65535,使用端口号来区分同一台服务器上的不同项目

  • http默认端口号是80
  • https默认端口号是443
  • ftp默认端口号是21
  • 如果项目采用的就是默认端口号,我们在书写地址的时候,不用加端口号,浏览器在发送请求的时候会帮我们默认给加上

请求资源路径名称(/s):

  • 默认的路径名称或者名称(xxx.com/stu/ 不指定资源名,服务器会找默认的资源,一般默认资源名称是default.html / index.html...当然这些可以在服务器端自己配置,如果都不写,找不到会显示404)

  • 注意伪URL地址的处理:(URL重写技术是为了增加SEO搜索引擎优化的,动态的网址一般不能被搜索引擎收录,所以我们要把网址静态化,此时需要的是重写URL)

     举例:https://item.jd.hk/23457607363.html=>它可能改写的是这个网址 https://item.jd.hk/index.php?id=23457607363
    

问号传参信息( ?wd=index&name=ll)

  • 客户端想把信息传递给服务器,有很多的方式
  • URL地址的问号传参
  • 请求报文传输(请求头和请求主体)
  • 也可以实现不同页面之间的信息交互,例如:从列表到详情

HASH值(#hash)

  • 也可以充当信息传输的方式
  • 锚点定位
  • 基于HASH实现路由管控(不同的HASH值,展示不同的组件和模块)

2.2.3 URL的字符编码

请求地址中如果出现非有效Unicode编码内容,现代版浏览器会默认的进行编码

  • 基于encodeURI编码,我们可以基于decodeURI解码,我们一般用encodeURI编码的是整个URL,这样整个URL中的特殊字符都会自动编译
  • encodeURIComponent / decodeURIComponent它相对于encodeURI来说,不用于给整个URL编码,而是给URL部分信息进行编码(一般都是问号传参的值编码)

=> 客户端和服务端进行信息传输的时候,如果需要把请求的地址和信息编码,我们则基于以上两种方式处理,服务器端也存在这些方法,这样就可以统一编码解码了

  • 客户端还存在一种方式,针对于中文的编码方式 escape / unescape,这种方式一般只应用于客户端页面之间自己的处理,例如:从列表跳转到详情,我们可以把传递的中文信息基于这个编码,详情页获取编码后的信息再解码,再比如我们在客户端种的cookie信息,如果信息是中文,我们也基于这种办法编码...

2.2 DNS服务器域名解析

DNS服务器:域名解析服务器,在服务器上存储着 域名<=>服务器外网IP 的相关记录 而我们发送请求时候所谓的DNS解析,其实就是根据域名在DNS服务器上查找到对应服务器的外网IP

2.2.1 DNS优化

  • DNS缓存:一般浏览器会在第一次解析后,默认建立缓存,时间很短,只有一分钟左右
  • 减少DNS解析次数:一个网站中我们需要发送请求的域名和服务器尽可能少即可
  • DNS预获取(dns-prefetch):在页面加载开始的时候,就把当前页面中需要访问其他域名(服务器)的信息进行提前DNS解析,以后加载到具体内容部分可以不用解析了
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <!-- DNS预获取 -->
    <!-- <meta http-equiv="x-dns-prefetch-control" content="on">
    <link rel="dns-prefetch" href="//static.360buyimg.com">
    <link rel="dns-prefetch" href="//misc.360buyimg.com">
    <link rel="dns-prefetch" href="//img10.360buyimg.com">
    <link rel="dns-prefetch" href="//img11.360buyimg.com">
    <link rel="dns-prefetch" href="//img12.360buyimg.com"> -->
    <title>AJAX</title>
    <script>
        // let link = document.getElementById('link');
        // console.log(link);
    </script>
</head>

2.3 建立TCP连接(三次握手)

关于三次握手以及下面的四次挥手,可以看掘金上这位博主的:三次握手

三次握手
三次握手

2.4 发送HTTP请求

http事务 / http请求: 都是指的一次完整的http请求(请求+响应)

2.4.1 HTTP报文

HTTP报文查看
HTTP报文查看

谷歌浏览器中F12 => network(所有客户端和服务器端的交互信息在这里都可以看到) => 点击某一条信息,在右侧可以看到所有的HTTP

  • 请求报文:所有经过传输协议,客户端传递给服务器的内容,都被称为请求报文
    • 起始行
    • 请求头:前端设置的 有些是默认设置, 也可以前端自己设置;
    • 请求主体
  • 响应报文:所有经过传输协议,服务器返回给客户端的内容,都被称为响应报文
    • HTTP状态码
    • 响应头: 是后台给的 前端没办法修改
    • 响应主体
  • HTTP报文:请求报文 + 响应报文

2.4.2 强缓存与协商缓存

强缓存 这种请求是到不了后台的;直接是从本地缓存中获取资源然后相应这个请求

  • Expires: 过期时间,在这个过期时间之内 的请求,都会直接从本地缓存获取资源;
  • cache-control: max-age=3600 ; max-age 缓存的有效时间;3600秒

协商缓存 协商缓存:如果没有命中强缓存 ,才会有可能走协商缓存,

  • 确实是去后台要东西了;但是后台告诉前端,这个请求可以使用缓存的内容;(304)
  • etag/if-none-match :etag是后端生成的一个字符串;那么下一次请求的时候 浏览器会在请求头中添加一个if-none-match 的属性
    • 这个属性对应的值 就是后台给的etag对应的值
  • last-modified/if-modified-since : last-modified 后端生成的一个时间,其实就是当前请求对应的内容最后一次更改的时间,下一次请求,请求头中 会带上 if-modified-since这个属性值是 last-modified 对应的值;

2.5 服务器得到并处理请求(HTTP响应内容)

2.5.1 HTTP状态码

1~5开头,三位数字,其中1开头的出现频率极低。

  • 200 OK:成功
  • 201 CREATED:一般应用于告诉服务器创建一个新文件,最后服务器创建成功后返回的状态码
  • 204 NO CONTENT:对于某些请求(例如:PUT或者DELETE),服务器不想处理,可以返回空内容,并且用204状态码告知
  • 301 Moved Permanently:永久重定向(永久转移)
  • 302 Moved Temporarily:临时转移,很早以前基本上用302来做,但是现在主要用307来处理这个事情,307的意思就是临时重定向Temporary Redirect =>主要用于:服务器的负载均衡等
  • 304 Not Modified:设置HTTP的协商缓存
  • 400 Bad Request:传递给服务器的参数错误
  • 401 Unauthorized:无权限访问
  • 404 Not Found:请求地址错误
  • 500 Internal Server Error:未知服务器错误
  • 503 Service Unavailable:服务器超负荷

2.6 客户端渲染服务器返回的内容

渲染树
渲染树

2.6.1 同步异步加载

遇到link/img/audio/video等是异步去加载资源信息(浏览器分配一个新的线程去加载,主线程继续向下渲染页面),如果遇到的是script或者@import,则让主线程去加载资源信息(同步),加载完成信息后,再去继续渲染页面

2.6.2 浏览器渲染页面的步骤

  • 处理 HTML 标记,构建 DOM 树
  • 处理 CSS 标记,构建 CSSOM 树
  • 将 DOM 树和 CSSOM 树融合成渲染树
  • 根据生成的渲染树,计算它们在设备视口(viewport)内的确切位置和大小,这个计算的阶段就是回流 => 布局(Layout)或 重排(reflow)
  • 根据渲染树以及回流得到的几何信息,得到节点的绝对像素 => 绘制(painting)或栅格化(rasterizing)

2.6.3 DOM的重绘与回流(重排)

  • 重绘:元素样式的改变(但宽高、大小、位置等不变)
  • 回流:元素的大小或者位置发生了改变(当页面布局和几何信息发生变化的时候),触发了重新布局,导致渲染树重新计算布局和渲染
  • 注意:回流一定会触发重绘,而重绘不一定会回流

2.6.4 前端性能优化:避免DOM的回流

  • 放弃传统操作DOM的时代,基于vue/react开始数据影响视图模式
  • 分离读写操作(现代浏览器都有渲染队列的机制)
    • 发现某一行要修改元素的样式,不立即渲染,而是看看下一行,如果下一行也会改变样式,则把修改样式的操作放到“渲染队列中”...一直到不在是修改样式的操作后,整体渲染一次,引发一次回流
    • offsetTop、offsetLeft、offsetWidth、offsetHeight、clientTop、clientLeft、clientWidth、clientHeightscrollTop、scrollLeft、scrollWidth、scrollHeight、getComputedStyle、currentStyle....会刷新渲染队列
  • 样式集中改变
  • 缓存布局信息
  • 元素批量修改
  • 动画效果应用到position属性为absolute或fixed的元素上(脱离文档流)
  • CSS3硬件加速(GPU加速)
  • 牺牲平滑度换取速度
  • 避免table布局和使用css的javascript表达式

2.7 和服务端断开TCP连接(四次挥手)

  • 第一次挥手:由浏览器发起,发送给服务器,我请求报文发送完了,你准备关闭吧
  • 第二次挥手:由服务器发起,告诉浏览器,我接收完请求报文了,我准备关闭,你也准备吧;
  • 第三次挥手:由服务器发起,告诉浏览器,我响应报文发送完毕,你准备关闭吧;
  • 第四次挥手:由浏览器发起,告诉服务器,我响应报文接收完毕,我准备关闭,你也准备吧;
四次挥手
四次挥手