前端部署时,需将 html/css/js/img 等静态资源发布至服务器/CDNs,常规优化点如下:
基于 express server 的例子
1 合并、压缩、混淆
文件合并,减少 http 请求次数
压缩、混淆,减少静态资源大小
实现上,可使用 webpack 配合系列插件,打包过程中可压缩源代码(去空格、换行、注释,JS混淆代码等等),webpack 配置复杂,不过多赘述
2 http gzip 压缩
减少 http 传输过程中文件大小
2.1 压缩前后对比
2.2 HTTP 请求头 Accept-Encoding
HTTP 请求头 Accept-Encoding 会将客户端能够理解的内容编码方式——通常是某种压缩算法——进行通知。通过内容协商的方式,服务端会选择一个客户端提议的方式,使用并在响应报文首部 Content-Encoding 中通知客户端该选择。
2.3 HTTP 响应头 Content-Encoding
Content-Encoding 是一个实体消息首部,用于对特定媒体类型的数据进行压缩。当这个首部出现的时候,它的值表示消息主体进行了何种方式的内容编码转换。这个消息首部用来告知客户端应该怎样解码才能获取在 Content-Type 中标示的媒体类型内容。
3 Not Modified 304
减少传输内容提升性能。
客户端有缓冲的文档并发出了一个条件性的请求。服务器告诉客户端,原来缓冲的文档还可以继续使用,涉及以下两种 HTTP Header。
3.1 Last-modified / If-Modified-Since
1)浏览器第一次请求某个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间
2)客户端第二次请求此URL时,HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间之后文件是否有被修改过。
3)如果服务器端的资源没有变化,则自动返回 HTTP 304 Not Modified 状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。
3.2 Etag / If-None-Match
Etag 类似于 hash 值,用来判断请求的文件是否被修改,其 http 缓存步骤与 Last-Modified 相同。
HTTP 协议规格说明定义ETag为“被请求变量的实体值”。 另一种说法是,ETag是一个可以与Web资源关联的记号(token)。
3.3 Etag 主要为了解决 Last-Modified 无法解决的一些问题
1)一些文件也许会周期性的更改,但内容并未改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新 GET
2)某些文件修改非常频繁,比如在秒以下的时间内进行修改(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒)
3)某些服务器不能精确的得到文件的最后修改时间
4 浏览器缓存
Last-Modified 和 Etag 标识资源变化情况,服务器返回 304 Not Modified 降低网络传输大小,提升性能。但是对于如图片、react/vue这类库资源、通用css这些不经常变化的静态资源,应利用浏览器缓存功能,连304这次请求都优化掉。
4.1 Pragma
HTTP1.0 标准,表明禁用缓存,由于 Pragma 在 HTTP 响应中的行为没有确切规范,所以不能可靠替代 HTTP/1.1 中通用首部 Cache-Control。看了下腾讯视频、京东商城等页面,用在html的请求头中。
4.2 Expires
HTTP1.0 标准,表明过期时间,注意此处的时间都是指的是服务器的时间。(无效的日期,比如 0, 代表着过去的日期,即该资源已经过期)
**存在问题**:客户端与服务器时间不一致,可能导致缓存失效。
4.3 Cache-Control
HTTP 1.1 标准,是 expires 的补充,使用的是相对时间的概念。
Cache-Control 属性如下:
1)max-age: 设置缓存的最大的有效时间,单位为秒(s)。max-age会覆盖掉Expires
2)s-maxage: 只用于共享缓存,比如CDN缓存(s -> share)。与 max-age 的区别是:max-age 用于普通缓存,而 s-maxage 用于代理缓存。如果存在 s-maxage,则会覆盖 max-age 和 Expires
3)public:响应会被缓存,并且在多用户间共享。默认是public。
3)private: 响应只作为私有的缓存,不能在用户间共享。如果要求HTTP认证,响应会自动设置为private。
4)no-cache: 指定不缓存响应,表明资源不进行缓存。但是设置了no-cache之后并不代表浏览器不缓存,而是在缓存前要向服务器确认资源是否被更改。因此有的时候只设置no-cache防止缓存还是不够保险,还可以加上private指令,将过期时间设为过去的时间。
5)no-store: 绝对禁止缓存。
6)must-revalidate: 如果页面过期,则去服务器进行获取。
更多属性请参考 MDN:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control
使用浏览器缓存后,chrome 中网络请求如下:
1)from memery cache 从内存中读取
2)from disk cache 从浏览器缓存中读取
Chorme官网描述
5 HTTP2
这篇文字介绍的很全面
协议递进顺序 HTTP1.0 -> HTTP1.1 -> spdy(谷歌) -> HTTP2
1)多路复用 + 二进制分帧:使用 HTTP1.1,浏览器在同一时间,针对同一域名下的请求有一定的数量限制,超过限制数目的请求会被阻塞(不同浏览器不同),HTTP2 引入二进制数据帧和流的概念,而非 HTTP1.1 的文本形式,实现在同一 TCP 连接下的多并发请求(当然 HTTP1.1 优化的 keep-alive 也不需要了)
2)头部压缩:HTTP1.1 Header 中有许多无意义的重复的头部,HTTP2 使用 HPACK 算法进行头部压缩
3)服务端推送:例如,在浏览器请求 html 时,服务端预测性的将 js、css 等文件推送回来,但在实际应用中有许多问题需要解决
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。