💯 http 1.0 1.1 1.2 区别

http 1.0 和 http 1.1 的区别

  • 长连接

    • http 1.0打开一个tcp/ip连接后只用来发送一个http 请求,发完后tcp/ip连接关闭。
    • http 1.1打开一个 tcp/ip连接后可以发送多个 http请求,发完后如果上一个http请求报文中有 connection: keep-alive,服务端在返回应答报文以后不把tcp/ip连接关闭,如果是connection: close,那么tcp/ip连接关闭。
  • 节约带宽

    • http 1.0存在带宽浪费的现象,比方说,某时刻发送端http请求报文里有一个token,但是这个 token已经过期了,http 1.0会把整个报文发送给接收端,服务端看到报文是过期的,返回错误码401,连接终止。但是其实发送整个html完全没有必要,我们完全可以先发送 html head先试探一下,如果返回401则不再发送 body,否则再继续发送body,这种分块发送的思想 http 1.1可以做到。
  • host域

    • 一个ip地址可以对应多个虚拟主机,每个虚拟主机对应一个host,http 1.1有host这个字段。
  • 缓存

    • http 1.0使用expire头来判断本地缓存的资源是否过期,通过发送if-modified-since验证服务端的last-modified看资源是否有更新,其中,expire,if-modified-since和last-modified都是绝对时间,你可以简单的理解为一个Date对象
    • http 1.1引入了更多的缓存策略,比如cache-control,entity-tag和if-non-match,你可以理解cache-control是一个基于时间的相对值,而 entity-tag和if-non-match你可以理解为是一个服务端根据文件计算出来的hash值(可能不是hash值,但你可以这么理解)。为什么要有一套etag/if-non-match又有一套last-modified/if-modified-since,你可以这么理解,假如说服务端的一个文件被频繁修改,那么使用 last-modified/if-modified-since 会比较好,因为直接更新时间就可以了,但是会存在服务端发送端计时器不统一的问题;如果一个文件不是那么频繁地被更新,那么使用计算hash值生成etag/if-non-match的方式则会更好。
  • 新增状态码

    • http 1.1新增了一些状态码,比如410代表某个资源被永久性的删除。

http 1.1 和 http 2.0 的区别

  • 多路复用

    • http 2.0可以在一个tcp/ip连接上并发的发送多个http请求,不必等待上一个http请求返回请求报文。虽然http 1.1可以启动多个tcp/ip连接来达到并发,但是tcp/ip连接本身的建立也会产生额外的性能开销。
  • 头部压缩

    • http报文分为三个部分,状态行,头部,主体。http 1.1会对主体进行压缩,但不会压缩头部,http 2.0使用hpack算法对header进行压缩。
  • 服务器推送

    • 比方说,一个资源服务器上有html,css,js,http 1.1会在浏览器解析html的时候再次发送请求,请求css和js资源。但是http 2.0会在浏览器第一次请求html的时候,检查这个html引用的资源,如果被引用的资源刚好也在这台服务器上,那么服务器会自动地把被引用的资源,比如,css,js推送给浏览器。

💯 http协议_响应状态码_页面渲染流程_路由_中间件

  1. http协议

超文本传输协议

协议详细规定了 浏览器 和 万维网服务器 之间互相通信的规则

客户端与服务端通信时传输的内容我们称之为报文(请求报文、响应报文)

常见的发送 get 请求方式 在浏览器地址栏输入 url 地址访问

所有的标签默认发送的是 get 请求:如 script link img a...

form 表单默认也是 get 请求

常见的发送 post 请求方式 只能通过 form 表单,设置 method="post" 发送

ajax 可以发送任意请求 2. 响应状态码

告诉浏览器(接受响应),响应内容是怎么样的状态

1xx: 基本不用 2xx: 响应成功的状态 200

3xx: 请求资源重定向 302 请求的资源/网址重新定向到新的一个网址

304 请求的资源/网址重新定向到缓存中

4xx: 请求资源未找到 404 服务器没有问题,资源在服务器中找不到

