这个信息爆炸的时代,使用移动终端获取新鲜信息已经是大势所趋,但是移动网页浏览速度还有巨大的提升空间。据 Strangeloop Networks 统计,在同样的网络条件下,使用移动端访问相同网页平均会比 PC 端慢40%!然而另一方面,用户对网速的要求却步步紧逼。研究表明,网页响应时间可容忍的阀值是2秒,一旦超过3秒,会有40%的用户放弃浏览页面。
所谓天下武功,唯快不破!想要设计更快的网页优化速度,我们可以借鉴成功的优化经验,全球最大的CDN服务商Akamai(阿卡迈)针对移动体验的问题,提供了一套较为完整的解决方案,感兴趣的读者可以前往注册下载;与此同时,我们也可以采用直接的技术手段,本文从PC端优化经验、HTTP/2优化协议、优化蜂窝网络、以及智能的加载方案设计四个维度,总结了一些提升移动网页加载速度的方法和技巧。
一、PC 端网站优化方案
不论在 PC 还是在移动浏览器上,只有不到10%的时间是用来读取页面的 HTML 的。剩下的90%是用来加载额外的如样式表、脚本文件、或者图片这样的资源和执行客户端的程序。因此,许多在 PC 端的传统网页优化方案在移动端仍然可行。比如说:
1.1 减少每个页面的 HTTP 请求数
I. 将共用的 JavaScript 和 CSS 代码放在公共的文件夹中与多个页面共享。
II. 确保在一个页面中相同的脚本不会被加载多次。同时,将脚本中的 Click 事件改为 On Touch 事件来减少固有的300ms延迟。
III. 使用 CSS Sprites 来整合图像,将多张图片整合到一个线性的网状的大图片中。
IV. 使用 Cache-Control 或者 Expires 标记来实现浏览器缓存,从而减少不必要的服务器请求,尽可能地从本地缓存中获取资源。
1.2 减少每个请求加载的大小
I. 使用 gzip 这样的压缩技术来压缩图像和文本,依靠增加服务端压缩和浏览器解压的步骤,来减少资源的负载。
II. 整合并压缩 CSS 与 JavaScript,删除不必要的字符与变量。
III. 动态地调整图片大小或者将图片替换为移动设备专用的更小的版本。
IV. 分段加载和隐藏加载等手段,可以将不可见区域的内容延迟加载或暂时不需要的脚本进行延时读取
二、采用更优的 HTTP/2 协议
2.1 多路复用技术带来的请求-响应加速
I. HTTP/2 采用多路复用的技术,允许同时通过单一的 HTTP/2 连接发起多重的请求响应消息,从而大大的加快了网页加载时间。
2.2 更节省空间的二进制头部数据嵌套
I. HTTP/2 采用二进制格式传输数据,并把他们分割为更小的帧,相比于 HTTP/1.x 的文本格式传输更为方便。
II. HTTP1.x 的 header 由于 cookie 和 user agent 很容易膨胀,而且每次都要重复发送。HTTP/2 对消息头采用 HPACK 进行压缩传输,能够节省消息头占用的网络流量。
2.3 Server Push 带来的更快的资源推送
I. 通过 Server Push 功能,服务端可以主动把 JS 和 CSS 等文件发送给终端,而省去了解析HTML 请求的过程。简单的说,当你需要访问某个文件的时候,它已经在乖乖的在后台躺好了。
三、优化蜂窝网络
I.具有实力的内容服务商可以把资源配置在离用户地理位置更近的地方,缩短最后一公里。
II. 与移动网络服务商合作共同开发算法,实现实时自动调整互联网路由,避免网络拥堵、丢包与离线问题。
III. 还可以采用优化TCP协议的方法,通过借助主流的Cubic、Bic以及Westwood算法,可以有效的避免网络拥堵。
IV. 此外,还可以研究算法改善NAT嵌套导致的网络延时,也可以直接通过IPV6的连接协议规避NAT的延迟问题。
四、设计更加智能的加载方案
4.1采用分段加载和隐藏加载
I.分段加载又称懒加载,它能够在用户滚动页面的时候自动获取更多的数据,从而可以很大程度上减少服务器端的资源耗用。诸如Lazyload.js或Belazy.js都是非常成熟易用的开发包。
II. 隐藏加载是在页面显示后再加载用户暂时看不到的信息,诸如图片展示窗里除了第一张图片,其他图片都可以采用隐藏加载的技术。
4.2采用预加载技术
I.资源预加载目的是让浏览器在空闲时间下载或预读取一些文档资源,用户在将来将会访问这些资源时浏览器能快速的从缓存里提取给用户。
II. 预加载技术不仅支持PC,也已经支持Android系统,可惜的是目前尚不支持iOS Safari。
III. 事实上,Prefetch是网页优化里Prebrowsing的一部分,开发者还可以通过DNS-Prefetch , Subresource,Preconnect,Prerender等技术来实现预先解析DNS与提前渲染等优化。
4.3通过机器学习的手段智能加载
I.通过机器学习的方法,网站可以自动收集并分析用户的浏览习惯与访问信息,然后通过预加载的手段将最有可能访问的信息提前加载完成。
4.4智能调整图片分辨率
I.图片通常占用了Web页面加载的大部分网络资源,也占据了页面缓存的主要空间。 根据统计,一个站点平均62%的内容都是由图片组成。管理这些图片除了需要考虑到图片的大小、格式、旋转、艺术处理、增加水印、存储空间等,还要顾及海量的设备的屏幕尺寸,以及适应终端上运行的浏览器。
以上是我们给开发者总结的一些经验分享,希望能够对读者有所帮助,大家也可以注册下载阿卡迈的技术PPT详细了解如何通过CDN 的方式为(移动)网页提速。我们需要明确的是,专注移动网页的性能优化无疑是开发者需要努力的方向,然而用户并不等于机器。用户不关心你的网站发出了多少请求,也不在乎你的屏幕渲染得有多快,他们只关心网站带给他们体验上的感觉。因此,开发者在进行技术优化时,不仅仅是在某一技术点上的优化,更需要从网站的整体性能规划把控,让整个网站给客户呈现出更快的加载体验!
HTTP车是由蒂姆·伯纳斯-李( TimBerners—Lee )于1989年在欧洲核子研究组织( CERN )所发起
其中最著名的是 1999 年 6 月公布的 RFC 2616 ,定义了 HTTP 协议中现今广泛使用的一个版本—— HTTP 1.1
全称:超文本传输协议( HyperText Transfer Protocol )
概念: HTTP 是一种能够获取像 HTML 、图片等网络资源的通讯协议( protocol )。它是在 web 上进行数据交换的基础,是一种 client-server 协议
HTTP ——因特网的多媒体信使 ——《HTTP权威指南》。 HTTP 在因特网的角色:充当一个信使的角色,干的就是一个跑腿的活,在客户端和服务端之间传递信息,但我们又不能缺少它。 HTTP 协议是应用层的协议,是与前端开发最息息相关的协议。平时我们遇到的 HTTP 请求、 HTTP 缓存、 Cookies 、跨域等其实都跟 HTTP 息息相关
也就是说, HTTP 依赖于面向连接的 TCP 进行消息传递,但连接并不是必须的。只需要它是可靠的,或不丢失消息的(至少返回错误)。
HTTP/1.0 默认为每一对 HTTP 请求/响应都打开一个单独的 TCP 连接。当需要连续发起多个请求时,这种模式比多个请求共享同一个 TCP 链接更低效。为此, HTTP 1.1 持久连接的概念,底层 TCP 连接可以通过 connection 头部实现。但 HTTP 1.1 在连接上也是不完美的,后面我们会提到。
HTTP 的组件系统包括客户端、 web 服务器和代理
浏览器,特殊比如是工程师使用的程序,以及 Web 开发人员调试应用程序
由 Web Server 来服务并提供客户端所请求的文档。每一个发送到服务器的请求,都会被服务器处理并返回一个消息,也就是 response
在浏览器和服务器之间,有很多计算机和其他设备转发了 HTTP 消息。它们可能出现在传输层、网络层和物理层上,对于 HTTP 应用层而言就是透明的
有如下的一些作用
HTTP 有两种类型的消息:
HTTP 消息由采用 ASCII 编码的多行文本构成的。在 HTTP/1.1 以及更早的版本中,这些消息通过连接公开的发送。在 HTTP2.0 中,消息被分到了多个 HTTP 帧中。通过配置文件(用于代理服务器或者服务器), API (用于浏览器)或者其他接口提供 HTTP 消息
HTTP 请求和响应都包括起始行( start line )、请求头( HTTP Headers )、空行( empty line )以及 body 部分,如下图所示:
下面详细说下请求 Path ,请求路径( Path )有以下几种:
1)一个绝对路径,末尾跟上一个 ' ? ' 和查询字符串。这是最常见的形式,称为 原始形式 ( origin form ),被 GET , POST , HEAD 和 OPTIONS 方法所使用
POST / HTTP/1.1
GET /background.png HTTP/1.0
HEAD /test.html?query=alibaba HTTP/1.1
OPTIONS /anypage.html HTTP/1.0
复制代码
2)一个完整的 URL 。主要在使用 GET 方法连接到代理的时候使用
GET http://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1
复制代码
3)由域名和可选端口(以':'为前缀)组成的 URL 的 authority component ,称为 authority form 。仅在使用 CONNECT 建立 HTTP 隧道时才使用
CONNECT developer.mozilla.org:80 HTTP/1.1
复制代码
4)星号形式 ( asterisk form ),一个简单的星号('*'),配合 OPTIONS 方法使用,代表整个服务器。
OPTIONS * HTTP/1.1
复制代码
请求 Body 部分: 有些请求将数据发送到服务器以便更新数据:常见的的情况是 POST 请求(包含 HTML 表单数据)。请求报文的 Body 一般为两类。一类是通过 Content-Type 和 Content-Length 定义的单文件 body 。另外一类是由多 Body 组成,通常是和 HTML Form 联系在一起的。两者的不同表现在于 Content-Type 的值。
1) Content-Type —— application/x-www-form-urlencoded 对于 application/x-www-form-urlencoded 格式的表单内容,有以下特点:
I.其中的数据会被编码成以&分隔的键值对
II.字符以URL编码方式编码。
// 转换过程: {a: 1, b: 2} -> a=1&b=2 -> 如下(最终形式)
"a%3D1%26b%3D2"
复制代码
2) Content-Type —— multipart/form-data
请求头中的 Content-Type 字段会包含 boundary ,且 boundary 的值有浏览器默认指定。例: Content-Type: multipart/form-data;boundary=----WebkitFormBoundaryRRJKeWfHPGrS4LKe 。
数据会分为多个部分,每两个部分之间通过分隔符来分隔,每部分表述均有 HTTP 头部描述子包体,如 Content-Type ,在最后的分隔符会加上--表示结束。
Content-Disposition: form-data;name="data1";
Content-Type: text/plain
data1
----WebkitFormBoundaryRRJKeWfHPGrS4LKe
Content-Disposition: form-data;name="data2";
Content-Type: text/plain
data2
----WebkitFormBoundaryRRJKeWfHPGrS4LKe--
复制代码
响应 Body 部分:
1)由已知长度的单个文件组成。该类型 body 有两个 header 定义: Content-Type 和 Content-Length
2)由未知长度的单个文件组成,通过将 Transfer-Encoding 设置为 chunked 来使用 chunks 编码。
关于 Content-Length 在下面 HTTP 1.0 中会提到,这个是 HTTP 1.0 中新增的非常重要的头部。
安全方法: HTTP 定义了一组被称为安全方法的方法。 GET 方法和 HEAD 方法都被认为是安全的,这意味着 GET 方法和 HEAD 方法都不会产生什么动作 —— HTTP 请求不会再服务端产生什么结果,但这并不意味着什么动作都没发生,其实这更多的是 web 开发者决定的
首先要了解下副作用和幂等的概念,副作用指的是对服务器端资源做修改。幂等指发送 M 和 N 次请求(两者不相同且都大于 1),服务器上资源的状态一致。应用场景上,get是无副作用的,幂等的。post 主要是有副作用的,不幂等的情况
技术上有以下的区分:
HTTP Headers
1.通用首部( General headers )同时适用于请求和响应消息,但与最终消息主体中传输的数据无关的消息头。如 Date
2.请求首部( Request headers )包含更多有关要获取的资源或客户端本身信息的消息头。如 User-Agent
3.响应首部( Response headers )包含有关响应的补充信息
4.实体首部( Entity headers )含有关实体主体的更多信息,比如主体长( Content-Length )度或其 MIME 类型。如 Accept-Ranges
详细的 Header 见 HTTP Headers 集合
HTTP(HyperText Transfer Protocol) 是万维网( World Wide Web )的基础协议。 Tim Berners-Lee 博士和他的团队在 1989-1991 年间创造出它。【HTTP、网络浏览器、服务器】
在 1991 年发布了 HTTP 0.9 版,在 1996 年发布 1.0 版,1997 年是 1.1 版,1.1 版也是到今天为止传输最广泛的版本。2015 年发布了 2.0 版,其极大的优化了 HTTP/1.1 的性能和安全性,而 2018 年发布的 3.0 版,继续优化 HTTP/2 ,激进地使用 UDP 取代 TCP 协议,目前, HTTP/3 在 2019 年 9 月 26 日 被 Chrome , Firefox ,和 Cloudflare 支持
单行协议,请求由单行指令构成。以唯一可用的方法 GET 开头。后面跟的是目标资源的路径
GET /mypage.html
复制代码
响应:只包括响应文档本身
<HTML>
这是一个非常简单的HTML页面
</HTML>
复制代码
HTML
RFC 1945 提出了 HTTP1.0 , 构建更好可拓展性
媒体类型是一种标准。用来表示文档、文件或者字节流的性质和格式。浏览器通常使用 MIME ( Multipurpose Internet Mail Extensions )类型来确定如何处理 URL ,因此 Web 服务器在响应头中配置正确的 MIME 类型会非常的重要。如果配置不正确,可能会导致网站无法正常的工作。 MIME 的组成结构非常简单;由类型与子类型两个字符串中间用'/'分隔而组成。
HTTP 从 MIME type 取了一部分来标记报文 body 部分的数据类型,这些类型体现在 Content-Type 这个字段,当然这是针对于发送端而言,接收端想要收到特定类型的数据,也可以用 Accept 字段。
这两个字段的取值可以分为下面几类:
- text: text/html, text/plain, text/css 等
- image: image/gif, image/jpeg, image/png 等
- audio/video: audio/mpeg, video/mp4 等
- application: application/json, application/javascript, application/pdf, application/octet-stream
复制代码
同时为了约定请求的数据和响应数据的压缩方式、支持语言、字符集等,还提出了以下的 Header
1.压缩方式:发送端: Content-Encoding (服务端告知客户端,服务器对实体的主体部分的编码方式) 和 接收端: Accept-Encoding (用户代理支持的编码方式),值有 gzip: 当今最流行的压缩格式;deflate: 另外一种著名的压缩格式;br: 一种专门为 HTTP 发明的压缩算法
2.支持语言: Content-Language 和 Accept-Language (用户代理支持的自然语言集)
3.字符集:发送端: Content-Type 中,以 charset 属性指定。接收端: Accept-Charset (用户代理支持的字符集)。
// 发送端
Content-Encoding: gzip
Content-Language: zh-CN, zh, en
Content-Type: text/html; charset=utf-8
// 接收端
Accept-Encoding: gzip
Accept-Language: zh-CN, zh, en
Accept-Charset: charset=utf-8
复制代码
虽然 HTTP1.0 在 HTTP 0.9 的基础上改进了很多,但还是存在这不少的缺点
HTTP/1.0 版的主要缺点是,每个 TCP 连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。 TCP 连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢( slow start )。
HTTP 最早期的模型,也是 HTTP/1.0 的默认模型,是短连接。每一个 HTTP 请求都由它自己独立的连接完成;这意味着发起每一个 HTTP 请求之前都会有一次 TCP 握手,而且是连续不断的。
HTTP/1.1 在1997年1月以 RFC 2068 文件发布。
HTTP 1.1 消除了大量歧义内容并引入了多项技术
虚拟主机( virtual hosting )即共享主机( shared web hosting ),可以利用虚拟技术把一台完整的服务器分成若干个主机,因此可以在单一主机上运行多个网站或服务。
举个例子,有一台 ip 地址为 61.135.169.125 的服务器,在这台服务器上部署着谷歌、百度、淘宝的网站。为什么我们访问 https://www.google.com 时,看到的是 Google 的首页而不是百度或者淘宝的首页?原因就是 Host 请求头决定着访问哪个虚拟主机。
2015年, HTTP2.0 面世。 rfc7540
HTTP 2.0 中的帧将 HTTP/1.x 消息分成帧并嵌入到流 ( stream ) 中。数据帧和报头帧分离,这将允许报头压缩。将多个流组合,这是一个被称为多路复用 ( multiplexing ) 的过程,它允许更有效的底层 TCP 连接。
也就是说,流用来承载消息,消息又是有一个或多个帧组成。二进制传输的方式更加提升了传输性能。 每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。 帧是流中的数据单位。
HTTP 帧现在对 Web 开发人员是透明的。在 HTTP/2 中,这是一个在 HTTP/1.1 和底层传输协议之间附加的步骤。 Web 开发人员不需要在其使用的 API 中做任何更改来利用 HTTP 帧;当浏览器和服务器都可用时, HTTP/2 将被打开并使用。
之前我们提到,虽然 HTTP 1.1 有了长连接和管道化的技术,但是还是会存在 队头阻塞。而 HTTP 2.0 就解决了这个问题 HTTP/2 中新的二进制分帧层突破了这些限制,实现了完整的请求和响应复用:客户端和服务器可以将 HTTP 消息分解为互不依赖的帧,然后交错发送,最后再在另一端把它们重新组装起来。
如上图所示,快照捕捉了同一个连接内并行的多个数据流。 客户端正在向服务器传输一个 DATA 帧(数据流 5),与此同时,服务器正向客户端交错发送数据流 1 和数据流 3 的一系列帧。因此,一个连接上同时有三个并行数据流。
将 HTTP 消息分解为独立的帧,交错发送,然后在另一端重新组装是 HTTP 2 最重要的一项增强。事实上,这个机制会在整个网络技术栈中引发一系列连锁反应,从而带来巨大的性能提升,让我们可以: 1.并行交错地发送多个请求,请求之间互不影响。 2.并行交错地发送多个响应,响应之间互不干扰。 3.使用一个连接并行发送多个请求和响应。 4.消除不必要的延迟和提高现有网络容量的利用率,从而减少页面加载时间。 5.不必再为绕过 HTTP/1.x 限制而做很多工作(比如精灵图) ...
连接共享,即每一个 request 都是是用作连接共享机制的。一个 request 对应一个 id ,这样一个连接上可以有多个 request ,每个连接的 request 可以随机的混杂在一起,接收方可以根据 request 的 id 将 request 再归属到各自不同的服务端请求里面。
HTTP 1.1 和 HTTP 2.0 的对比,可以参考这个 网站 demo 演示
HTTP 1.1 演示如下:
HTTP2.0 演示如下:
使用 HTTP/1.1 和 HTTP/2 对于站点和应用来说是透明的。拥有一个最新的服务器和新点的浏览器进行交互就足够了。只有一小部分群体需要做出改变,而且随着陈旧的浏览器和服务器的更新,而不需 Web 开发者做什么,用的人自然就增加了
HTTPS 也是通过 HTTP 协议进行传输信息,但是采用了 TLS 协议进行了加密
对称加密就是两边拥有相同的秘钥,两边都知道如何将密文加密解密。但是因为传输数据都是走的网络,如果将秘钥通过网络的方式传递的话,一旦秘钥被截获就没有加密的意义的
非对称加密
公钥大家都知道,可以用公钥加密数据。但解密数据必须使用私钥,私钥掌握在颁发公钥的一方。首先服务端将公钥发布出去,那么客户端是知道公钥的。然后客户端创建一个秘钥,并使用公钥加密,发送给服务端。服务端接收到密文以后通过私钥解密出正确的秘钥
TLS 握手的过程采用的是非对称加密
强缓存主要是由 Cache-control 和 Expires 两个 Header 决定的
Expires 的值和头里面的 Date 属性的值来判断是否缓存还有效。 Expires 是 Web 服务器响应消息头字段,在响应 http 请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。 Expires 的一个缺点就是,返回的到期时间是服务器端的时间,这是一个绝对的时间,这样存在一个问题,如果客户端的时间与服务器的时间相差很大(比如时钟不同步,或者跨时区),那么误差就很大。
Cache-Control 指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。但是其设置的是一个相对时间。
指定过期时间: max-age 是距离请求发起的时间的秒数,比如下面指的是距离发起请求 31536000S 内都可以命中强缓存
Cache-Control: max-age=31536000
复制代码
表示没有缓存
Cache-Control: no-store
复制代码
有缓存但要重新验证
Cache-Control: no-cache
复制代码
私有和公共缓存
public 表示响应可以被任何中间人(比如中间代理、 CDN 等缓存) 而 private 则表示该响应是专用于某单个用户的,中间人不能缓存此响应,该响应只能应用于浏览器私有缓存中。
Cache-Control: private
Cache-Control: public
复制代码
验证方式:以下表示一旦资源过期(比如已经超过 max-age ),在成功向原始服务器验证之前,缓存不能用该资源响应后续请求
Cache-Control: must-revalidate
复制代码
Cache-control 优先级比 Expires 优先级高
以下是一个 Cache-Control 强缓存的过程:
Last-Modified 表示本地文件最后修改日期,浏览器会在 request header 加上 If-Modified-Since (上次返回的 Last-Modified 的值),询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来
但是如果在本地打开缓存文件,就会造成 Last-Modified 被修改,所以在 HTTP / 1.1 出现了 ETag
Etag 就像一个指纹,资源变化都会导致 ETag 变化,跟最后修改时间没有关系, ETag 可以保证每一个资源是唯一的。 If-None-Match 的 header 会将上次返回的 Etag 发送给服务器,询问该资源的 Etag 是否有更新,有变动就会发送新的资源回来
If-none-match 、 ETags 优先级高于 If-Modified-Since、Last-Modified
第一次请求:
第二次请求相同网页:
协商缓存,假如没有改动的话,返回 304 ,改动了返回 200 资源
现在的200 (from cache) 已经变成了 disk cache (磁盘缓存)和 memory cache (内存缓存)两种
上面提到 HTTP 缓存相关,但是很多有时候,我们希望上线之后需要更新线上资源。
web 开发者发明了一种被 Steve Souders 称之为 revving 的技术。不频繁更新的文件会使用特定的命名方式:在 URL 后面(通常是文件名后面)会加上版本号。
弊端:更新了版本号,所有引用这些的资源的地方的版本号都要改变
web 开发者们通常会采用自动化构建工具在实际工作中完成这些琐碎的工作。当低频更新的资源( js/css )变动了,只用在高频变动的资源文件( html )里做入口的改动。
HTTP Cookie (也叫 Web Cookie 或浏览器 Cookie )是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。
Set-Cookie 响应头部和 Cookie 请求头部
Set-Cookie: <cookie名>=<cookie值>
复制代码
会话期Cookie是最简单的 Cookie :浏览器关闭之后它会被自动删除,也就是说它仅在会话期内有效。会话期 Cookie 不需要指定过期时间( Expires )或者有效期( Max-Age )。需要注意的是,有些浏览器提供了会话恢复功能,这种情况下即使关闭了浏览器,会话期 Cookie 也会被保留下来,就好像浏览器从来没有关闭一样
和关闭浏览器便失效的会话期 Cookie 不同,持久性 Cookie 可以指定一个特定的过期时间( Expires )或有效期( Max-Age )。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
复制代码
标记为 Secure 的 Cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端。
标记为 Secure 的 Cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端。但即便设置了 Secure 标记,敏感信息也不应该通过 Cookie 传输,因为 Cookie 有其固有的不安全性, Secure 标记也无法提供确实的安全保障
通过 JavaScript 的 Document.cookie API 是无法访问带有 HttpOnly 标记的 cookie 。这么做是为了避免跨域脚本攻击( XSS )
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
复制代码
Domain 和 Path 标识定义了 Cookie 的作用域:即 Cookie 应该发送给哪些 URL 。
Domain 标识指定了哪些主机可以接受 Cookie 。如果不指定,默认为当前的主机(不包含子域名)。如果指定了 Domain ,则一般包含子域名。
例如,如果设置 Domain=mozilla.org ,则 Cookie 也包含在子域名中(如 developer.mozilla.org )。
Path 标识指定了主机下的哪些路径可以接受 Cookie (该 URL 路径必须存在于请求 URL 中)。以字符 %x2F ("/") 作为路径分隔符,子路径也会被匹配。
例如,设置 Path=/docs ,则以下地址都会匹配:
/docs
/docs/Web/
/docs/Web/HTTP
复制代码
SameSite Cookie 允许服务器要求某个 cookie 在跨站请求时不会被发送,从而可以阻止跨站请求伪造攻击
Set-Cookie: key=value; SameSite=Strict
复制代码
None Strict Lax
在新版本的浏览器( Chrome 80 之后)中, SameSite 的默认属性是 SameSite=Lax 。换句话说,当 Cookie 没有设置 SameSite 属性时,将会视作 SameSite 属性被设置为 Lax —— 这意味着 Cookies 将不会在当前用户使用时被自动发送。如果想要指定 Cookies 在同站、跨站请求都被发送,那么需要明确指定 SameSite 为 None 。因为这一点,我们需要好好排查旧系统是否明确指定 SameSite ,以及推荐新系统明确指定 SameSite ,以兼容新旧版本 Chrome
更多 cookie 相关,可以查看我之前总结的一篇关于 cookie 的文章 前端须知的 Cookie 知识小结
跨域资源共享( CORS )是一种机制,它使用额外的 HTTP 头告诉浏览器,让运行在一个 origin ( domain ) 上的 web 应用被准许访问来自不同源服务器上的指定的资源
跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。
简单请求(不会触发 CORS 的预检请求)需要同时满足以下三点:
以下为一个简单请求的请求报文以及响应报文
简化以下:
请求首部字段 Origin 表明该请求来源于 http://foo.example
本例中,服务端返回的 Access-Control-Allow-Origin: * 表明,该资源可以被任意外域访问。如果服务端仅允许来自 http://foo.example 的访问,该首部字段的内容如下:
Access-Control-Allow-Origin: http://foo.example
复制代码
Access-Control-Allow-Origin 应当为 * 或者包含由 Origin 首部字段所指明的域名。
规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法。浏览器必须首先使用 OPTIONS 方法发起一个预检请求( preflight request ),从而获知服务端是否允许该跨域请求。
服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)
预检请求中同时携带了下面两个首部字段:
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
复制代码
首部字段 Access-Control-Request-Method 告知服务器,实际请求将使用 POST 方法。首部字段 Access-Control-Request-Headers 告知服务器,实际请求将携带两个自定义请求首部字段: X-PINGOTHER 与 Content-Type 。服务器据此决定,该实际请求是否被允许。
预检请求的响应中,包括了以下几个字段
Access-Control-Allow-Origin: http://foo.example
// 表明服务器允许客户端使用 POST, GET 和 OPTIONS 方法发起请求
Access-Control-Allow-Methods: POST, GET, OPTIONS
// 表明服务器允许请求中携带字段 X-PINGOTHER 与 Content-Type
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
// 表明该响应的有效时间为 86400 秒,也就是 24 小时。在有效时间内,浏览器无须为同一请求再次发起预检请求。
Access-Control-Max-Age: 86400
复制代码
一般而言,对于跨域 XMLHttpRequest 或 Fetch 请求,浏览器不会发送身份凭证信息。如果要发送凭证信息,需要设置 XMLHttpRequest 的某个特殊标志位。比如说 XMLHttpRequest 的 withCredentials 标志设置为 true ,则可以发送 cookie 到服务端。
对于附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin 的值为“*”。 这是因为请求的首部中携带了 Cookie 信息,如果 Access-Control-Allow-Origin 的值为“*”,请求将会失败。而将 Access-Control-Allow-Origin 的值设置为 http://foo.example ,则请求将成功执行。
CORS 涉及到的请求和响应头如下: HTTP 响应首部字段
HTTP 请求首部字段
Origin
Access-Control-Request-Method
Access-Control-Request-Headers
有感兴趣的朋友可以关注一下我的公众号:前端维他命,不定时更新优秀文章。
称为前端三剑客的HTML、CSS、JS
HTML我们上节课已经进行了简单的介绍,未看过的同学可以点击传送门:
果冻公开课:什么是HTML
本节课,我们就来用几分钟快速了解下,附着在HTML骨骼上,使得页面呈现出丰富内容的CSS层叠样式表。
动画视频:
果冻公开课:三分钟了解CSS
文字解析:
CSS,全称为层叠样式表。
简单来说,就是给被HTML标记的内容加上装饰,让它能有所不同,不管是外观还是内在,都有一个新的变化。
这个过程我们可以称之为为内容增加新的属性,赋予它更多的可能。
与HTML不同的是,它用的是花括号{}来包裹属性。
CSS的属性大体可以分为5大类。
其中样式、框模型、定位、选择器为较为常用的四类,而其余属性皆归为高级属性。
CSS的语言规则分为两部分:
第一部分是选择器,顾名思义我们要告诉浏览器这个属性是用在哪个或者哪几个标签上。
第二部分是声明,是告诉浏览器具体我要为它附加什么属性,增加什么变化的部分。
让我们看看加上了属性之后,我们的HTML有什么变化吧~
color,改变了文字的颜色
font-size可以让文字的大小发生变化
background-color可以添加背景颜色
border可以让文字的外边出现了边框
margin和padding可以添加内外边距,让文字和线框,线框和块之间出现了新的空间
float可以让文字浮动
top给文字增加了顶部的距离
在有了内容和样式后,我们的网页现在是这个样子,看起来和我们平时看到的网页没什么不同。
但当你对他进行操作时,你会发现,为什么这里不动了,为什么那里没反应了?
这是因为我们缺少激活它的语言JS,JS全称为javascript,是一种脚本语言。
整体来说,JS在网页中起到的作用,就像装修好的房子,你要通电才能使用这些电器一样,只有有了电,你才能使用这些电器。
而电器就是我们的CSS和HTML。
那么,为什么浏览器可以把这些代码变成我们平时浏览的网页呢?
这里可以给大家举一个很简单的例子:
大家都知道记事本,只可以在里面输入的文字。
但当我们在word中输入文字的时候,可以通过word中的各种按钮给他增加字体、字号、颜色,还可以插入表格、排版等。
而这些按钮就是前面说到的标签和属性,他为文字增加了很多新的东西。
而浏览器就相当于我们的word,可以把我们写好的HTML文件打开,让大家看到编辑好的内容。
网页没有我们想的那么复杂,HTML和CSS也没有我们想的那么神秘,它只是换了一种方式的word。
我们要先用一个软件打开和编辑我们的HTML文件,然后再用浏览器打开它,就能看到我们平时看到的那些网页了。
而我们只是将编辑的过程给了编译器,显示的过程给了浏览器,各司其职而已。
好了,今天的果冻公开课就先到这里,下期我们将向大家介绍CSS的选择器都有哪些。
★★★★★
这里是果冻公开课,一个用趣味的动画来分享IT知识的课堂
我们将原本复杂、不易理解的编程知识,转化为一个个有趣的动画短视频,为更多人提供生动有趣的IT内容/服务
无论是大咖还是小白,都可以快速学会并深度了解每一个知识点,让IT,Q弹可口。
更多内容,欢迎加大师姐微信it_xzy,入群717415872了解课程动态、幕后花絮,还有机会参与到课程制作,成为联合制作人
记得备注来自果冻课堂哟
*请认真填写需求信息,我们会在24小时内与您取得联系。