高性能网站建设指南--笔记
================================================================================
规则1--减少HTTP请求
性能黄金法则:
10%-20%的最终用户响应的时间花在接受所请求的HTML文档上。剩下80%-90%的时间花在为
HTML文档所引用的所有组件(图片、脚本、样式、Flash等)进行的HTTP请求上。改善响应
时间最简单的途径就是减少组件的数量,并由此减少HTTP请求的数量。
图片地图
服务器端图片地图 传递 x,y 坐标映射
客户端图片地图
CSS Sprites
background-position:
优点:合并图片减少下载HTTP请求,并且降低图片大小(降低图片本身开销如颜色表,格式
信息等)
内联图片
data:[<mdediatype>][;base64],<data>
缺陷:不收IE支持,数据大小受限制
夸页面不会被缓存,不要内联公司LOGO,编码会导致logo变大
可用css将内联图片做背景,可缓存
合并脚本和样式表
================================================================================
规则2--使用内容发布网络(CDN加速技术Content Delivery NetWork)
如果应用程序web服务器(Application Web Server)离用户更近,则一个HTTP请求的响应
时间将缩短。
如果组件web服务器(Componet Web Server)离用户更近,则多个HTTP请求的响应时间将
变短
内容发布网络(Conten Delivery Networks)
CDN用于发布静态内容,如图片,脚本,样式表和Flash
节省
================================================================================
规则3--添加Expires头
长久的Expires头可是组件被缓存,可在后续页面浏览中避免不必要的HTTP请求。
应该讲Expires头用于图片、脚本、样式表和Flash等所有组件中
Expires头
Max-Age和mod_expires
HTTP1.1引入Cache-Control头来克服Expires头限制,因为Expires头使用了一个特定时间,
它要求服务器和客户端时钟严格同步且到期后服务器还需提供一个新日期
Cache-Control使用max-age指令指定组件被缓存多久,以秒为单位定义了一个更新窗口
对于不支持HTTP1.1浏览器可同时提供两个头,当同时存在时HTTP规范规定max-age 指令重写
Expires头。
mod_expires Apache模块使你使用Expires头时可像max-age那样以相对的方式设置日期,通过
Expires-Default指令完成。
跨浏览器改善缓存的最佳解决方案就是使用由ExpiresDefault设置的Expires头
空缓存VS完整缓存
不仅仅是图片
HTML文档不应当使用长久Expires头,因为它包含动态内容,这些内容在每次用户请求时
都将被更新。
修订文件名
设置Expires头后在过期前不会请求新数据,为了使用户获得组件新版本,需要在所有的
HTML页面修改组件名称
示例
没有Expires头时,组件仍会存储在浏览器的缓存中。在后续请求时,浏览器会检查缓存并发现
组件过期,像原始服务器发送一个条件GET请求,组件没有改变,原始服务器可发送一个很小的头
避免发送整个组件。
================================================================================
规则4--压缩组件
压缩是如果工作的
HTTP1.1开始,Web客户端可通过HTTP请求中的Accept-Encoding头来标识对压缩的支持
Accept-Encoding:gzip deflate
压缩什么
实际上,值得压缩的内容包括XML和JSON在内任何文本响应,但是这里只关注脚本和样式表
因为他们用的最普遍。图片和PDF不应该被压缩,因为他们本来就是被压缩了的,视图对
他们进行压缩只会浪费CPU资源,还有可能增加文件大小。
根据经验通常对大于1kb或者2kb文件压缩。
节省
压缩通常能将响应的数据量减少近70%
配置
相关服务器开启gzip压缩
代理缓存
在Web服务器的响应中添加Vary头。web服务器可以告诉代理根据一个或者多个请求头来
改变缓存的响应。由于压缩的决定是基于accept-encoding的请求头。因此需要在服务器
的Vary响应头中包含Accept-Encoding
Vary:Accept-Encoding
将使得代理缓存响应多个版本。
边缘情形
白名单
如何平衡压缩和代理缓存支持的决定很复杂
压缩的实际效果
压缩脚本和样式表
================================================================================
规则5--将样式表放在顶部
逐步呈现
将样式表放在文档底部会导致在浏览器中阻止内容逐步呈现,为避免当样式变化时重绘页
中的元素,浏览器会阻塞内容逐步呈现。
sleep.cgi
白屏
将CSS放在底部
可能会导致白屏
将CSS放在顶部
在文档引入css两种方式
<link>
<style>
@import url("style2.css");
</style>
@import 可以有多个 但是必须放到其他规则之前
Link可以带来性能上的收益,@import可能带来白屏
无样式内容的闪烁
前段工程师应该做什么
如果你的样式表不要求呈现页面,可以想办法在文档加载完毕后动态的加载进来,否则
不管你的样式表在呈现页面时是否必需,都应该遵循放在顶部。
使用LINK标签将样式表放在文档HEAD中
================================================================================
规则6--将脚本放在底部
如果可以的话将脚本(外部js文件)移动到底部
脚本带来的问题
脚步阻塞下载
并行下载
从同一个主机同时下载的组件有限制
可修改相关配置,但不见的并行越多就越快,取决于的因素有很多
脚本阻塞下载
加载脚本时可能document.writer 改变页面所以阻塞并行加载
阻塞也保证的脚本的执行顺序
最差的情况:将脚步放置在顶部
最佳的情况:将脚本放置在底部
正确地放置
使用延迟(Defferred)脚本
================================================================================
规则7--避免CSS表达式
对于很多动态页面,可使用css表达式
background-color:expresssion((new Date()).getHours()%2?"#B8D4FF":"#F08A00");
跟新表达式
表达式的问题在于对其进行的求值的频率比人们期望的要高,它们不只是页面呈和大小
改变时求值,当页面滚动甚至鼠标在页面上移动时都要求值
围绕问题展开工作
创建一次性表达式或者使用事件处理器取代表达式
================================================================================
规则8--使用外部js和css
内联VS外置
纯纯而言内联更快
页面查看
空缓存VS完整缓存
组件重用
典型的对比结果
主页
主页内联好处不少
两全其美
加载后下载
动态内联
================================================================================
规则9--减少DNS查找
DNS缓存和TTL
影响DNS缓存的因素
TTL值
浏览器的视角
浏览器也有DNS缓存 不同于系统缓存
Internet Explorer
Firefox
减少DNS查找
通过Keep-alive 和较少的域名来减少DNS查找
================================================================================
规则10--精简javaScript
精简(Minification)
移除空格 注释 等不必要的东西
混淆(Obfuscation)
在精简的基础上改写代码,函数变量名转换成更短的字符串避免反向
混淆的三个主要缺点:
缺陷,混淆过程本身可能引入错误
维护,要对任何不能修改的符号(例如api函数)进行标记,防止混淆器修改他们
调试,调试比较困难
节省
精简js代码工具JSMin和Dojo Compressor
示例
结合gzip后精简和混淆差别不大 ,但是不会带来风险
锦上添花
内联脚本
内联的js也应该精简
压缩和精简
在精简的基础上压缩效果不错
精简css
精简CSS带来的节省通常小于精简js,因为通常css中的注释和空白比js少,最大的潜在节省
来自优化css--合并相同的类,移除不适用的类,css的依赖顺序的本质(层叠)决定了这是个
复杂的问题。最佳的解决方案还是移除注释和空白,并进行一些直观优化比如用“#606”代替
“#660066”和移除不必要的字符串(“0”代替“0px”)。
================================================================================
规则11--避免重定向
重定向(Redirect)用于将用户从一个URL重新路由到另一个URL,有很多种301和302 是最常用
重定向的类型
304并不是真的重定向只是用来响应get请求,避免下载以缓存的组件
js也可以重定向document.location 。最好使用HTTP 3xx代码重定向 使后退按钮能正常使用
重定向是如何损伤性能的
重定向引起的延迟严重,延迟整个HTML文档的传输,在HTML文档到达前,页面不会呈现任何内容
组件也不会被下载
重定向之外的其他选择
缺少结尾的斜线
链接网站
跟踪内部流量
跟踪出站流量
美化url
================================================================================
规则12--移除重复脚本
重复脚本--确有其事
重复脚本损伤性能
不必要的HTTP请求和执行js浪费的时间
IE没有缓存的情况下请求两次
对js执行多次js和firefox 都存在
避免重复脚本
可在模板系统中实现一个脚本管理模块。
================================================================================
规则13--配置ETag
实体标签(Entity Tag) 是web服务器和浏览器用于确认缓存组件有效性的
一种机制
条件GET请求
服务器在检测缓存的组件是否和原始服务器上的组件匹配是有两种方法
比较最新的修改日期
比较实体标签
最新修改日期 Last-Modefied Date
实体标签
ETag 提供另一种方式 在HTTP1.1 中引入 ETag是唯一标识一个组价的特定版本字符串 必须用引号括起
用ETag 响应头来指定组件的ETag
ETag带来的问题
ETag 通常使用组件的某些属性构造,当从另一台服务器发起GET请求ETag 不会匹配。 对集群环境来说
对于apache 和IIS 向ETag中嵌入数据都会大大降低性能
ETag用还是不用
最好移除
现实世界中的ETag
================================================================================
规则14--使Ajax可缓存
Web2.0、DHML和Ajax
异步与即时
优化Ajax请求
现实世界中的Ajax缓存
确保Ajax请求遵守性能指导,尤其应具有长久的Expires头
================================================================================
15--析构十大网站
页面大小、响应时间、YSlow等级
页面大小和响应时间有着很强的正比关系,比例系数0.94,添加更多的组件或者更大组件
回使之更慢
开发过程持续对页面大小和响应时间进行测绘师一种值得去做的分析
如何进行测试
================================================================================
规则1--减少HTTP请求
性能黄金法则:
10%-20%的最终用户响应的时间花在接受所请求的HTML文档上。剩下80%-90%的时间花在为
HTML文档所引用的所有组件(图片、脚本、样式、Flash等)进行的HTTP请求上。改善响应
时间最简单的途径就是减少组件的数量,并由此减少HTTP请求的数量。
图片地图
服务器端图片地图 传递 x,y 坐标映射
客户端图片地图
CSS Sprites
background-position:
优点:合并图片减少下载HTTP请求,并且降低图片大小(降低图片本身开销如颜色表,格式
信息等)
内联图片
data:[<mdediatype>][;base64],<data>
缺陷:不收IE支持,数据大小受限制
夸页面不会被缓存,不要内联公司LOGO,编码会导致logo变大
可用css将内联图片做背景,可缓存
合并脚本和样式表
================================================================================
规则2--使用内容发布网络(CDN加速技术Content Delivery NetWork)
如果应用程序web服务器(Application Web Server)离用户更近,则一个HTTP请求的响应
时间将缩短。
如果组件web服务器(Componet Web Server)离用户更近,则多个HTTP请求的响应时间将
变短
内容发布网络(Conten Delivery Networks)
CDN用于发布静态内容,如图片,脚本,样式表和Flash
节省
================================================================================
规则3--添加Expires头
长久的Expires头可是组件被缓存,可在后续页面浏览中避免不必要的HTTP请求。
应该讲Expires头用于图片、脚本、样式表和Flash等所有组件中
Expires头
Max-Age和mod_expires
HTTP1.1引入Cache-Control头来克服Expires头限制,因为Expires头使用了一个特定时间,
它要求服务器和客户端时钟严格同步且到期后服务器还需提供一个新日期
Cache-Control使用max-age指令指定组件被缓存多久,以秒为单位定义了一个更新窗口
对于不支持HTTP1.1浏览器可同时提供两个头,当同时存在时HTTP规范规定max-age 指令重写
Expires头。
mod_expires Apache模块使你使用Expires头时可像max-age那样以相对的方式设置日期,通过
Expires-Default指令完成。
跨浏览器改善缓存的最佳解决方案就是使用由ExpiresDefault设置的Expires头
空缓存VS完整缓存
不仅仅是图片
HTML文档不应当使用长久Expires头,因为它包含动态内容,这些内容在每次用户请求时
都将被更新。
修订文件名
设置Expires头后在过期前不会请求新数据,为了使用户获得组件新版本,需要在所有的
HTML页面修改组件名称
示例
没有Expires头时,组件仍会存储在浏览器的缓存中。在后续请求时,浏览器会检查缓存并发现
组件过期,像原始服务器发送一个条件GET请求,组件没有改变,原始服务器可发送一个很小的头
避免发送整个组件。
================================================================================
规则4--压缩组件
压缩是如果工作的
HTTP1.1开始,Web客户端可通过HTTP请求中的Accept-Encoding头来标识对压缩的支持
Accept-Encoding:gzip deflate
压缩什么
实际上,值得压缩的内容包括XML和JSON在内任何文本响应,但是这里只关注脚本和样式表
因为他们用的最普遍。图片和PDF不应该被压缩,因为他们本来就是被压缩了的,视图对
他们进行压缩只会浪费CPU资源,还有可能增加文件大小。
根据经验通常对大于1kb或者2kb文件压缩。
节省
压缩通常能将响应的数据量减少近70%
配置
相关服务器开启gzip压缩
代理缓存
在Web服务器的响应中添加Vary头。web服务器可以告诉代理根据一个或者多个请求头来
改变缓存的响应。由于压缩的决定是基于accept-encoding的请求头。因此需要在服务器
的Vary响应头中包含Accept-Encoding
Vary:Accept-Encoding
将使得代理缓存响应多个版本。
边缘情形
白名单
如何平衡压缩和代理缓存支持的决定很复杂
压缩的实际效果
压缩脚本和样式表
================================================================================
规则5--将样式表放在顶部
逐步呈现
将样式表放在文档底部会导致在浏览器中阻止内容逐步呈现,为避免当样式变化时重绘页
中的元素,浏览器会阻塞内容逐步呈现。
sleep.cgi
白屏
将CSS放在底部
可能会导致白屏
将CSS放在顶部
在文档引入css两种方式
<link>
<style>
@import url("style2.css");
</style>
@import 可以有多个 但是必须放到其他规则之前
Link可以带来性能上的收益,@import可能带来白屏
无样式内容的闪烁
前段工程师应该做什么
如果你的样式表不要求呈现页面,可以想办法在文档加载完毕后动态的加载进来,否则
不管你的样式表在呈现页面时是否必需,都应该遵循放在顶部。
使用LINK标签将样式表放在文档HEAD中
================================================================================
规则6--将脚本放在底部
如果可以的话将脚本(外部js文件)移动到底部
脚本带来的问题
脚步阻塞下载
并行下载
从同一个主机同时下载的组件有限制
可修改相关配置,但不见的并行越多就越快,取决于的因素有很多
脚本阻塞下载
加载脚本时可能document.writer 改变页面所以阻塞并行加载
阻塞也保证的脚本的执行顺序
最差的情况:将脚步放置在顶部
最佳的情况:将脚本放置在底部
正确地放置
使用延迟(Defferred)脚本
================================================================================
规则7--避免CSS表达式
对于很多动态页面,可使用css表达式
background-color:expresssion((new Date()).getHours()%2?"#B8D4FF":"#F08A00");
跟新表达式
表达式的问题在于对其进行的求值的频率比人们期望的要高,它们不只是页面呈和大小
改变时求值,当页面滚动甚至鼠标在页面上移动时都要求值
围绕问题展开工作
创建一次性表达式或者使用事件处理器取代表达式
================================================================================
规则8--使用外部js和css
内联VS外置
纯纯而言内联更快
页面查看
空缓存VS完整缓存
组件重用
典型的对比结果
主页
主页内联好处不少
两全其美
加载后下载
动态内联
================================================================================
规则9--减少DNS查找
DNS缓存和TTL
影响DNS缓存的因素
TTL值
浏览器的视角
浏览器也有DNS缓存 不同于系统缓存
Internet Explorer
Firefox
减少DNS查找
通过Keep-alive 和较少的域名来减少DNS查找
================================================================================
规则10--精简javaScript
精简(Minification)
移除空格 注释 等不必要的东西
混淆(Obfuscation)
在精简的基础上改写代码,函数变量名转换成更短的字符串避免反向
混淆的三个主要缺点:
缺陷,混淆过程本身可能引入错误
维护,要对任何不能修改的符号(例如api函数)进行标记,防止混淆器修改他们
调试,调试比较困难
节省
精简js代码工具JSMin和Dojo Compressor
示例
结合gzip后精简和混淆差别不大 ,但是不会带来风险
锦上添花
内联脚本
内联的js也应该精简
压缩和精简
在精简的基础上压缩效果不错
精简css
精简CSS带来的节省通常小于精简js,因为通常css中的注释和空白比js少,最大的潜在节省
来自优化css--合并相同的类,移除不适用的类,css的依赖顺序的本质(层叠)决定了这是个
复杂的问题。最佳的解决方案还是移除注释和空白,并进行一些直观优化比如用“#606”代替
“#660066”和移除不必要的字符串(“0”代替“0px”)。
================================================================================
规则11--避免重定向
重定向(Redirect)用于将用户从一个URL重新路由到另一个URL,有很多种301和302 是最常用
重定向的类型
304并不是真的重定向只是用来响应get请求,避免下载以缓存的组件
js也可以重定向document.location 。最好使用HTTP 3xx代码重定向 使后退按钮能正常使用
重定向是如何损伤性能的
重定向引起的延迟严重,延迟整个HTML文档的传输,在HTML文档到达前,页面不会呈现任何内容
组件也不会被下载
重定向之外的其他选择
缺少结尾的斜线
链接网站
跟踪内部流量
跟踪出站流量
美化url
================================================================================
规则12--移除重复脚本
重复脚本--确有其事
重复脚本损伤性能
不必要的HTTP请求和执行js浪费的时间
IE没有缓存的情况下请求两次
对js执行多次js和firefox 都存在
避免重复脚本
可在模板系统中实现一个脚本管理模块。
================================================================================
规则13--配置ETag
实体标签(Entity Tag) 是web服务器和浏览器用于确认缓存组件有效性的
一种机制
条件GET请求
服务器在检测缓存的组件是否和原始服务器上的组件匹配是有两种方法
比较最新的修改日期
比较实体标签
最新修改日期 Last-Modefied Date
实体标签
ETag 提供另一种方式 在HTTP1.1 中引入 ETag是唯一标识一个组价的特定版本字符串 必须用引号括起
用ETag 响应头来指定组件的ETag
ETag带来的问题
ETag 通常使用组件的某些属性构造,当从另一台服务器发起GET请求ETag 不会匹配。 对集群环境来说
对于apache 和IIS 向ETag中嵌入数据都会大大降低性能
ETag用还是不用
最好移除
现实世界中的ETag
================================================================================
规则14--使Ajax可缓存
Web2.0、DHML和Ajax
异步与即时
优化Ajax请求
现实世界中的Ajax缓存
确保Ajax请求遵守性能指导,尤其应具有长久的Expires头
================================================================================
15--析构十大网站
页面大小、响应时间、YSlow等级
页面大小和响应时间有着很强的正比关系,比例系数0.94,添加更多的组件或者更大组件
回使之更慢
开发过程持续对页面大小和响应时间进行测绘师一种值得去做的分析
如何进行测试