去年笔者(Chainn)读完了几本前端性能优化以及HTTP等网络方面的书,并在生产环境做了部分应用。这些书包括《高性能网站建设指南》、《高性能网站建设进阶指南》、《大型网站技术架构:核心原理与案例分析》、《HTTP权威指南》、《图解TCP/IP》等,最近遇到一些问题,又开始翻这些书,发现不少技术点颇为生疏,看来该总结一番了。先总结最实用的《高性能网站建设指南》一本书吧,后续还会出一个前端性能优化的系列。
先上一张图吧:
这本书主要讲了前端优化的14条规则:
1、减少http请求;
2、使用内容发布网络;
3、添加expires头部;
4、压缩组件;
5、将样式表放在顶部;
6、将脚本放在底部;
7、避免css表达式;
8、使用外部的javascript和css;
9、减少dns查找;
10、精简javascript;
11、避免重定向;
12、移除重复脚本;
13、配置etag;
14、使ajax缓存。
在了解这14条规则之前,先记住前端优化黄金法则:
只有10%~20%的最终用户响应时间花在了下载HTML文档上。其余的80%~90%时间花在了下载页面中的所有组件上。
HTTP相关概念也要了解:
HTTP请求类型:
GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE
压缩:
浏览器使用Accept-Encoding头来声明支持压缩:Accept-Encoding:gzip,deflate
服务器使用Content-Encoding头确认响应已被压缩:Content-Encoding:gzip
条件GET请求:浏览器在缓存中保存了一个组件的副本,当If-Modified-Since头询问组件副本是否可用,服务器若返回304响应,浏览器得到一个更小更快的响应(没有响应体)。
Expires:Expires:Wed,05 Oct 2016 19:16:20 GMT
Expires头明确指出浏览器是否可以使用组件副本。浏览器将过期时间和组件副本一同存入缓存,不再询问服务器组件副本是否可用。
Keep-Alive:浏览器和服务器均使用Connection:keep-alive头指出对Keep-Alive的支持。
浏览器或服务器通过发出Connection:close关闭连接。
注:在HTTP1.1中定义的管道技术普及之前,Keep-Alive依然是必要手段。对于HTTPS来说更重要,因为建立新的安全socket连接需要更多时间。
下面就总结一下这14条规则吧!
只有10%到20%的最终用户响应时间花在接收请求的HTML文档上面。剩下80%到90%的 时间花在为HTML文档所引用的所有组件(图片,脚本,flash,样式表等)进行的HTTP请求上。因此改善响应的最简单途径就是减少组件数量,由此减少HTTP请求的数量。
使用map标签进行坐标定位,减少图片数量。导航栏中使用了多个图片时候可以使用。缺点很多:手工方式很难完成坐标定位,且容易出错。除了矩形之外也难以定义其他形状,通过DHTML定义的图片IE中还无法工作。不建议使用。
通过把多个图片合并到一个图片,然后利用background-position进行定位,比使用分离图片快50%。图片地图中的图片必须是连续的,而CSS Sprites则没有这个限制。也有人认为合并后的图片比分离的图片总和还要大,合并后的图片包含附加的空白区域。实际是变小的,雪碧图降低了图片自身的开销。(颜色表,格式信息,等等)如果页面中背景,按钮,导航栏,链接需要使用很多图片,可以使用。优点——干净的标签,很少的图片和很短的响应时间。
缺点:后期修改麻烦,难以维护,牵一发动全身,没有之前改一个图片就好了容易
使用 data:URL的模式在WEB页面中包含图片,但无需任何额外的HTTP请求。我们都熟悉http:模式的URL。其他类似模式包括ftp:,file:和maito:
data:url模式
在1995年提出来:允许将小数据块内联为立即数,数据就在url自身中。
什么是内联图片
内联图片是一种新型的图像格式(在我看来是这样不知道理解对否),官方称为:data URI scheme。通常我们存储的图片在网页中需要写:
<img src="http://blog.xmaoseo.com/images/xmaoseo.jpg"/>
而内联图片写法会是
<img src="data:image/png;base64,iVAGRw0KGDCFGNSUhEUgACBBQAVGADCAIATYJ7ljmRGGAAGElEVQQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPACCCTElFTEVBQmGA"/>
内联图片语法
="data:image/png;base64,iVBOR....>
1、data - 取得数据的协定名称
2、image/png - 数据类型名称
3、base64 - 数据的编码方法
4、iUANR.... - 编码后的数据
5、: , ; - data URI scheme 指定的分隔符号
这种图片格式无需额外的HTTP请求是不错,但是还有一个重要的一点,浏览器不会缓存这种图像。 data url 节省了HTTP请求,但是如果这个图像在网页多个地方显示会加大网页的内容,延长下载时间。还有一点 IE8 以下都不支持这种图像,所以还是IE6的用户就比较悲催了。并且超过 100kb 图像使用base64编码也会增大图片大小。导致网页整体下载量增加。 (BASE64编码图片导致网站浏览缓慢崩溃http://blog.xmaoseo.com/125.html) 但是很多聪明人做法是把背景平铺类图片作为内联图片使用,这样效果很不错。也减少了HTTP请求加快了网站速度。那么你可能会问到如何获取图片的base64编码呢。网络上有很多免费的base编码和解码工具,但是有个最简单方法就是我们写一个PHP文件。使用base64_encode()进行编码:比如:
echo base64_encode(file_get_contents('211-11.JPG'));
如何解决网页下载延迟问题。最简单一个方法就是用写成CSS里的背景去调用CLASS 类名就可以了。比如咱们用上面的例子:
.blogxmao{background:url(data:image/png;base64,iVAGRw0KGDCFGNSUhEUgACBBQAVGADCAIATYJ7ljmRGGAAGElEVQQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPACCCTElFTEVBQmGA")}
..内容.....内容...
根据模块化原则, 我们应该将代码放到多个小文件中,但是这样会降低性能,因为每个文件都会导致一个额外的http请求。理想情况,一个页面不应该使用多余一个的脚本和样式表。世界前十网站脚本和样式表一般不超过2个。
使用模块化工具,比如seajs,requirejs进行优化。不然随着文件的增多,手动合并将会很麻烦。
内容分发网络(conten delivery network)是一组分布在多个不同地理位置的Web服务器。可以使用CDN服务提供商。
缩短相应时间,备份扩展存储能力和进行缓存,缓和WEB流量峰值压力(获取天气,娱乐体育新闻等等)
你的响应时间会受到其他网站——甚至是竞争对手的流量的影响。无法控制组件服务器所带来的特殊麻烦。比如,修改HHTP表头必须由服务提供商来完成。
如果CDN服务性能下降了,你的工作也会受到影响。当然你可以使用两个CDN服务提供商。
CDN用于发布静态图片(将所有静态组件转移到CDN),图片,脚本样式表,Flash,静态文件更易存储,有较少的依赖性。
Web页面包含大量组件,首次访问时间并不是唯一需要考虑的,页面的初访者会进行很多HTTP请求,但是可以使用一个长久的Expires头,使得这些组件被缓存。
长久的expires经常用于图片,然而可以用于所有组件,很多顶级网站并没有做到这一点,因为添加长久的ecpires头会带来额外的开发成本。
Expires:Mon,15 Apr 2025 00:00:00 GMT
它会告诉浏览器该响应的有效性会持续到2025年。
因为expires使用一个特定的时间,要求客户端和服务器端时钟严格同步,过期日期需要检查,还要配置新的日期,所以使用麻烦。HTTP1.1引入了Cache-Control头来克服它的限制。Cache-Control使用max-age指令来指定组件被缓存多久。以秒为单位定义了一个更 新窗。
对于不支持HTTP1.1的浏览器,你可以同时指定两个响应头——Expires和max-age.如果两者同时出现,后者将会重写前者。如果你很尽责,你仍然会担心Expires过期问题以及时钟同步问题。
幸运的是,mod_expires使你通过ExpirsDefault指令以相对方式设置日期。
ExpirsDefault 'access plus 10 years'
时间可以设置为年月日时分秒。它同时向响应中发送Expires头和max-age头。实际过期日期根据何时得到请求而变,但是max-age有优先权。时钟同步问题和固定日期更新不用担心了。
跨浏览器改善缓存最佳方案就是使用 ExpirsDefault设置的Expires.
用户第一次访问你的网站它不会对HTTP的请求的数量产生任何影响。此时浏览器的缓存是空的。性能改进取决于是否有完整缓存。
在那些每日一次一更新的网站,带有完整缓存的页面浏览百分比很少。旅游网站,email网站中每个用户会话可能产生多次页面浏览,百分比就高。
只要用户每个月至少访问一次,或者每次会话产生多次页面浏览,完整缓存就很有用,使用长久Expires就很有必要。
脚本,样式表,flash都可以缓存,但是HTML文档不应该使用,因为包含动态内容,每次都要更新。
大型网站,图片,样式表,脚本大部分都要缓存30天以上。但是经常需要变化的新闻图片等等,不应该使用。我们可以查看Last-Modifed中的值来看改变时间以及频率。
使用长久的Expires缺点是 :浏览器不会检查任何更新,直到过了过期日期。即使在服务器上更新了组件,浏览器因为缓存也不能获得最新组件。
为了确保用户能获得更新过的组件,需要在所有HTML页面中修改组件的文件名。
最有效的解决方案是修改其所有链接,这样。全新的请求将从原始服务器下载最新的内容。
使用php等动态语言生成HTML页将很简单,为所有组件的文件名使用变量,使用这种方法,在页面中更新文件名只需要简单地在某个地方修改变量。Yahoo经常将这一步作为生成过程的一部分——版本号嵌入在组件的文件名中(例如yahoo_2.0.6.js),而且在全局映射中修订过的文件名会自动更新。嵌入版本号不仅可以改变文件名,还能在调试中更容易找到准确的源代码文件。
规则1–3都是限制不必要的HTTP请求来减少响应时间,现在我们通过减少响应大小来减少响应时间。
压缩HTTP响应包(效果最显著)
删除注释
缩短URL
用于减小文件体积的文件压缩已经在email应用和ftp站点中使用了十年,同样的技术也可以用于向浏览器发布压缩的web页面。
从HTTP1.1开始,web客户端可以通过请求中的Accept-Encoding头来表示对文件压缩的支持。
————>
Accept-Encoding:gzip
如果web服务器看到请求中有这个头,就会使用客户端列出来的方法中的一种来压缩响应。并通过响应中的Content-Ecoding来通知客户端。
<————
Content-Ecoding:gzip
gzip是目前最有效,最流行的压缩方法,免费模式,并被标准化为RFC 1952.(90%使用)
很多网站会压缩HTML文档,压缩脚本和样式表也是非常值得的,还包括XML和JSON在内的任何文本响应。图片和PDF不应该解压缩,因为已经被压缩了。再压缩只会浪费CPU资源,还有可能会增加文件大小。
压缩的成本:服务器会花费额外的CPU周期来完成压缩,客户端要对压缩文件进行解压缩。要检测受益是否大于开销,需要考虑响应的大小,连接的带宽和和客户端服务器之间的Internet距离。
根据经验,通常对大于1KB或2KB的文件进行压缩。mod_gzip_minimum_file_size指令控制着希望压缩文件的最小值,默认值是500B。
美国十大流行网站中9个压缩了html,七个压缩了大多数脚本和样式表,只要五个压缩了所有脚本和样式表。这可以将页面减少70%。
压缩之后能将响应整体减少60%左右
配置gzip时使用的模块取决于Apache(intert上最流行的web服务器,份额70%以上)的版本。Apache1.3使用mod_gzip,2.3使用mod_deflate.
具体配置详情如何压缩,压缩哪些文件,压缩程度,类型(可使用正则匹配)可搜索mod_gzip的网站参考。
存在两种方式上的问题:
问题1:
不支持gzip的浏览器先访问了代理服务器,代理服务器转发请求,服务器返回未经压缩的响应包给代理服务器,代理服务器将未经压缩的响应包缓存后转发给该浏览器;
支持gzip的浏览器请求代理服务器,代理服务器发现缓存,直接将缓存的未经压缩的响应包返回给该支持gzip的浏览器。
结果:虽然支持gzip的浏览器收到的是未经压缩的响应包,未提高效率,但最终还能完成基本的请求。
问题2:
支持gizp的浏览器先访问了代理服务器,代理服务器转发请求,服务器返回经过压缩的响应包给代理服务器,代理服务器将经过压缩的响应包缓存后转发给该浏览器;
不支持gzip的浏览器请求代理服务器,代理服务器发现缓存,直接将缓存的经过压缩的响应包返回给该不支持gzip的浏览器。
结果:第二个不支持gzip的浏览器收到的是经过压缩的响应包,无法正常解析。
解决方法:在Web服务器中添加Vary头
Vary:Accept-Encoding
1.Web服务器通过客户端列出方法中的一种来压缩响应。
2.gzip是最理想的压缩方式。
3.需要压缩的内容:HTML文档、脚本、样式表、XML和JSON在内的任何文本响应。
4.不应该压缩的内容:图片和PDF(浪费CPU,增加大小)
5.压缩成本:服务器CPU开销和客户端解压缩耗费的资源
6.检测收益是否大于开销需要考虑的因素:响应的大小,连接的带宽,客户端与服务端Internet距离
7.根据经验,通常对大于1KB或2KB的文件进行压缩
8.mod_gzip_mininum_file_size控制着希望压缩文件的最小值,默认为500B
使用link标签将样式表放在文档head中
将css放在底部的时候(有观点觉得DHTML特性东西在最后展现,所以会把css放在底部觉得更优化。)实则不然,这样容易发生白屏和无样式内容的闪烁。
DHTML不是 W3C 标准
DHTML 指动态 HTML(Dynamic HTML)。
DHTML 是一个营销术语 - 被网景公司(Netscape)和微软公司用来描述 4.x 代浏览器应当支持的新技术。
DHTML 是一种用来创建动态站点的技术组合物。
对大多数人来说,DHTML 意味着 HTML 4.0、样式表以及 JavaScript 的结合物。
W3C 曾讲过:“动态HTML是一个被某些厂商用来描述可使文档动态性更强的HTML、样式表以及脚本的结合物的术语。”
比如一些打字机效果文字,闪烁文字,遮罩滤镜等等。
白屏容易产生的地方,特别是在IE中:
新窗口中打开时
重新加载时
作为主页(打开新的浏览器窗口)
FOUC flash of unstyles content 产生原因是没有吧样式表放在head顶部,或者使用了@import导入(即便放在前面了,样式表还是会最后下载)
所以避免无样式内容闪烁最好方法就是使用link标签将其放在head顶部
脚本放在顶部会阻塞后面内容的呈现和组件的下载。进而产生白屏现象。 放在底部将会产生最小影响和最佳效应。
并行下载
从同一个主机同时下载的组件有限制
可修改相关配置,但不见的并行越多就越快,取决于的因素有很多
脚本阻塞下载
加载脚本时可能执行document.write 改变页面所以阻塞并行加载
阻塞也保证的脚本的执行顺序
最差的情况:将脚步放置在顶部(优化:使用延迟脚本)
最佳的情况:将脚本放置在底部
css表达式 expression方法被其他浏览器忽略,IE支持,这种方法虽然强大但是非常危险。
表达式求之的频率远高于人们的期望,不仅在页面呈现和大小改变时求值,鼠标拖拽,页面滚动时候都会求值。所以要避开css表达式,用事件处理器来为特定的事件提供所期望的动态行为。
内联VS外置
单纯比较而言,内联在第一次加载时要快一点,因为内联只有一个http请求。
但是多方面考虑还是要用外置。
内联无法缓存,外置可以缓存,而且当你页面使用了相同的js和css时候,可以组件重用,缓存优势更明显。
最重要的是,外置可以降低耦合度,调试更加方便~~~
Internet通过IP地址查找服务器,浏览器查找一个给定主机名的IP地址要花费20—120毫秒,也是有开销的,充当这个角色的就是DNS(domain name system)
1.TTL值
2.浏览器的视角:浏览器也有DNS缓存 不同于系统缓存
通过Keep-alive 和较少的域名来减少DNS查找
使用较少的域名,谷歌只有一个,因为只有两个组件,可以一次并行下载完,两个主机是最好的,平衡并行下载和DNS查询。
在HTTP请求中使用 Connection:keep-alive 来保持持久连接。早期HTTP请求中。每个请求都要打开一个socket连接,因为页面中很多请求收拾指向同一个服务器,所以这样效率很低。持久连接的引入使得浏览器可以在一个单独的连接上进行多个请求。
HTTP1.1中定义的管道可以在一个单独的socket上发送多个请求而无需等待响应,而且性能优于持久连接。
当客户端的DNS缓存为空(浏览器和操作系统都是)时,DNS查找的数量与Web页面中唯一主机名的数量相等。
建议:将组件分别放到2~4个主机名下(减少主机名潜在减少了组件并行下载的数量)。
精简是从代码中移除不必要的字符以减小其大小。进而改善加载时间的实践。
代码精简之后所有的注释以及不必要的空白字符(空格,换行,制表符),可以减小20%。
混淆是可以应用在源代码上的另外一种优化方式,和精简一样,也会移除注释和空白,作为改写的一部分,函数和变量的名字将被转换为更短的字符串。
这样的代码更加精炼,但是更难阅读。通常这样做是为了增加对代码进行反向工程的难度,但对提高性能也有帮助。
混淆js的三个缺点
缺陷:混淆更加复杂,混淆过程本身很有可能引入错误。
维护: 由于混淆会改变js符号,因此需要对任何不能改变的符号(例如API函数)进行标记,防止混淆修改他们。
调试:很难阅读,调试更加困难。
精简从来不会带来问题,但是混淆会带来很多问题和缺陷。维护庞大的js建议使用精简而不是混淆。
实际经过gzip压缩之后,精简和混淆差别很小。
精简css带来的节省通常小于js,因为注释和空白比较少。最大的潜在节省来自于优化css——合并相同的类,移除不使用的类等。css依赖顺序的本质(成为层叠样式表的原因)决定了这是一个复杂的问题。这个领域还需要进一步的研究和工具开发。
通常解决方案有使用颜色缩写,用0代替0px。
优化CSS:
合并相同的类、移除不使用的类
移除注释和空白
直观优化(如缩写#606代替#660066)
移除不必要字符(例如0代替0px)
重定向用于将用户从一个URL重新路由到另一个URL。重定向有很多种重。301和302是最常用的两种。
通常针对HTML文档进行重定向,但也可能用在请求页面中的组件(图片脚本)。
实现重定向有很多原因:
网站重新设计
跟踪流量
记录广告点击
建立易于记忆的URL
301和302是使用的最多的。
<————
HTTP1.1 301 Moved permanetely
Location: http://www.baidu.com
Content-type:text/html
浏览器会自动将用户带到Location字段给出的URL。重定向所必需的信息都出现了。301和302不会被缓存,除非有附加头,如Expires和Cache-Control
将用户重定向到其他URL的方法
1.HTML文档中的meta refresh 标签可以在其content属性所指定的秒数之后重定向用户
<meta http-equiv="refresh" content="0; url=http://www.baidu.com" >
2.js也可以执行重定向,documet.location设置为期望的url
如果你必须重定向,最好的技术是使用标准的3XX HTPP状态码,主要是为了确保后退按钮可以正常工作
HTML重定向小科普
页面定期刷新,如果加url的,则会重新定向到指定的网页,content后面跟的是时间(单位秒),把这句话加到指定网页的里。一般也用在实时性很强的应用中,需要定期刷新的,如新闻页面,论坛等,不过一般不会用这个,都用新的技术比如ajax等。
<meta http-equiv="refresh" content="0; url=">
经过一段时间转到另外某个页面,这里0表示没有延时,直接跳转到后面的URL;把0改成1,则延时1秒后跳转。网页自动计时跳转。这个页面跳转的好处在于不需要JS调用,直接在html文件头里加入
<meta http-equiv="refresh[刷新-这里指定动作]" content="5[这里是时间];url=/article[这里是跳转的URL]">
重定向时的第一个HTTP请求会阻塞后面html文档的加载,四个重定向请求就会将用户带到期望HTML文档的时间多花费一半。
1.缺少结尾的斜线/:这是最为浪费和频繁的,也是web开发人员没注意的。没有/时会导致301响应,这是很多web服务器的默认行为,所以很简单,url后面加一个/
2.连接网站:将旧网站连接到新网站只是重定向这种常见应用的一种表现形式。重定向降低了开发的复杂性,但是也损害了用户体验。
跟踪内部流量:分析离开网页首页之后的流量去向。使用referer。难处在于只能分析内部,自己公司的,如果目标网站属于其他公司则不可能分析referer日志了。
3.跟踪出站流量:也不用重定向而是用信标(beacon)——一个hppt请求
4.美化URl: 使用重定向的另一种动机是使URL美观并且易于记忆。
这一节有点扯和凑数。简单网站手动查看排序依赖关系即可。现在大型网站需要使用grunt.webpack .seajs等前端自动化工具,处理依赖关系并进行打包,也就是模块化等高级,方便的知识。
实体标签(Entity Tag,ETag)是服务器和浏览器用于确认缓存组件有效性的一种机制。
如果缓存组件过期了或者用户明确地重新加载了页面,浏览器在重用之前必须首先检查它是否有效。这称作一个条件GET请求。虽然浏览器必须产生这个http请求,但是仍比简单地下载所有已过期的组件效率高。如果浏览器组件是有效的(相互匹配)原始服务器则不会返回整个组件,而是返回304 not modifed状态码。
检测匹配有两种方式
第一次请求响应
————>
GET /i/xx.jpg HTTP 1.1
HOST www.xxx.com
<————
HTTP 1.1 20 OK
Last-Modified:true .12 dec 2015 03:03:09 GMT
Content-Length:1024
第二次请求响应
————>
GET /i/xx.jpg HTTP 1.1
HOST www.xxx.com
If-Modified-Since:True,12 dec 2015 03:03:09 GMT
<————
HTTP 1.1 304 not modifed
实体是我们之前提到的组件的另一种称呼。ETag是唯一标识了一个组件的一个特定版本的字符串,必须带上引号。这种为验证实体提供了更为灵活的机制——可以根据user-agent,accept-language头而改变。
第一次请求响应
————>
GET /i/xx.jpg HTTP 1.1
HOST www.xxx.com
<————
HTTP 1.1 20 OK
Last-Modified:true .12 dec 2015 03:03:09 GMT
ETag:"10c34ba-8ba-abds3b3"
Content-Length:1024
第二次请求响应
————>
GET /i/xx.jpg HTTP 1.1
HOST www.xxx.com
If-Modified-Since:True,12 dec 2015 03:03:09 GMT
If-None-Match:"10c34ba-8ba-abds3b3"
<————
HTTP 1.1 304 not modifed
对于使用服务器集群来处理请求的网站,匹配次数会大大降低。此时etag就降低了缓存效率,导致了不必要的请求、If-None-Match的优先级比If-Modified-Since的优先级更高,加剧了问题严重性。
稍微麻烦一点,你要用php等脚本语言配置ETag头。(如果你使用的是具有默认配置的Apache和iis)
你还可以将ETag头安全移除在apache配置文件中,减少它的坏处。
从ETag中移除ChangeNumber或者完全移除ETag可以避免当数据已经位于浏览器缓存中时进行不必要的和低效的下载。
本书写的时候google docs和mail刚出来,刚应用ajax,知识点不是很多。google的ajax请求中并不完全是使用XMLHttpRequest,也有的使用了IFrame。
有的响应中因为数据隐私原因而不能缓存,当数据被认为是私有的时候,大多会在响应中使用
Cache-Control:no-store
。
处理数据隐私的更好方法是使用安全通信协议如安全套接字层(Secure Socket Layer,SSL)。SSL响应式可以缓存的。有关SSL细节,可以参考我最近写的博客:ssl四次握手简述
在goole docs中缓存电子表格不像添加一个长久的expires头那样简单,如果用户修改了电子表格,我们必须确保产生变化后不会再使用缓存的请求。
简单的解决方案还是使用查询字符串。后端应该具有一个时间戳,来表示未次修改发生的时间,并将其嵌入到ajax请求的查询字符串中。
/ar?id=[snip...]&srow=0&erow=100%t=15398503189
确保Ajax请求遵守性能指导,尤其应具有长久的Expires头。
1.使用yslow可以清晰的看出14条军规里面A-F的等级速度。
2.页面大小和响应时间成正比关系。比例系数0.94。
3.使用http1.1,默认开启了持久化连接,效果好的多。
4.图片转换为文字可以减少请求数量。联想到BootStrap中使用的icon字体图标。
5.html中的img加上with,height,提前限制好,不用等到css再渲染确定。
6.使用IFrame提供广告的方式值得探讨。IFrame实现了广告与实际页面的彻底分离,使得两者的团队和系统能够互不依赖。缺点是每个IFrame都带来一个额外http请求。使用IFrame又是合理的。因为广告内容来自第三方通常包含自己的js代码。将其放到iframe中也就将js放在了沙箱,可以带来极高安全性。(第三方代码无法访问web页面的命名空间) 将IFrame的src属性设置为about:blank 这不会生成任何HTTP流量。
7.预加载,可以提前判断用户的访问,后台再下载所需组件。预加载是提高网站后续页面加载速度的一种很好的方式。瀑布流中,图片不到视窗中,不加载,延迟加载(这方面目前观点不清)
8.使用png格式比gif格式图片好。有png优化器,当然jpg格式也更好,适用场景不同。
github.com/KristenXu/ReadingNotes/blob/master/HighPerformanceWebSites.md