5xx: 服务器内部错误 500 服务器出错了

  1. 从浏览器输入一个url地址(www.baidu.com),到最终页面渲染完成,中间发生了什么?

① DNS解析

将域名地址解析为 ip 地址

② TCP连接:TCP三次握手

第一次握手: 浏览器发送给服务器,告诉服务器,我将要发送请求了,你准备接受一下

第二次握手: 服务器发送给浏览器,告诉浏览器,我准备好了,你放马过来

第三次握手: 浏览器发送给服务器,告诉服务器,我真的要发了,你准备好

③ 发送请求报文

请求报文

④ 接受响应

响应报文

⑤ 渲染页面

遇到 html,调用 html 解析器,将 html 的 dom 结构解析为 dom 树

遇到 css,调用 css 解析器,将 css 样式解析 cssom 树

将 dom 树和 cssom 树组合在一起,形成 render 树

先布局 layout,再渲染 render

遇到 js,调用 js 引擎,解析 js 代码,如果 js 中有操作 dom,它会修改 dom 树,如果有修改样式,它会修改 cssom 树

将 dom 树和 cssom 树组合在一起,形成 render 树

先布局 layout,再渲染 render (页面重排和重绘)

⑥ TCP四次挥手 断开连接 ---- 断开浏览器发送的请求的链接,断开浏览器接受响应的链接

第一次挥手: 浏览器发送给服务器,告诉服务器,我东西(请求报文)发完了,你准备关闭吧

第二次挥手: 服务器发送给浏览器,告诉浏览器,我接受完了,我准备关闭,你也准备关闭吧

第三次挥手: 服务器发送给浏览器,告诉浏览器,我东西(响应报文)发完了,你准备关闭吧

第四次挥手: 浏览器发送给服务器,告诉服务器,我接受完了,我准备关闭,你也准备关闭吧

  1. 路由

组成:

请求方式 get(查) / post(增) / put(改) / delete (删) ....

路由路径 必须'/'开头 /shop/:id :id部分有params参数

回调函数(句柄函数)

req 请求信息 req.query 获取查询字符串参数 GET 请求

req.params 获取params参数

req.headers 获取请求头的所有信息

req.body 获取请求体参数 POST请求 (默认 express 框架是解析不了请求体数据的,要想解析需要引入中间件实现)

res 响应信息 注意:返回响应的方法有且只能设置一个,一旦有多个就会报错

res.download(文件相对路径) 返回响应,让浏览器自动下载指定文件

res.sendFile(文件绝对路径) 返回响应,让浏览器自动打开指定文件

res.end() 返回响应, 返回一个快速响应

res.json() 返回响应, 将传入的数据转化为json字符串返回

res.send() 返回响应, 根据传入的数据的类型,来自动判断添加相应的响应头来处理

res.redirect() 返回响应,请求资源重定向新的地址,默认响应状态码为302

res.get() 获取响应头的内容

res.set() 设置响应头的内容

res.status() 设置响应状态码

作用: 接受请求、返回响应 定义请求地址

使用: app.请求方式(路由路径, (request, response) => {});

request.query 参数(查询字符串参数): ?username=111&pwd=222

request.params 参数 : http://localhost:3000/hotel/123456 --> 123456就是params参数

  1. 中间件

本质是一个函数 (req, res, next) => {}

作用:做一些重复做的事情。(当有多个路由重复做同一件事,这时就会交给中间件完成)

通过app.use(中间件函数)

解析原理:

所有路由和中间件都在一个数组中,会按照 js 引擎解析代码的先后顺序添加路由和中间件

当请求发送到服务器的时候,服务器获取到当前的请求信息(请求方式、请求路由路径),

遍历数组,找到第一个匹配(请求路由路径和请求方式必须完全一致)到的路由或者中间件(默认接受处理所有请求),执行其回调函数

如果处理的是中间件,中间件内部如果调用了next()方法,还会接下来匹配下一个路由或者中间件

