[TOC]
## 前言
相信有不止一个人给你推荐过web优化中药减少并简化请求,比如使用图片精灵,合并压缩文件,脚本文件写在dom末尾,那么今天我们从http这个角度去分析,去做一些有意义的探索。
## http瀑布图入门
如果说你想了解下http的请求情况或者想优化页面初始化的效率,那么http瀑布图是你不可缺少的一个分析工具。如下图所示:下面分别展示了一个页面打开的所有请求以及一个资源请求的详细情况。从下面的图中你既能看到不同请求的请求顺序,请求时间,也能看到资源是同步加载的,脚本会阻塞加载,另外渲染和js执行属于不同的引擎负责,等等。在后面的文章中,我会分别介绍如何去分析这些图,并根据这些图去优化对应的部分。
![](https://box.kancloud.cn/ba24ba04e2088903b82474358ebe7e19_1125x675.png)
## http协议的类型
科普内容:
![](https://box.kancloud.cn/564f9fe6070274d7457575b768ab4e08_690x515.png)
>物理层:以太网 · 调制解调器 · 电力线通信(PLC) · SONET/SDH · G.709 · 光导纤维 · 同轴电缆 · 双绞线等
数据链路层:Wi-Fi(IEEE 802.11) · WiMAX(IEEE 802.16) ·ATM · DTM · 令牌环 · 以太网 ·FDDI · 帧中继 · GPRS · EVDO ·HSPA · HDLC · PPP · L2TP ·PPTP · ISDN·STP 等
网络层协议:IP (IPv4 · IPv6) · ICMP· ICMPv6·IGMP ·IS-IS · IPsec · ARP · RARP等
传输层协议:TCP · UDP · TLS · DCCP · SCTP · RSVP · OSPF 等
应用层协议:DHCP ·DNS · FTP · Gopher · HTTP· IMAP4 · IRC · NNTP · XMPP ·POP3 · SIP · SMTP ·SNMP · SSH ·TELNET · RPC · RTCP · RTP ·RTSP· SDP · SOAP · GTP · STUN · NTP· SSDP · BGP · RIP 等
* http的通信流程:
![](https://box.kancloud.cn/505f7e66d76e9cca3a3fbaa3b0a554be_307x199.png)
* http的消息结构:
![](https://box.kancloud.cn/ff5d37e40e0dca70d7e3e6c0dcdca1d0_466x165.png)
* http连接注意事项
HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。
HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
* http版本
0.9 只接受get,过时;
1.0 大多数网站使用;
1.1 当前版本。持久连接被默认采用,并能很好地配合代理服务器工作。还支持以管道方式同时发送多个请求,以便降低线路负载,提高传输速度。
2.0 符合spdy协议,二进制格式在协议的解析和优化扩展上带来了跟多的优势,对消息头采用Hpack进行压缩传输,能够节省消息头占用的网络流量,异步连接多路复用,Server Push,服务器端能够更快的把资源推送到客户端,保持了与HTTP 1.1语义的向后兼容性
* http种类:
**HTTP**:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
**HTTPS**:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL(ssl用户安全认证)。
**cdn请求**:为什么有的文件用cdn加速之后就没有写协议类型,因为当前协议类型有可能是http or https不确定的,写//会自动识别当前的页面请求类型。
**data:image/png;base64**:为什么没有协议类型,本身属于符合RFC2397的Data URI scheme,不需要加载文件,知识一部分内容直接用于输出,图片是2进制的,所以一般需要转换为64进制。除了这个之外,还有其他类型:比如:data:text/plain,<文本数据> ,data:text/css,<css代码> ,data:image/x-icon;base64,base64编码的icon图片数据等,详细文档请站内搜索“Data URI scheme”。
## http2 详解
### 多路复用
在HTTP/2中,有两个非常重要的概念:帧(frame)和流(stream)。
**1、帧(frame)**
HTTP/2中数据传输的最小单位,因此帧不仅要细分表达HTTP/1.x中的各个部份,也优化了HTTP/1.x表达得不好的地方,同时还增加了HTTP/1.x表达不了的方式。
每一帧都包含几个字段,有length、type、flags、stream identifier、frame playload等,其中type代表帧的类型,在HTTP/2的标准中定义了10种不同的类型,包括上面所说的HEADERS frame和 DATA frame。此外还有
> PRIORITY(设置流的优先级)
> RST_STREAM(终止流)
> SETTINGS(设置此连接的参数)
> PUSH_PROMISE(服务器推送)
> PING(测量RTT)
> GOAWAY(终止连接)
> WINDOW_UPDATE(流量控制)
> CONTINUATION(继续传输头部数据)
**2、流(stream)**
> “流”在HTTP/2中是一个逻辑上的概念,就是说在一个TCP连接上,我们可以向对方不断发送一个个的消息,这里每一个消息看成是一帧,而每一帧有个stream identifier的字段标明这一帧属于哪个“流”,然后在对方接收时,根据stream identifier拼接每个“流”的所有帧组成一整块数据。我们把HTTP/1.x每个请求都当作一个“流”,那么请求化成多个流,请求响应数据切成多个帧,不同流中的帧交错地发送给对方,这就是HTTP/2中的多路复用。
![](https://box.kancloud.cn/e8e6fd7fc875e287ba007a0d9acbe8ab_640x185.png)
从上图我们可以留意到:
不同的流在交错发送;
HEADERS 帧在 DATA 帧前面;
流的ID都是奇数,说明是由客户端发起的,这是标准规定的,那么服务端发起的就是偶数了。
多路复用让HTTP连接变得很廉价,只需要创建一个新流即可,这不需要多少时间,而在HTTP/1.x时代却要经历三次握手时间或者队首阻塞等问题。而且创建新流默认是无限制的,也就是可以无限制的并行请求下载。不过,HTTP/2还是提供了`SETTINGS_MAX_CONCURRENT_STREAMS` 字段在 SETTINGS 帧上设置,可以限制并发流数目,标准上建议不要低于100以保证性能。
优化Web性能有一个常用的技术,就是图片延迟加载,目的是除了节省流量外,还能避免图片资源与其他重要的脚本资源竞争下载。
HTTP/2提供了流的优先级与依赖性这种机制,可用 HEADERS 帧或 PRIORITY 帧设置,不过协议并没有提供如何处理优先级的具体算法,这可由服务器灵活应对。我用个例子来说明这个机制。
~~~
<!-- a.html -->
<html>
<body>
<script src="a.js"></script>
<img src="a.jpg">
<img src="b.jpg">
<link rel="stylesheet" type="text/css" href="style.css">
</body>
</html>
~~~
浏览器是边下载边解析的,文档解析器首先遇到a.js,它就会去下载并且阻塞页面,同时,资源探测器会继续向下扫描,发现a.jpg、b.jpg和style.css并服务器发起请求。在没有优先级机制时,a.jpg、b.jpg会跟重要的a.js、style.css竞争下载,但在HTTP/2中,浏览器可以给a.jpg、b.jpg设置较低的优先级,另外依赖关系为
![](https://box.kancloud.cn/6d30ee2f3392aa9ea6f86395459e930e_434x153.png)
这样服务器根据优先级信息,首先吐出a.js、style.css,再吐出图片,因此页面在没有图片的情况下提前进入可交互状态。例子所说的是在浏览器层面上harcode的一个优先级策略,再比如上文提到的prefetch就可以给一个更低的优先级。在代码层面上,也许之后会提供一些控制优先级的特性,类似于目前只有IE支持的lazyload attribute。
## http请求状态码
>HTTP状态码(HTTP Status Code)是用以表示网页服务器HTTP响应状态的3位数字代码。它由 RFC 2616 规范定义的,并得到RFC 2518、RFC 2817、RFC 2295、RFC 2774、RFC 4918等规范扩展。http常见的状态码以及代表含义作为前端要清楚,并且正确的运用。以下只提供了部分常见的,如果大家想了解更多可以参考以下在线文档:
[百度百科](http://baike.baidu.com/link?url=5Qa0aFGQ4ZFOS0Bzj4kXZ_p9xPMw8ZV55XUTbx0UhZxHz35wDHaTA2IEV4gXykzqLe5Iwo-m8_DDF_vQyG0PRQnniO06nQ2lySObfBWcbB891L-AIkoD8dvWM2_JvNm3) / [菜鸟教程](http://www.runoob.com/http/http-status-codes.html)
![](https://box.kancloud.cn/e1cbf9af1b069680db8ef452c2f52343_582x370.png)
### 1. 1xx 信息正在处理
### 2. 2xx 请求成功
|状态码 | 描述 |
| ------------- | ------------- |
|200|ok 请求被成功处理 |
|201|请求成功,并且服务器创建了新的资源 |
|202|服务器已经接受请求,但还没有处理 |
|203|服务器已经处理了请求,但是信息来自于另一个来源 |
|204|请求成功,但是服务器没有响应体 |
|205|处理了请求,但没有返回内容,要求请求者重置内容再次请求 |
|206|部分内容,该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的GET请求 |
### 3. 3xx 重定向状态码
|状态码 | 描述 |
|------------- |------------- |
|301|永久性重定向 |
|302|临时性重定向 |
|304|未被修改,不会返回新内容 |
### 4. 4xx 代表请求错误
|状态码 | 描述 |
|------------- |------------- |
|401|未被授权 |
|403|服务器拒绝请求 |
|404|页面或者文件找不到 |
|405|禁用请求中的指定方法 |
|408|请求超时 |
|414|请求uri过长 |
|417|请求参数不符合标准 |
### 5. 5xx 服务器错误
| 状态码 | 描述 |
| --- | --- |
|500|服务器内部错误 |
|501|服务器不具备响应此需要的功能 |
|502|错误网关 |
|503|服务不可用,比如系统维护或者升级等 |
|504|网关超时 |
|505|http协议版本不支持 |
## http请求类型
共8种请求类型,常见的是get和post请求,所有的这些类型都参与js-restful的设计。
根据HTTP标准,HTTP请求可以使用多种请求方法。
HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法。
HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。
|状态码 | 描述 |
|------------- |------------- |
|GET|请求指定的页面信息,并返回实体主体 |
|HEAD|类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头 |
|POST|向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资 源的建立和/或已有资源的修改 |
|DELETE|请求服务器删除指定的页面 |
|CONNECT|HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器 |
|OPTIONS|允许客户端查看服务器的性能 |
|TRACE|回显服务器收到的请求,主要用于测试或诊断 |
## get与post方式区别
首先要了解清楚的一点是:我们大多数的请求是get方式的,少数表单或者数据操作是post的,ajax异步多是post.选择上:如果你希望url可见,可被分享抓取,可手动修改参数访问,希望被缓存,参数较短,主要是受限于url长度,那么考虑用get。需要注意的一点是:需要上传文件的要用post.
>1.GET被浏览器强制支持(POST是可选的,不过一般都支持)
2.GET是幂等的,POST非幂等(幂等每次请求不会对系统造成影响,而post有可能会更新数据)
3.GET可以被浏览器缓存,POST不可以(比如访问的历史记录,请求的历史文件,比如样式文件等)
4.GET请求是『安全』的,POST不安全(这里的安全还是指的不会更新数据)
5.POST相对来说比GET要『安全』一些(操作安全,参数等不可见)
6.参数大小(理想和现实)
- 前端工程化
- 架构总纲
- 001
- 美团技术架构
- 前端工程化说明
- 历史背景说明
- 架构说明
- 前端工程化技术栈
- 技术文档说明
- 功能模块说明
- 前端模块管理器简介
- 框架对比分析
- vue&react&ng对比分析(一)
- vue&react&ng对比分析(二)
- vue&react&ng对比分析(三)
- 工程化专题系列
- 需要解决的问题
- 001
- 002
- 003
- 常见代码错误
- jslint中常见的错误
- css规范常见错误
- html规范常见错误
- 工程化目录
- 工程化初始化
- 项目构建流程
- 项目打包优化
- 上线与迭代注意事项
- 前端部署发布
- jetkins部署
- 部署需求整理
- 前端监控
- 工程化实践指南
- dock持续部署
- 系列文章
- 插拔式前端的设计
- 其他实践
- 工程化的前端管理
- 宋小菜借鉴
- 大前端团队介绍
- 人员组成
- 人员发展
- 研发流程
- 任务分类
- 前端基础建设与架构
- 技术栈以及技术方案
- 业务目录大纲
- 前端大纲
- api管理
- 后端api工具
- 前端easymock
- api拦截与代理
- api优化
- api请求时长策略设计
- 前端架构专题
- 架构专题一
- 产品原型对接
- 与ui对接
- 图片专题
- 图片工程化大纲
- 图片优化
- 图标字体
- 图标字体vs雪碧图
- 工程化的前端矩阵
- 蚂蚁金服前端矩阵分享
- BFF架构
- 概念解析
- 前端脚手架
- 初始化项目
- 个性化配置
- 部署与发布
- 性能优化专题
- http专题
- https常识
- http优化1
- http优化2
- http优化3
- http缓存
- 常规web性能优化攻略
- 性能优化大纲
- 样式优化
- js优化
- 第三方依赖优化
- 代码分割优化
- 图片优化
- 打包优化
- 服务器优化
- 缓存优化
- 交互优化
- pc事件优化
- 手机事件优化
- 推荐文章
- 01
- 前端安全专题
- 前端安全大纲
- 前端第三方库
- seo优化
- web框架的对比
- 001
- 学习资源
- 珠峰前端架构
- npm教程
- npm入门
- cnpm入门
- cnpm搭建
- 你该知道的js模块
- browserSync
- opn
- js-cookie
- npm-script进阶
- 入门篇
- 进阶篇
- 高阶篇
- 实践篇
- yarn入门
- nodejs教程
- axios&&fetch
- xhr
- axios
- fetch
- babel专题
- babel入门
- profill入门
- nodejs入门
- 快速入门
- 大纲介绍
- node基础
- global obj
- assert断言
- procss-进程
- child_process子进程
- cluster集群
- console控制台
- crypto-加密
- dgram-数据报
- dns-域名服务器
- error-异常
- events-事件
- global-全局变量
- http-基本协议
- https-安全协议
- modules-模块
- os-操作系统
- path-路径
- querystring-查询字符串
- readline-逐行读取
- fs-文件系统
- net-网络操作
- 命令行工具
- 内存泄露
- 代码的组织与部署
- 异步编程
- orm模块
- 异步编程解决方案
- node-lessons
- 环境准备
- nodejs实践
- 项目搭建
- 异步优化
- 创建web和tcp服务器
- 终端问答程序
- 爬虫系统
- mongleDb
- mongoDB简介
- 基本使用
- 实用技巧
- 汇总001
- 饿了么后台搭建
- nodejs干货
- 沪江基于node的实践
- 苏宁基于nodejs优化
- 基于nodejs开发脚手架
- 书籍干货
- 深入浅出nodejs
- 异步I/O(一)
- gulp教程
- gulp入门
- gulp常用插件(1)
- gulp常用插件(2)
- gulp创建目录
- 经验普及贴
- webpack教程
- webpack入门
- 简单入门
- entry配置
- output配置
- 插件使用01
- 插件使用02
- loader使用
- dev-server介绍
- 构建css
- css模块化
- 使用less和sass
- 构建图片
- 引入字体
- babel配置攻略
- eslint
- 001
- webpack进阶
- 分不同文件检出
- 优化打包大小
- 优化打包速度
- 自定义配置
- 单页以及多页如何配置
- 优化实践
- 文章导读
- 001
- 优化指南
- 参考列表
- webpack4
- 多入口程序构建
- 参考教程
- 项目实践
- 环境区分
- 常见问题
- 解读webpack
- 从vuejs权威指南中解决
- 深入浅出webpack
- rollup
- 入门
- parcel
- 入门篇
- express教程
- nuxt教程
- 入门
- 基本入门
- koa教程
- koa基本入门
- koa开发注意事项
- koa实践指南
- 关于路由
- koa优化指南
- 001
- Vuejs
- vuejs入门系列
- vue-cli入门
- vue2基本认识
- vuejs入门教程
- 样式绑定
- vuex入门学习笔记
- vue组件生命周期
- 组件的使用
- vue-router入门
- vue-filter
- 计算属性使用
- 开发注意事项
- mixins
- 组件通讯
- vuejs进阶
- 进阶资源
- router进阶
- 官网介绍
- 前进与后退优化
- keep-alive基本使用
- keep-alive原理详解
- 钩子函数进阶
- 计算属性&监听&方法
- vue服务端渲染技术
- 项目实践之路
- 实践大纲
- 插槽专题篇
- vue-cli升级
- 进阶入门
- vuejs架构
- nuxt
- vuejs项目实践
- vue实践常见问题
- 001
- 002
- 003
- 004
- 005
- 改造api参数探索
- 007
- 008
- 009
- 010
- 项目技术栈
- vue性能问题以及优化方案
- vue-spa应用的理解
- vue-ssr的部署与使用
- 滴滴出行实践案例
- 2.0重构
- vue-element-admin实践
- 准备工作
- 菜单设计
- 权限设计
- 依赖模块
- vue-betterScroll
- 性能优化懒加载
- 京东组件实践
- vue2项目小结
- vue探索与实践
- 去哪实践
- 介绍
- 饿了么项目实践
- 项目解析
- vue骨架屏实践
- vue生态推荐
- ui框架
- elementUI
- 001
- 002
- VUE-material
- vant-ui
- 解读入门
- iview
- 使用问题汇总
- vux
- mint-ui
- loadmore
- vue资源导航
- vueconf
- 源码解读
- vm
- 双向绑定
- 基本原理
- 数组双向绑定
- 报错机制
- 封装方法
- 运行环境
- 入门
- 指令
- vue-router解读
- util
- vue-props
- 流程逻辑
- 推荐文章
- 源码解读
- 文章导读
- 001
- vuejs实战
- 基础篇
- 进阶篇
- 实践篇
- 面试专题
- angularjs教程
- angularjs入门系列
- 基本入门
- ng2入门
- ng进阶
- ng项目实践
- 源码解读
- typescript
- reactjs教程
- reactjs入门系列
- react的基本入门
- react组件
- virtalDom认识
- react-cli入门
- react组件的生命周期
- 基本知识点
- react-router教程
- react进阶
- 基本实践
- react加载性能优化指南
- react属性封装
- 进阶45讲
- 01概述
- 02jsx
- 06高阶组件&函数子组件
- contextApi
- react-router
- 入门章节
- 进阶
- 高阶组件
- react进阶组件
- 基本介绍
- render props
- render props的封装
- render props getter
- react-native入门
- 源码解读
- 001
- 002-reactDemo
- 参考教程
- 参考教程1
- 了解react-hooks
- ui框架
- pc端ui框架推荐
- 项目实践
- weatherApp
- 001
- 002
- 不同生命周期使用场景
- react项目结构和组件的命名
- 常见问题解答
- 参考书籍
- react全栈
- 前言
- react与redux进阶
- 常见误解
- 反模式
- react设计模式与最佳实践
- 7美化组件
- 7.2行内样式
- 7.4css模块
- 深入react技术栈
- react学习手册
- 序
- mobx教程
- 入门
- 大佬推荐
- 001
- react面试
- 001
- linux教程
- linux入门
- 基本入门
- 文件管理
- 文件传输
- 文档编辑
- 磁盘管理
- 磁盘维护
- 网络通讯
- 系统管理
- 系统设置
- 备份压缩
- 设备管理
- 查看系统信息
- linux其他
- webhook
- rsync入门教程
- ssh免登陆设置
- 安装nodejs
- nginx教程
- 入门教程
- 安装
- 基本配置
- 服务基本使用
- 高性能nginx
- 001
- pm2教程
- shell教程
- 入门大纲
- echo命令
- 参考文献
- linux常用命令2
- linux常见问题
- 001
- python
- 入门教程
- 机器学习
- 准备工作
- 服务器常识
- tomcat
- 入门常识
- iis
- redis教程
- 入门第一篇
- redis进阶
- 项目实践
- redis使用问题
- mongleDB
- 入门
- 使用进阶
- 项目实践
- 常见问题
- electron
- 入门系列
- 前言
- 小程序
- 入门
- 准备工作
- 路由
- 参考文档
- 001
- 小程序开发--双路视频调研
- 准备工作
- 参考资源
- 参考网址
- docker
- 入门
- 基本认识
- 安装与使用
- docker安装nginx
- docker安装jetkins(1)
- docker部署jenkins(2)
- 进阶
- 实践总结
- docker群分享
- docker部署前端应用
- 文章导读
- docker其他
- 网络安全
- 入门
- 大纲
- 项目解析
- schoolpal.web
- 功能模块大纲
- 目录结构大纲
- 前端国际化
- 国际化方案
- 其他
- bower入门教程
- weex
- 入门
- memcached
- 入门
- sails
- 入门