使用Post-load Pre-loading和Inline资源
如果你是一个负责的web开发者,你就已经坚持使用分离的概念了,并且为你的页面内容使用了HTML,CSS表现页面布局,JavaScript产生网页行为。页面中这些决然不同的部分就应该一直保存在不同的文件中。但是为了性能的原因,你有时候在设计开发首页的时候,考虑打破这些规则。首页应该是你网站中打开最快的页面,如果访问者发现首页加载很面,无论它的内容多么好,许多第一次访问的浏览者会离开你的网站。
当一个访问者访问你的网站的时候,这是他第一此访问,没有缓存你网页的内容,最好的方来传送你的页面的方法就是只需一个请求,没有分离的部分。这就意味着脚本和样式表需要内嵌。实际上也可能让图片内嵌(尽管在浏览器中不支持),不过这就扯远了。刚才那么做的话,除了语义不正确的话,使用脚本和样式也阻止了缓存网页的组件,因此一个好的策略就是在首页已经加载后,再去加载组件。有一个技术名字很令人迷惑的技术叫:post-load preloading。让我们看一个例子。
让我们假设有一个文件,包含你首页的内容,叫做home.html,而其它的HTLM文件包括的内容零散的分布在整俄站点的文件中,并且所有这些内容页面使用一个JavaScript文件,mystuff.js,而首页只需要这个文件中的一小部分而已。
你要使用的策略就是将首页要用到的JavaScript移除出mystuff.js文件,并且将它内嵌到home.html中。接着,一旦home.html完全加载,使用一个幕后的请求预加载mystuff.js。通过这种方式,当用户点击你的内容页面时,JavaScript已经加载到浏览器,并且已经缓存了。
这个技术已经被一些大家所采用:雅虎和Google已经内嵌脚本和样式表到他们的主页中了,并且已经使用了预加载。如果你访问Google的首页,它下载一些HTML和一个单独的图片,也就是它的Logo。接着,一旦它的主页完成加载,就有一个请求获取字画面,这个子画面不到第二页面加载是不需要的,第二个页面也就是显示搜索结果的页面。
雅虎搜索页面执行有条件的预加载,这个页面并不是自动加载额外资源,而是等待用户在搜索框中输入搜索关键字。一旦你开始输入关键字,这就几乎保证你将要提交一个搜索请求。接着你确实这么做了,你将会得到一个结果页面,包括一些已经为你缓存的部分了。
预加载一个图片可以用下面几行JavaScript代码做到:
new Image().src='image.png';
预加载JavaScript文件,使用JavaScript,包括DOM技术,并且还要创建一个新的<script>标签,如:
var js = document.createElement('script');
js.src = 'mysftuff.js';
document.getElementsByTagName('head')[0].appendChild(js);
js.src = 'mysftuff.js';
document.getElementsByTagName('head')[0].appendChild(js);
下面是CSS版本:
var css = document.createElement('link');
css.href = 'mystyle.css';
css.rel = 'stylesheet';
document.getElementsByTagName('head')[0].appendChild(css);
css.href = 'mystyle.css';
css.rel = 'stylesheet';
document.getElementsByTagName('head')[0].appendChild(css);
在第一个样本中,图片被请求了,但是从来没有使用,因此它不影响当前页面。在第二个样本中,脚本被加入到页面中,因此也被下载了,它就将会被分析执行。对于CSS也是同样的道理,它将应用到页面。如果这是不和要求的,你仍旧可以使用XMLHttpRequest预加载资源。
对内容进行gzip压缩
大多数现代的浏览器都能支持压缩内容,因此,一个很好的性能页面因该让它里面的所有内容压缩。因为大多数的图片,swf文件和其它的多媒体文件已经被压缩过了,你不需要担心如何压缩它们。
但是,你需要非常小心被压缩过的HTML,CSS,客户端脚本,和其它任何类型的文本内容。如果你向服务器提交返回XML 的XMLHttpRequests,你就应该确保你的服务器gzips这些内容。
如果你打开Firebug中的Net面板(或者使用LiveHTTPHeaders),你可以看到它们的内容都被压缩过,你查看响应的Content-Encoding头部就会发现。如下面的例子所示:
Request请求示例:
GET /2.2.2/build/utilities/utilities.js HTTP/1.1
Host: yui.yahooapis.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.5) Gecko/20070713 Firefox/2.0.0.5
Accept-Encoding: gzip,deflate
Host: yui.yahooapis.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.5) Gecko/20070713 Firefox/2.0.0.5
Accept-Encoding: gzip,deflate
响应示例:
HTTP/1.x 200 OK
Last-Modified: Wed, 18 Apr 2007 17:36:33 GMT
Vary: Accept-Encoding
Content-Type: application/x-javascript
Content-Encoding: gzip
Cache-Control: max-age=306470616
Expires: Sun, 16 Apr 2017 00:01:52 GMT
Date: Mon, 30 Jul 2007 21:18:16 GMT
Content-Length: 22657
Connection: keep-alive
Last-Modified: Wed, 18 Apr 2007 17:36:33 GMT
Vary: Accept-Encoding
Content-Type: application/x-javascript
Content-Encoding: gzip
Cache-Control: max-age=306470616
Expires: Sun, 16 Apr 2017 00:01:52 GMT
Date: Mon, 30 Jul 2007 21:18:16 GMT
Content-Length: 22657
Connection: keep-alive
在这个请求中,浏览器通知服务器它能支持压缩文件,和压缩编码(Accept-Encoding: gzip,deflate),服务器响应了gzip编码的内容(Content-Encoding: gzip).
当进行gzip压缩内容的时候遇到一个问题:你必须保证代理商不妨碍你。如果一个ISP的代理缓存了你的gzip压缩内容,并把它面向它的所有客户,那么一些不支持压缩内容的浏览器也会看到压缩的内容。
为了避免这种问题,你可以使用带有Vary: Accept-Encoding的响应头部,来告诉你的代理商只有发送同样的带有Accept-Encoding头部请求的,才高速缓存这些响应。在上面的那个例子中,浏览器说他支持gzip和deflate,并且服务器响应为代理提供一些额外的信息,声明对于任何发送同样Accept-Encoding 内容的请求的客户点,gzip编码的内容也是可以的。
这里有另外一个问题:一些浏览器(举个例子,IE 5.5, IE 6 SP 1)声称他们gzip压缩内容,但是当你用他们浏览时就会遇到问题(正如Microsoft downloads site和 support site所描述的那样)。如果你很在一使用使用这样浏览器的人(他们占到一个网站访问者总数的1%一下)的话,你可以使用一个不同的头部。在头部标记Cache-Control: Private,这就能消除代理进行高速缓存。另外一个方式就是使用头部Vary: *.来阻止代理高速缓存。
如果你对Accept-Encoding还是很迷惑的话,那么就考虑用deflate,作为第二种方法来编码内容,虽然在众多浏览器中不是很流行,但是也很效果,因此gzip被引用进来了。
总结
到现在为止,你已经知道很多关于如何优化一个站点项目的方法了(最重要的是,在构建你的站点的时候会考虑性能问题)。当提及到优化,记住总的经验法则,集中那些影响大的方面,而不是小的优化方面。
你或许选择不要去实现我们以上讨论的,但是你仍旧可以集中下面几条,也会产生很好的效果。
·产生很少的HTTP请求,通过组合页面部分,包括JavaScript文件,样式表,图片(使用CSS子画面)
·将文本内容,包括HTML、scripts、风格、XML 、JSON,纯文本压缩
·缩小化 ,将脚本置于底部,样式表置于顶部
·使用独立的自由释放cookie的域保存站点组成成分。
祝你优化工作好运,当你看到结果时,你就会很有成就感。