没找到,返回一个状态码为404的响应, Cannot GET /xxx Cannot POST /xxx

💯 web缓存

  1. web缓存主要有:数据库缓存、服务器缓存(代理服务器缓存、CDN缓存),浏览器缓存

  2. 浏览器缓存包括:http缓存、cookie缓存、local storage本地缓存

  3. http缓存的几个术语:1)缓存命中率:从缓存中得到的数据请求数与所有请求数的比例。比例越高缓存越好 性能越好;2)过期内容:超过设置的有效期的内容,这些内容需要重新从服务器请求新数据或者需要在服务器验证内容是否修改(如果修改服务器更新失效时间,并且返回最新内容进行缓存,同时返回状态码为200,如果没有修改,服务器直接返回状态码304,3)验证:向服务器发送请求,验证过期内容是否有效,有效则直接返回304并刷新缓存失效时间;4)失效:把失效的缓存内容清除;

4.http缓存设置:通过设置html的meta来控制页面缓存,具体实例如下:

<meta http-equiv=“Cache-control” content=“no-cache,max-age,must-revalidate,no-store”>

<meta http-equiv=“Pragma” content=“no-cache”>

<meta http-equiv=“Expires” content=“0”>

<meta http-equiv=“Cache” content=“no-cache”>
  1. 浏览器缓存分为强缓存和协商缓存,其具体加载页面流出如下:1)浏览器先根据http的请求头信息来判断是否命中强缓存,如果命中强缓存则直接加载缓存中的资源,不会去服务器请求新的资源;2)如果未命中强缓存,则会向服务器发送资源请求,服务器会直接验证相关的请求的资源是否在浏览器本地缓存失效,如果没有失效,则服务器不会返回资源信息,此时的状态码为304,浏览器直接从缓存中获取资源;3)如果未命中协商缓存,即服务器校验发现浏览器本地缓存内容失效,则返回新的请求资源并更新浏览器的缓存,此时的状态码为200

  2. 属性的具体讲解:

1)Cache-control:是一个相对时间,与客户端时间进行比较,从而来判断缓存是否失效,具体包括:max-age 最大失效时间,即在该时间内缓存都有效,单位为s,设置了max-age=0时,获取资源之前都需要先校验Etag和Last-modify,来判断资源是否进行修改,如果未修改服务器直接返回304,no-cache强制使用缓存前必须发送资源请求到服务器进行校验本地缓存是否有效;no-store 禁止使用缓存资源,必须去服务器请求新的资源;public 表示响应可以被任何对象(客户端、代理服务器 等)缓存;private 只能被单个对象(如操作系统等用户,浏览器)缓存,不能被代理服务器缓存;must-revalidate 告诉浏览器或者缓存服务器 在本地文件过期之前使用本地文件,本地文件一旦过期就要去服务器进行文件检验,如果服务器检验维修改则直接返回304(目前不常用)

2)Expires 响应头过期时间,需要和Last-modify一起使用,优先级低于Cache-control;Expires是以绝对时间,如果客户端时间更改则会导致客户端与服务器时间差造成缓存失效,因此才引入Cache-control

3)Pragma:用于向后兼容http1.0协议的缓存服务器,那时候的http1.1协议中还没有Cache-control

4)Last-Modified / If-Modified-Since:

浏览器第一次请求服务器资源的时候,服务器返回的响应头(response)中会加上Last-Modified,其是一个时间标示,表示资源的失效时间

当浏览器再次请求该资源的时候 请求头(request)中会带有If-Modified-Sinxe,其值就为缓存是的Last-Modified的值,去服务器进行校验缓存是否失效,未失效返回304,失效返回新的资源并更新缓存

⚠️缺点:1)Last-Modified的时间只能精确到秒,如果在一秒内多次修改则无法判断资源被修改;2)如果文件被定时生成 并为改变内容时,缓存会失效;3)服务器没有获取到最新的修改时间造成资源无法更新。因此引入了ETag。

5)ETag / If-None-Match:

浏览器第一次请求服务器资源的时候,服务器返回的响应头(response)会带有ETag表示符,当浏览器再次请求时会在请求头加上If-None-Match,其值就为缓存时的ETag的值。

⚠️:Last-Modified和ETag可以同时使用,但ETag的优先级较高,会先比较ETag,如果相同才会去比较Last-Modified,最终由服务器决定是否返回304

💯 什么是回流和重绘?如何优化?

浏览器渲染一个页面有两条线程:一条是渲染js脚本,一条是渲染css脚本。但是两条线程是互斥的。

回流

当render tree的一部分或者全部元素因改变了自身的宽高,布局,显示或隐藏,或元素内部的文字结构发生变化,导致需要重新构建页面的时候,回流就产生了。

重绘

当一个元素自身的宽高,布局,及显示或隐藏没有改变,而只是改变了元素的外观风格的时候,就产生了重绘。

回流必定触发重绘,而重绘不一定出发回流。

如何避免回流

1.不使用能够触发回流的属性 2. 建立一个图层,让回流在图层里面进行,限制回流和重绘的范围,减少浏览器的运算工作量。

图层的优点:当一个元素在自己的图层内发生变化时,他的回流和重绘只会在图层内发生变化,减少了浏览器的计算量。

有哪些可替换的属性可以优化回流与重绘呢

  1. 用transform 代替 top,left ,margin-top, margin-left... 这些位移属性
  2. 用opacity 代替 visibility,但是要同时有translate3d 或 translateZ 这些可以创建的图层的属性存在才可以阻止回流 但是第二点经过我的实验,发现如果不加 transform: translateZ(0) 配合opacity的话还是会产生回流的,而只用visibility 就只会产生重绘不会回流 而  opacity 加上 transform: translateZ/3d  这个属性之后便不会发生回流和重绘了
  3. 不要使用 js 代码对dom 元素设置多条样式,选择用一个 className 代替之。
  4. 如果确实需要用 js 对 dom 设置多条样式那么可以将这个dom 先隐藏,然后再对其设置
  5. 不要在循环内获取dom 的样式例如:offsetWidth, offsetHeight, clientWidth, clientHeight... 这些。浏览器有一个回流的缓冲机制,即多个回流会保存在一个栈里面,当这个栈满了浏览器便会一次性触发所有样式的更改且刷新这个栈。但是如果你多次获取这些元素的实际样式,浏览器为了给你一个准确的答案便会不停刷新这个缓冲栈,导致页面回流增加。 所以为了避免这个问题,应该用一个变量保存在循环体外。
  6. 不要使用table 布局,因为table 的每一个行甚至每一个单元格的样式更新都会导致整个table 重新布局
  7. 动画的速度按照业务按需决定
  8. 对于频繁变化的元素应该为其加一个 transform 属性,对于视频使用video 标签
  9. 必要时可以开启 GPU 加速,但是不能滥用

什么是 16ms 优化?

  • 大多数设备的刷新频率是 60 次/秒,(1000/60 = 16.6ms)也就说是浏览器对每一帧画面的渲染工作要在 16ms 内完成,超出这个时间,页面的渲染就会出现卡顿现象,影响用户体验。
  • 浏览器在一帧里面,会依次执行以下这些动作。减少或者避免 layout,paint 可以让页面不卡顿,动画效果更加流畅。
    1. JavaScript:JavaScript 实现动画效果,DOM 元素操作等。
    2. Style(计算样式):确定每个 DOM 元素应该应用什么 CSS 规则。
    3. Layout(布局):计算每个 DOM 元素在最终屏幕上显示的大小和位置。由于 web 页面的元素布局是相对的,所以其中任意一个元素的位置发生变化,都会联动的引起其他元素发生变化,这个过程叫 reflow。
    4. Paint(绘制):在多个层上绘制 DOM 元素的的文字、颜色、图像、边框和阴影等。
    5. Composite(渲染层合并):按照合理的顺序合并图层然后显示到屏幕上。
贡献者: mankueng