﻿<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Xixi&#039;s Blog &#187; javascript</title>
	<atom:link href="http://www.xixis.net/archives/tag/javascript/feed" rel="self" type="application/rss+xml" />
	<link>http://www.xixis.net</link>
	<description>http://www.xixis.net  &#124;  Eternal Sunshine of the Spotless Mind</description>
	<lastBuildDate>Thu, 12 Jan 2012 06:04:19 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>IE中JS错误(KB927917)的解决办法</title>
		<link>http://www.xixis.net/archives/ie-in-the-js-error-kb927917-solution.html</link>
		<comments>http://www.xixis.net/archives/ie-in-the-js-error-kb927917-solution.html#comments</comments>
		<pubDate>Thu, 04 Mar 2010 16:23:37 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[KB927917]]></category>

		<guid isPermaLink="false">http://www.xixis.net/archives/ie%e4%b8%adjs%e9%94%99%e8%af%afkb927917%e7%9a%84%e8%a7%a3%e5%86%b3%e5%8a%9e%e6%b3%95.html</guid>
		<description><![CDATA[博客用了半静态化后，使用了月光的js版postviews，但是ie会提示KB927917的错误，计数器有时候也不会正常工作。查了一些资料，终于解决了。
页面错误提示：Unable to modify the parent container element before the child element is closed (KB927917)
错误描述：“用户代理: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media CenterPC 6.0; InfoPath.2)，时间戳: Tue, 12 May 2009 13:49:16 UTC消息: HTML Parsing Error: Unable to modify the parent container element before the child element is closed (KB927917)行: 0字符: 0代码: 0。”
 
简单描述：子HTML元素内包含试图修改子容器的父容器元素的脚本。 
去微软知识库查了KB927917，其说明写道：“出现此问题的原因子容器 HTML 元素包含试图修改子容器的父容器元素的脚本。 脚本试图使用innerHTML&#160; 方法或&#160; appendChild&#160; 方法修改父容器元素。例如如果 DIV 元素是在 BODY 元素中的子容器，并在 DIV 元素中的一个 SCRIPT 块尝试修改 DIV 元素的父容器的BODY 元素，可能会出现此问题”。   这个问题是伟大的浏览器IE发现的，各大浏览器没有这种反馈，原因就是解析的JavaScript的机制不同。这个问题一直到IE8还是存在，估计一直也存在。因为解析JavaScript的解析IE是边读边执行的，所以如果脚本允许修改父元素，并且子元素又没关闭的话，会失去条理性。 
&#160;
解决：将JS代码或引用文件放入页面底部的body之后，这样代码在body被解释之后执行，就不会出现这个错误了，对于js版的postviews，将footer.php中的

&#60;?php wp_footer&#40;&#41;; ?&#62;

放置于&#60;/body&#62;后即可。如果有其他内容需要置于body内的。则修改插件postviews.php文件81行左右，将如下语句注释掉

#add_action(&#34;wp_footer&#34;,&#34;the_views_javascript&#34;);

然后将下面的代码置入footer.php的后面

&#60;?php
if&#40;is_single&#40;&#41; &#41;&#123;
	echo &#34;&#60;script language=\&#34;javascript\&#34; ...]]></description>
			<content:encoded><![CDATA[<p>博客用了半静态化后，使用了月光的js版postviews，但是ie会提示<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/kb927917" title="显示KB927917的所有日志" target="_blank">KB927917</a></span>的错误，计数器有时候也不会正常工作。查了一些资料，终于解决了。</p>
<p>页面错误提示：<strong>Unable to modify the parent container element before the child element is closed (<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/kb927917" title="显示KB927917的所有日志" target="_blank">KB927917</a></span>)</strong></p>
<p>错误描述：“用户代理: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media CenterPC 6.0; InfoPath.2)，时间戳: Tue, 12 May 2009 13:49:16 UTC消息: HTML Parsing Error: Unable to modify the parent container element before the child element is closed (<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/kb927917" title="显示KB927917的所有日志" target="_blank">KB927917</a></span>)行: 0字符: 0代码: 0。”</p>
<p> <span id="more-400"></span>
<p>简单描述：子HTML元素内包含试图修改子容器的父容器元素的脚本。 </p>
<p>去微软知识库查了KB927917，其说明写道：“出现此问题的原因子容器 HTML 元素包含试图修改子容器的父容器元素的脚本。 脚本试图使用innerHTML&#160; 方法或&#160; appendChild&#160; 方法修改父容器元素。例如如果 DIV 元素是在 BODY 元素中的子容器，并在 DIV 元素中的一个 SCRIPT 块尝试修改 DIV 元素的父容器的BODY 元素，可能会出现此问题”。   <br />这个问题是伟大的浏览器<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/ie" title="显示IE的所有日志" target="_blank">IE</a></span>发现的，各大浏览器没有这种反馈，原因就是解析的JavaScript的机制不同。这个问题一直到IE8还是存在，估计一直也存在。因为解析JavaScript的解析<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/ie" title="显示IE的所有日志" target="_blank">IE</a></span>是边读边执行的，所以如果脚本允许修改父元素，并且子元素又没关闭的话，会失去条理性。 </p>
<p>&#160;</p>
<p>解决：将JS代码或引用文件放入页面底部的body之后，这样代码在body被解释之后执行，就不会出现这个错误了，对于js版的postviews，将footer.php中的</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> wp_footer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>放置于&lt;/body&gt;后即可。如果有其他内容需要置于body内的。则修改插件postviews.php文件81行左右，将如下语句注释掉</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#add_action(&quot;wp_footer&quot;,&quot;the_views_javascript&quot;);</span></pre></div></div>

<p>然后将下面的代码置入footer.php的</body>后面</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>is_single<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;script language=<span style="color: #000099; font-weight: bold;">\&quot;</span><span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/javascript" title="显示javascript的所有日志" target="_blank">javascript</a></span><span style="color: #000099; font-weight: bold;">\&quot;</span> type=<span style="color: #000099; font-weight: bold;">\&quot;</span>text/<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/javascript" title="显示javascript的所有日志" target="_blank">javascript</a></span><span style="color: #000099; font-weight: bold;">\&quot;</span>&gt;
try{
	var elScript = document.createElement(<span style="color: #000099; font-weight: bold;">\&quot;</span>script<span style="color: #000099; font-weight: bold;">\&quot;</span>);
	elScript.setAttribute(<span style="color: #000099; font-weight: bold;">\&quot;</span>language<span style="color: #000099; font-weight: bold;">\&quot;</span>, <span style="color: #000099; font-weight: bold;">\&quot;</span>javascript<span style="color: #000099; font-weight: bold;">\&quot;</span>);
	elScript.setAttribute(<span style="color: #000099; font-weight: bold;">\&quot;</span>src<span style="color: #000099; font-weight: bold;">\&quot;</span>, <span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><span style="color: #339933;">.</span>get_option<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;home&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;/wp-counter.php?post_id=<span style="color: #000099; font-weight: bold;">\&quot;</span> + escape(strBatchView));
	document.getElementsByTagName(<span style="color: #000099; font-weight: bold;">\&quot;</span>body<span style="color: #000099; font-weight: bold;">\&quot;</span>)[0].appendChild(elScript);
	}
catch(e){};
&lt;/script&gt; &quot;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.xixis.net/archives/ie-in-the-js-error-kb927917-solution.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>flickr对javascript干的好事</title>
		<link>http://www.xixis.net/archives/flickr-doing-a-good-thing-for-javascript.html</link>
		<comments>http://www.xixis.net/archives/flickr-doing-a-good-thing-for-javascript.html#comments</comments>
		<pubDate>Sun, 07 Feb 2010 15:17:43 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[gzip]]></category>

		<guid isPermaLink="false">http://www.xixis.net/?p=308</guid>
		<description><![CDATA[在一个讨论web技术的网站vitamin上发现这篇《Serving JavaScript Fast》，读过之后大有收获，茅塞顿开。于是就有了翻译过来的念头——我这人有个毛病，看到有意思的英文文章，就想自己翻过来（虽然英文水平很烂）。先在网上查了查，已经有blog谈到这篇文章（我算是后知后觉了），有总结要点的《Flickr 的开发者的 Web 应用优化技巧》，也有延伸开来的《接着讲Flickr的八卦》，但似乎没有全文翻译的（这下就好，不会忙了半天发现是无用功）。之后，就写信问作者可不可以，作者一口答应：“sure &#8211; i’d love you to translate it”，只是要求我翻好之后给他一个链接地址。得到准许，心里就有底了。
 

先介绍一下作者。Cal Henderson，伦敦人，现居加利福尼亚的旧金山。PHP，MySQL和Perl专家，现任flickr架构师（flickr被收购后就在yahoo了），同时也是vitamin的特聘顾问（写些技术性文章）。
既然他是架构师，flickr用的应该就是文中谈到的这些技术，于是参照文章，再对比网站，种种迹象表明确实如此。虽然在中国访问flickr速度不敢恭维，加速效果不得而知，但其用了n多css和javascript资源却似乎从没出过什么问题，也从侧面印证了这些技术的有效性。
仔细的看完文章，还有个强烈的感觉：这老兄也太能卖关子了，一句话非分成三句说，摆事实讲道理是够透彻，就是有点太@#$%了…… 算了，他怎么说我怎么翻吧，忠实于原著嘛，要不就成篡改了。经过几天努力，加上同事thincat兄倾力援手（小弟不胜感激啊），终于完工（@_@ 真是苦力活啊，我再也不想干了～）。
全文翻译如下：
让javascript跑得更快
作者：Cal Henderson
下一代web应用让javascript和css得堪大用。我们会告诉你怎样使这些应用又快又灵。
建立了号称“Web 2.0”的应用，也实现了富内容（rich content）和交互，我们期待着css和javascript扮演更加重要的角色。为使应用干净利落，我们需要完善那些渲染页面的文件，优化其大小和形态，以确保提供最好的用户体验——在实践中，这就意味着一种结合：使内容尽可能小、下载尽可能快，同时避免对未改动资源不必要的重新获取。
由于css和js文件的形态，情况有点复杂。跟图片相比，其源代码很有可能频繁改动。而一旦改动，就需要客户端重新下载，使本地缓存无效（保存在其他缓存里的版本也是如此）。在这篇文章里，我们将着重探讨怎样使用户体验最快：包括初始页面的下载，随后页面的下载，以及随着应用渐进、内容变化而进行的资源下载。
我始终坚信这一点：对开发者来说，应该尽可能让事情变得简单。所以我们青睐于那些能让系统自动处理优化难题的方法。只需少许工作量，我们就能建立一举多得的环境：它使开发变得简单，有极佳的终端性能，也不会改变现有的工作方式。
好大一沱
老的思路是，为优化性能，可以把多个css和js文件合并成极少数大文件。跟十个5k的js文件相比，合并成一个50k的文件更好。虽然代码总字节数没变，却避免了多个HTTP请求造成的开销。每个请求都会在客户端和服务器两边有个建立和消除的过程，导致请求和响应header带来开销，还有服务器端更多的进程和线程资源消耗（可能还有为压缩内容耗费的cpu时间）。
（除了HTTP请求，）并发问题也很重要。默认情况下，在使用持久连接（persistent connections）时，ie和firefox在同一域名内只会同时下载两个资源（在HTTP 1.1规格书中第8.1.4节的建议）（htmlor注：可以通过修改注册表等方法改变这一默认配置）。这就意味着，在我们等待下载2个js文件的同时，将无法下载图片资源。也就是说，这段时间内用户在页面上看不到图片。
（虽然合并文件能解决以上两个问题，）可是，这个方法有两个缺点。第一，把所有资源一起打包，将强制用户一次下载完所有资源。如果（不这么做，而是）把大块内容变成多个文件，下载开销就分散到了多个页面，同时缓解了会话中的速度压力（或完全避免了某些开销，这取决于用户选择的路径）。如果为了随后页面下载得更快而让初始页面下载得很慢，我们将发现更多用户根本不会傻等着再去打开下一个页面。
第二（这个影响更大，一直以来却没怎么被考虑过），在一个文件改动很频繁的环境里，如果采用单文件系统，那么每次改动文件都需要客户端把所有css和js重新下载一遍。假如我们的应用有个100k的合成的js大文件，任何微小的改动都将强制客户端把这100k再消化一遍。
分解之道
（看来合并成大文件不太合适。）替代方案是个折中的办法：把css和js资源分散成多个子文件，按功能划分、保持文件个数尽可能少。这个方案也是有代价的，虽说开发时代码分散成逻辑块（logical chunks）能提高效率，可在下载时为提高性能还得合并文件。不过，只要给build系统（把开发代码变成产品代码的工具集，是为部署准备的）加点东西，就没什么问题了。
对于有着不同开发和产品环境的应用来说，用些简单的技术可以让代码更好管理。在开发环境下，为使条理清晰，代码可以分散为多个逻辑部分（logical components）。可以在Smarty（一种php模板语言）里建立一个简单的函数来管理javascript的下载：


SMARTY:
&#123;insert_js files=&#34;foo.js,bar.js,baz.js&#34;&#125;
&#160;
PHP:
function smarty_insert_js&#40;$args&#41;&#123;   foreach &#40;explode&#40;',', $args&#91;'files'&#93;&#41; as $file&#41;&#123;     echo &#34;&#60;script type=\&#34;text/javascript\&#34; SOURCE=\&#34;/javascript/$file\&#34;&#62;&#60;/script&#62;\\n&#34;;   &#125;
&#125;
&#160;
OUTPUT:
&#60;script type=&#34;text/javascript&#34; SOURCE=&#34;/javascript/foo.js&#34;&#62;&#60;/script&#62;
&#60;script type=&#34;text/javascript&#34; SOURCE=&#34;/javascript/bar.js&#34;&#62;&#60;/script&#62;
&#60;script type=&#34;text/javascript&#34; SOURCE=&#34;/javascript/baz.js&#34;&#62;&#60;/script&#62;

（htmlor注：wordpress中会把“src”替换成不知所谓的字符，因此这里只有写成“SOURCE”，使用代码时请注意替换，下同）
就这么简单。然后我们就命令build过程（build process）去把确定的文件合并起来。这个例子里，合并的是foo.js和bar.js，因为它们几乎总是一起下载。我们能让应用配置记住这一点，并修改模板函数去使用它。（代码如下：）

SMARTY:
&#123;insert_js files=&#34;foo.js,bar.js,baz.js&#34;&#125;
&#160;
PHP:
# 源文件映射图。在build过程合并文件之后用这个图找到js的源文件。

$GLOBALS&#91;'config'&#93;&#91;'js_source_map'&#93; = array&#40;   'foo.js'	=&#62; 'foobar.js',   'bar.js'	=&#62; 'foobar.js',   'baz.js'	=&#62; 'baz.js',
&#41;;
&#160;
function smarty_insert_js&#40;$args&#41;&#123;   if &#40;$GLOBALS&#91;'config'&#93;&#91;'is_dev_site'&#93;&#41;&#123;     $files = explode&#40;',', $args&#91;'files'&#93;&#41;;   &#125;else&#123;     $files = array&#40;&#41;; ...]]></description>
			<content:encoded><![CDATA[<p>在一个讨论web技术的网站<a href="http://www.thinkvitamin.com/">vitamin</a>上发现这篇<a href="http://www.thinkvitamin.com/features/webapps/serving-javascript-fast">《Serving JavaScript Fast》</a>，读过之后大有收获，茅塞顿开。于是就有了翻译过来的念头——我这人有个毛病，看到有意思的英文文章，就想自己翻过来（虽然英文水平很烂）。先在网上查了查，已经有blog谈到这篇文章（我算是后知后觉了），有总结要点的<a href="http://www.dbanotes.net/web/flickr_web_tech.html">《Flickr 的开发者的 Web 应用优化技巧》</a>，也有延伸开来的<a href="http://blog.94smart.com/2006/05/26/744.html">《接着讲Flickr的八卦》</a>，但似乎没有全文翻译的（这下就好，不会忙了半天发现是无用功）。之后，就写信问作者可不可以，作者一口答应：“sure &#8211; i’d love you to translate it”，只是要求我翻好之后给他一个链接地址。得到准许，心里就有底了。</p>
<p> <span id="more-308"></span>
</p>
<p>先介绍一下作者。<a href="http://www.iamcal.com/">Cal Henderson</a>，伦敦人，现居加利福尼亚的旧金山。PHP，MySQL和Perl专家，现任<a href="http://www.flickr.com/">flickr</a>架构师（flickr被收购后就在<a href="http://www.yahoo.com/">yahoo</a>了），同时也是vitamin的<a href="http://www.thinkvitamin.com/advisors/cal_henderson.php">特聘顾问</a>（写些技术性文章）。</p>
<p>既然他是架构师，flickr用的应该就是文中谈到的这些技术，于是参照文章，再对比网站，种种迹象表明确实如此。虽然在中国访问flickr速度不敢恭维，加速效果不得而知，但其用了n多css和<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/javascript" title="显示javascript的所有日志" target="_blank">javascript</a></span>资源却似乎从没出过什么问题，也从侧面印证了这些技术的有效性。</p>
<p>仔细的看完文章，还有个强烈的感觉：这老兄也太能卖关子了，一句话非分成三句说，摆事实讲道理是够透彻，就是有点太@#$%了…… 算了，他怎么说我怎么翻吧，忠实于原著嘛，要不就成篡改了。经过几天努力，加上同事<a href="http://my.donews.com/thincat/">thincat</a>兄倾力援手（小弟不胜感激啊），终于完工（@_@ 真是苦力活啊，我再也不想干了～）。</p>
<p>全文翻译如下：</p>
<h4>让<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/javascript" title="显示javascript的所有日志" target="_blank">javascript</a></span>跑得更快</h4>
<p>作者：Cal Henderson</p>
<p>下一代web应用让javascript和css得堪大用。我们会告诉你怎样使这些应用又快又灵。</p>
<p>建立了号称“Web 2.0”的应用，也实现了富内容（rich content）和交互，我们期待着css和javascript扮演更加重要的角色。为使应用干净利落，我们需要完善那些渲染页面的文件，优化其大小和形态，以确保提供最好的用户体验——在实践中，这就意味着一种结合：使内容尽可能小、下载尽可能快，同时避免对未改动资源不必要的重新获取。</p>
<p>由于css和js文件的形态，情况有点复杂。跟图片相比，其源代码很有可能频繁改动。而一旦改动，就需要客户端重新下载，使本地缓存无效（保存在其他缓存里的版本也是如此）。在这篇文章里，我们将着重探讨怎样使用户体验最快：包括初始页面的下载，随后页面的下载，以及随着应用渐进、内容变化而进行的资源下载。</p>
<p>我始终坚信这一点：对开发者来说，应该尽可能让事情变得简单。所以我们青睐于那些能让系统自动处理优化难题的方法。只需少许工作量，我们就能建立一举多得的环境：它使开发变得简单，有极佳的终端性能，也不会改变现有的工作方式。</p>
<h3>好大一沱</h3>
<p>老的思路是，为优化性能，可以把多个css和js文件合并成极少数大文件。跟十个5k的js文件相比，合并成一个50k的文件更好。虽然代码总字节数没变，却避免了多个HTTP请求造成的开销。每个请求都会在客户端和服务器两边有个建立和消除的过程，导致请求和响应header带来开销，还有服务器端更多的进程和线程资源消耗（可能还有为压缩内容耗费的cpu时间）。</p>
<p>（除了HTTP请求，）并发问题也很重要。默认情况下，在使用持久连接（persistent connections）时，ie和firefox在同一域名内只会同时下载<a href="http://blogs.msdn.com/ie/archive/2005/04/11/407189.aspx">两个资源</a>（在<a href="http://www.ietf.org/rfc/rfc2616.txt">HTTP 1.1规格书</a>中第8.1.4节的建议）（htmlor注：可以通过修改注册表等方法改变这一默认配置）。这就意味着，在我们等待下载2个js文件的同时，将无法下载图片资源。也就是说，这段时间内用户在页面上看不到图片。</p>
<p>（虽然合并文件能解决以上两个问题，）可是，这个方法有两个缺点。第一，把所有资源一起打包，将强制用户一次下载完所有资源。如果（不这么做，而是）把大块内容变成多个文件，下载开销就分散到了多个页面，同时缓解了会话中的速度压力（或完全避免了某些开销，这取决于用户选择的路径）。如果为了随后页面下载得更快而让初始页面下载得很慢，我们将发现更多用户根本不会傻等着再去打开下一个页面。</p>
<p>第二（这个影响更大，一直以来却没怎么被考虑过），在一个文件改动很频繁的环境里，如果采用单文件系统，那么每次改动文件都需要客户端把所有css和js重新下载一遍。假如我们的应用有个100k的合成的js大文件，任何微小的改动都将强制客户端把这100k再消化一遍。</p>
<h3>分解之道</h3>
<p>（看来合并成大文件不太合适。）替代方案是个折中的办法：把css和js资源分散成多个子文件，按功能划分、保持文件个数尽可能少。这个方案也是有代价的，虽说开发时代码分散成逻辑块（logical chunks）能提高效率，可在下载时为提高性能还得合并文件。不过，只要给build系统（把开发代码变成产品代码的工具集，是为部署准备的）加点东西，就没什么问题了。</p>
<p>对于有着不同开发和产品环境的应用来说，用些简单的技术可以让代码更好管理。在开发环境下，为使条理清晰，代码可以分散为多个逻辑部分（logical components）。可以在<a href="http://smarty.php.net/">Smarty</a>（一种php模板语言）里建立一个简单的函数来管理javascript的下载：</p>
<blockquote>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">SMARTY<span style="color: #339933;">:</span>
<span style="color: #009900;">&#123;</span>insert_js files<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;foo.js,bar.js,baz.js&quot;</span><span style="color: #009900;">&#125;</span>
&nbsp;
PHP<span style="color: #339933;">:</span>
<span style="color: #000000; font-weight: bold;">function</span> smarty_insert_js<span style="color: #009900;">&#40;</span><span style="color: #000088;">$args</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>   <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">','</span><span style="color: #339933;">,</span> <span style="color: #000088;">$args</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'files'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>     <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;script type=<span style="color: #000099; font-weight: bold;">\&quot;</span>text/javascript<span style="color: #000099; font-weight: bold;">\&quot;</span> SOURCE=<span style="color: #000099; font-weight: bold;">\&quot;</span>/javascript/<span style="color: #006699; font-weight: bold;">$file</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&gt;&lt;/script&gt;<span style="color: #000099; font-weight: bold;">\\</span>n&quot;</span><span style="color: #339933;">;</span>   <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
OUTPUT<span style="color: #339933;">:</span>
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;text/javascript&quot;</span> SOURCE<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;/javascript/foo.js&quot;</span><span style="color: #339933;">&gt;&lt;/</span>script<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;text/javascript&quot;</span> SOURCE<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;/javascript/bar.js&quot;</span><span style="color: #339933;">&gt;&lt;/</span>script<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;text/javascript&quot;</span> SOURCE<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;/javascript/baz.js&quot;</span><span style="color: #339933;">&gt;&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></div></div>

<p>（htmlor注：wordpress中会把“src”替换成不知所谓的字符，因此这里只有写成“SOURCE”，使用代码时请注意替换，下同）</p>
<p>就这么简单。然后我们就命令build过程（build process）去把确定的文件合并起来。这个例子里，合并的是foo.js和bar.js，因为它们几乎总是一起下载。我们能让应用配置记住这一点，并修改模板函数去使用它。（代码如下：）</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">SMARTY<span style="color: #339933;">:</span>
<span style="color: #009900;">&#123;</span>insert_js files<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;foo.js,bar.js,baz.js&quot;</span><span style="color: #009900;">&#125;</span>
&nbsp;
PHP<span style="color: #339933;">:</span>
<span style="color: #666666; font-style: italic;"># 源文件映射图。在build过程合并文件之后用这个图找到js的源文件。
</span>
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'config'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'js_source_map'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>   <span style="color: #0000ff;">'foo.js'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'foobar.js'</span><span style="color: #339933;">,</span>   <span style="color: #0000ff;">'bar.js'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'foobar.js'</span><span style="color: #339933;">,</span>   <span style="color: #0000ff;">'baz.js'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'baz.js'</span><span style="color: #339933;">,</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> smarty_insert_js<span style="color: #009900;">&#40;</span><span style="color: #000088;">$args</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>   <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'config'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'is_dev_site'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>     <span style="color: #000088;">$files</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">','</span><span style="color: #339933;">,</span> <span style="color: #000088;">$args</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'files'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>   <span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>     <span style="color: #000088;">$files</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>     <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">','</span><span style="color: #339933;">,</span> <span style="color: #000088;">$args</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'files'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>       <span style="color: #000088;">$files</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'config'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'js_source_map'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">++;</span>     <span style="color: #009900;">&#125;</span>     <span style="color: #000088;">$files</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$files</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>   <span style="color: #009900;">&#125;</span>   <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$files</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>     <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;script type=<span style="color: #000099; font-weight: bold;">\&quot;</span>text/javascript<span style="color: #000099; font-weight: bold;">\&quot;</span> SOURCE=<span style="color: #000099; font-weight: bold;">\&quot;</span>/javascript/<span style="color: #006699; font-weight: bold;">$file</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&gt;&lt;/script&gt;<span style="color: #000099; font-weight: bold;">\\</span>n&quot;</span><span style="color: #339933;">;</span>   <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
OUTPUT<span style="color: #339933;">:</span>
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;text/javascript&quot;</span> SOURCE<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;/javascript/foobar.js&quot;</span><span style="color: #339933;">&gt;&lt;/</span>script<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;text/javascript&quot;</span> SOURCE<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;/javascript/baz.js&quot;</span><span style="color: #339933;">&gt;&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></div></div>

</blockquote>
<p>模板里的源代码没必要为了分别适应开发和产品阶段而改动，它帮助我们在开发时保持文件分散，发布成产品时把文件合并。想更进一步的话，可以把合并过程（merge process）写在php里，然后使用同一个（合并文件的）配置去执行。这样就只有一个配置文件，避免了同步问题。为了做的更加完美，我们还可以分析css和js文件在页面中同时出现的几率，以此决定合并哪些文件最合理（几乎总是同时出现的文件是合并的首选）。</p>
<p>对css来说，可以先建立一个主从关系的模型，它很有用。一个主样式表控制应用的所有样式表，多个子样式表控制不同的应用区域。采用这个方法，大多数页面只需下载两个css文件，而其中一个（指主样式表）在页面第一次请求时就会缓存。</p>
<p>对没有太多css和js资源的应用来说，这个方法在第一次请求时可能比单个大文件慢，但如果保持文件数量很少的话，你会发现其实它更快，因为每个页面的数据量更小。让人头疼的下载花销被分散到不同的应用区域，因此并发下载数保持在一个最小值，同时也使得页面的平均下载数据量很小。</p>
<h3>压缩</h3>
<p>谈到资源压缩，大多数人马上会想到<a href="http://sourceforge.net/projects/mod-gzip/">mod_gzip</a>（但要当心，mod_gzip实际上是个魔鬼，至少能让人做恶梦）。它的原理很简单：浏览器请求资源时，会发送一个header表明自己能接受的内容编码。就像这样：</p>
<blockquote>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">Accept<span style="color: #339933;">-</span>Encoding<span style="color: #339933;">:</span> <span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/gzip" title="显示gzip的所有日志" target="_blank">gzip</a></span><span style="color: #339933;">,</span>deflate</pre></div></div>

</blockquote>
<p>服务器遇到这样的header请求时，就用<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/gzip" title="显示gzip的所有日志" target="_blank">gzip</a></span>或deflate压缩内容发往客户端，然后客户端解压缩。这过程减少了数据传输量，同时消耗了客户端和服务器的cpu时间。也算差强人意。但是，mod_gzip的工作方式是这样的：先在磁盘上创建一个临时文件，然后发送（给客户端），最后删除这个文件。在高容量的系统中，由于磁盘io问题，很快就会达到极限。要避免这种情况，可以改用<a href="http://httpd.apache.org/docs/2.0/mod/mod_deflate.html">mod_deflate</a>（apache 2才支持）。它采用更合理的方式：在内存里做压缩。对于apache 1的用户来说，可以建立一块ram磁盘，让mod_gzip在它上面写临时文件。虽然没有纯内存方式快，但也不会比往磁盘上写文件慢。</p>
<p>话虽如此，其实还是有办法完全避免压缩开销的，那就是预压缩相关静态资源，下载时由mod_gzip提供合适的压缩版本。如果把压缩添加在build过程，它就很透明了。需要压缩的文件通常很少（用不着压缩图片，因为并不能减小更多体积），只有css和js文件（和其他未压缩的静态内容）。</p>
<p>配置选项会告诉mod_gzip去哪里找到预压缩过的文件。</p>
<blockquote>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">mod_gzip_can_negotiate	Yes
mod_gzip_static_suffix	<span style="color: #339933;">.</span>gz
AddEncoding	gzip	<span style="color: #339933;">.</span>gz</pre></div></div>

</blockquote>
<p>新一点的mod_gzip版本（从1.3.26.1a开始）添加一个额外的配置选项后，就能自动预压缩文件。不过在此之前，必须确认apache有正确的权限去创建和覆盖压缩文件。</p>
<blockquote>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">mod_gzip_update_static	Yes</pre></div></div>

</blockquote>
<p>可惜，事情没那么简单。某些Netscape 4的版本（尤其是4.06-4.08）认为自己能够解释压缩内容（它们发送一个header这么说来着），但其实它们不能正确的解压缩。大多数其他版本的Netscape 4在下载压缩内容时也有各种各样的问题。所以要在服务器端探测代理类型，（如果是Netscape 4，就要）让它们得到未压缩的版本。这还算简单的。ie（版本4-6）有些更有意思的问题：当下载压缩的javascript时，有时候ie会<a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;823386&amp;Product=ie600">不正确的解压缩文件</a>，或者解压缩到一半中断，然后把这半个文件显示在客户端。如果你的应用对javascript的依赖比较大（htmlor注：比如ajax应用），那么就得避免发送压缩文件给ie。在某些情况下，一些更老的5.x版本的ie倒是能正确的收到压缩的javascript，可它们会忽略这个文件的etag header，不缓存它。（thincat友情提示：尽管压缩存在一些浏览器不兼容的现象，由于这些不能很好的支持压缩的浏览器数量现在已经非常少了，我认为这种由于浏览器导致的压缩不正常的情况可以忽略不计。这些过时的浏览器还能不能在现在流行的windows或unix环境下面安装都存在不小的问题）</p>
<p>既然gzip压缩有这么多问题，我们不妨把注意力转到另一边：不改变文件格式的压缩。现在有很多这样的javascript压缩脚本可用，大多数都用一个正则表达式驱动的语句集来减小源代码的体积。它们做的不外乎几件事：去掉注释，压缩空格，缩短私有变量名和去掉可省略的语法。</p>
<p>不幸的是，大多数脚本效果并不理想，要么压缩率相当低，要么某种情形下会把代码搞得一团糟（或者两者兼而有之）。由于对解析树的理解不完整，压缩器很难区分一句注释和一句看似注释的引用字符串。因为闭合结构的混合使用，要用正则表达式发现哪些变量是私有的并不容易，因此一些缩短变量名的技术会打乱某些闭合代码。</p>
<p>还好有个压缩器能避免这些问题：<a href="http://dojotoolkit.org/docs/compressor_system.html">dojo压缩器</a>（现成的版本在<a href="http://alex.dojotoolkit.org/shrinksafe/">这里</a>）。它使用rhino（mozilla的javascript引擎，是用java实现的）建立一个解析树，然后将其提交给文件。它能很好的减小代码体积，仅用很小的成本：因为只在build时压缩一次。由于压缩是在build过程中实现的，所以一清二楚。（既然压缩没有问题了，）我们可以在源代码里随心所欲的添加空格和注释，而不必担心影响到产品代码。</p>
<p>与javascript相比，css文件的压缩相对简单一些。由于css语法里不会有太多引用字符串（通常是url路径跟字体名），我们可以用正则表达式大刀阔斧的干掉空格（htmlor注：这句翻的最爽，哈哈）。如果确实有引用字符串的话，我们总可以把一串空格合成一个（因为不需要在url路径和字体名里查找多个空格和tab）。这样的话，一个简单的perl脚本就够了：</p>
<blockquote>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/usr/bin/perl
</span>
my <span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
open F<span style="color: #339933;">,</span> <span style="color: #000088;">$ARGV</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> or <span style="color: #990000;">die</span> <span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span>Can<span style="color: #0000ff;">'t open source file: $!&amp;quot;;
$data .= $_ while &amp;lt;F&amp;gt;;
close F;
&nbsp;
$data =~ s!\/\*(.*?)\*\/!!g;  # 去掉注释
$data =~ s!\s+! !g;           # 压缩空格
$data =~ s!\} !}\\n!g;         # 在结束大括号后添加换行
$data =~ s!\\n$!!;             # 删除最后一个换行
$data =~ s! \{ ! {!g;         # 去除开始大括号后的空格
$data =~ s!; \}!}!g;          # 去除结束大括号前的空格
&nbsp;
print $data;</span></pre></div></div>

</blockquote>
<p>然后，就可以把单个的css文件传给脚本去压缩了。命令如下：</p>
<blockquote>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">perl compress<span style="color: #339933;">.</span>pl site<span style="color: #339933;">.</span>source<span style="color: #339933;">.</span>css <span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span> site<span style="color: #339933;">.</span>compress<span style="color: #339933;">.</span>css</pre></div></div>

</blockquote>
<p>做完这些简单的纯文本优化工作后，我们就能减少数据传输量多达50%了（这个量取决于你的代码格式，可能更多）。这带来了更快的用户体验。不过我们真正想做的是，尽可能避免用户请求的发生——除非确实有必要。这下HTTP缓存知识派上用场了。</p>
<h3>缓存是好东西</h3>
<p>当用户代理（如浏览器）向服务器请求一个资源时，第一次请求过后它就会缓存服务器的响应，以避免重复之后的相同请求。缓存时间的长短取决于两个因素：代理的配置和服务器的缓存控制header。所有浏览器都有不同的配置选项和处理方式，但大多数都会把一个资源至少缓存到会话结束（除非被明确告知）。</p>
<p>为了不让浏览器缓存改动频繁的页面，你很可能已经发送过header不缓存动态内容。在php中，以下两行命令可以做到：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span>Cache<span style="color: #339933;">-</span>Control<span style="color: #339933;">:</span> private<span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span>Cache<span style="color: #339933;">-</span>Control<span style="color: #339933;">:</span> no<span style="color: #339933;">-</span><span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/cache" title="显示cache的所有日志" target="_blank">cache</a></span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>听起来太简单了？确实如此——因为有些代理（浏览器）在某些环境下将忽略这些header。要确保浏览器不缓存文档，应该更强硬一些：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;"># 让它在过去就“失效”
</span><span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span>Expires<span style="color: #339933;">:</span> Mon<span style="color: #339933;">,</span> <span style="color: #cc66cc;">26</span> Jul <span style="color: #cc66cc;">1997</span> <span style="color: #208080;">05</span><span style="color: #339933;">:</span><span style="color: #208080;">00</span><span style="color: #339933;">:</span><span style="color: #208080;">00</span> GMT<span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># 永远是改动过的
</span><span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span>Last<span style="color: #339933;">-</span>Modified<span style="color: #339933;">:</span> <span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;.</span><span style="color: #990000;">gmdate</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span>D<span style="color: #339933;">,</span> d M Y H<span style="color: #339933;">:</span>i<span style="color: #339933;">:</span>s<span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.&amp;</span>quot<span style="color: #339933;">;</span> GMT<span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># HTTP/1.1
</span><span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span>Cache<span style="color: #339933;">-</span>Control<span style="color: #339933;">:</span> no<span style="color: #339933;">-</span>store<span style="color: #339933;">,</span> no<span style="color: #339933;">-</span><span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/cache" title="显示cache的所有日志" target="_blank">cache</a></span><span style="color: #339933;">,</span> must<span style="color: #339933;">-</span>revalidate<span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span>Cache<span style="color: #339933;">-</span>Control<span style="color: #339933;">:</span> post<span style="color: #339933;">-</span>check<span style="color: #339933;">=</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> pre<span style="color: #339933;">-</span>check<span style="color: #339933;">=</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># HTTP/1.0
</span><span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span>Pragma<span style="color: #339933;">:</span> no<span style="color: #339933;">-</span>cache<span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>这样，对于我们不想缓存的内容来说已经行了。但对于那些不会每次请求时都有改动的内容，应该鼓励浏览器更霸道的缓存它。“If-Modified-Since”请求header能够做到这点。如果客户端在请求中发送一个“If-Modified-Since”header，apache（或其他服务器）会以状态代码304（没改过）响应，告诉浏览器缓存已经是最新的。使用这个机制，能够避免重复发送文件给浏览器，不过仍然导致了一个HTTP请求的消耗。嗯，再想想。</p>
<p>与If-Modified-Since机制类似的是实体标记（entity tags）。在apache环境下，每个对静态文件的响应都会发出一个“ETag”header，它包含了一个由文件修改时间、文件大小和inode号生成的校验和（checksum）。在下载文件之前，浏览器会发送一个HEAD请求去检查文件的etag。可ETag跟If-Modified-Since有同样的问题：客户端仍旧需要执行HTTP请求来验证本地缓存是否有效。</p>
<p>此外，如果你使用多台服务器提供内容，得小心使用if-modified-since和etags。在两台负载平衡的服务器环境下，对一个代理（浏览器）来说，一个资源可以这次从A服务器得到，下次从B服务器得到（htmlor注：lvs负载平衡系统就是个典型的例子）。这很好，也是采用平衡负载的原因。可是，如果两台服务器给同一个文件生成了不同的etag或者文件修改日期，浏览器就无所适从了（每次都会重新下载）。默认情况下，etag是由文件的inode号生成的，而多台服务器之间文件的inode号是不同的。可以使用apache的配置选项关掉它：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">FileETag MTime Size</pre></div></div>

<p>使用这个选项，apache将只用文件修改日期和文件大小来决定etag。很不幸，这导致了另一个问题（一样能影响if-modified-since）。既然etag依赖于修改时间，就得让时间同步。可往多台服务器上传文件时，上传时间差个一到两秒是常有的事。这样一来，两台服务器生成的etag还是不一样。当然，我们还可以改变配置，让etag的生成只取决于文件大小，但这就意味着如果文件内容变了而大小没变，etag也不会变。这可不行。</p>
<h3>缓存真是个好东西</h3>
<p>看来我们正从错误的方向入手解决问题。（现在的问题是，）这些可能的缓存策略导致了一件事情反复发生，那就是：客户端向服务器查询本地缓存是否最新。假如服务器在改动文件的时候通知客户端，客户端不就知道它的缓存是最新的了（直到接到下一次通知）？可惜天公不做美——（事实）是客户端向服务器发出请求。</p>
<p>其实，也不尽然。在获取js或css文件之前，客户端会用&lt;script&gt;或&lt;link&gt;标记向服务器发送一个请求，说明哪个页面要加载这些文件。这时候就可以用服务器的响应来通知客户端这些文件有了改动。有点含糊，说得再详细点就是：如果改变css和js文件内容的同时，也改变它们的文件名，就可以告诉客户端对url全都永久缓存——因为每个url都是唯一的。</p>
<p>假如能确定一个资源永不更改，我们就可以发出一些霸气十足的缓存header（htmlor注：这句也很有气势吧）。在php里，两行就好：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span>Expires<span style="color: #339933;">:</span> <span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;.</span><span style="color: #990000;">gmdate</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span>D<span style="color: #339933;">,</span> d M Y H<span style="color: #339933;">:</span>i<span style="color: #339933;">:</span>s<span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;,</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">315360000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.&amp;</span>quot<span style="color: #339933;">;</span> GMT<span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span>Cache<span style="color: #339933;">-</span>Control<span style="color: #339933;">:</span> max<span style="color: #339933;">-</span>age<span style="color: #339933;">=</span><span style="color: #cc66cc;">315360000</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>我们告诉浏览器这个内容在10年后（10年大概会有315,360,000秒，或多或少）过期，浏览器将会保留它10年。当然，很有可能不用php输出css和js文件（因此就不能发出header），这种情况将在稍后说明。</p>
<h3>人力有时而穷</h3>
<p>当文件内容更改时，手动去改文件名是很危险的。假如你改了文件名，模板却没有指向它？假如你改了一些模板另一些却没改？假如你改了模板却没改文件名？还有最糟的，假如你改动了文件却忘了改名或者忘了改变对它的引用？最好的结果，是用户看到老的而看不到新的内容。最坏的结果，是找不到文件，网站没法运转了。听起来这（指改动文件内容时修改url）似乎是个馊主意。</p>
<p>幸运的是，计算机做这类事情——当某种变化发生，需要相当准确地完成的、重复重复再重复的（htmlor注：番茄鸡蛋伺候～）、枯燥乏味的工作——总是十分在行。</p>
<p>这个过程（改变文件的url）没那么痛苦，因为我们根本不需要改文件名。资源的url和磁盘上文件的位置也没必要保持一致。使用apache的<a href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html">mod_rewrite</a>模块，可以建立简单的规则，让确定的url重定向到确定的文件。</p>
<blockquote>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">RewriteEngine on
RewriteRule ^<span style="color: #339933;">/</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">.*</span>\<span style="color: #339933;">.</span><span style="color: #009900;">&#41;</span>v<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">-</span><span style="color:#800080;">9.</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">+</span>\<span style="color: #339933;">.</span><span style="color: #009900;">&#40;</span>css<span style="color: #339933;">|</span>js<span style="color: #339933;">|</span>gif<span style="color: #339933;">|</span>png<span style="color: #339933;">|</span>jpg<span style="color: #009900;">&#41;</span>$	<span style="color: #339933;">/</span>$<span style="color: #cc66cc;">1</span>$<span style="color: #cc66cc;">2</span>	<span style="color: #009900;">&#91;</span>L<span style="color: #009900;">&#93;</span></pre></div></div>

</blockquote>
<p>这条规则匹配任何带有指定扩展名同时含有“版本”信息（version nugget）的url，它会把这些url重定向到一个不含版本信息的路径。如下所示：</p>
<blockquote><p>
 URL			   Path<br />
/images/foo.v2.gif	-&gt; /images/foo.gif<br />
/css/main.v1.27.css	-&gt; /css/main.css<br />
/javascript/md5.v6.js	-&gt; /javascript/md5.js
</p></blockquote>
<p>使用这条规则，就可以做到不改变文件路径而更改url（因为版本号变了）。由于url变了，浏览器就认为它是另一个资源（会重新下载）。想更进一步的话，可以把我们之前说的脚本编组函数结合起来，根据需要生成一个带有版本号的&lt;script&gt;标记列表。</p>
<p>说到这里，你可能会问我，为什么不在url结尾加一个查询字符串（query string）呢（如/css/main.css?v=4）？根据HTTP缓存规格书所说，用户代理对含有查询字符串的url永不缓存。虽然ie跟firefox忽略了这点，opera和safari却没有——为了确保所有浏览器都缓存你的资源，还是不要在url里用查询字符串的好。</p>
<p>现在不移动文件就能更改url了，如果能让url自动更新就更好了。在小型的产品环境下（如果有大型的产品环境，就是开发环境了），使用模板功能可以很轻易的实现这点。这里用的是smarty，用其他模板引擎也行。</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">SMARTY<span style="color: #339933;">:</span>
<span style="color: #339933;">&lt;</span>link xhref<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;{version xsrc='/css/group.css'}&quot;</span> rel<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;stylesheet&quot;</span> type<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;text/css&quot;</span> <span style="color: #339933;">/&gt;</span>
&nbsp;
PHP<span style="color: #339933;">:</span>
<span style="color: #000000; font-weight: bold;">function</span> smarty_version<span style="color: #009900;">&#40;</span><span style="color: #000088;">$args</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>   <span style="color: #000088;">$stat</span> <span style="color: #339933;">=</span> <span style="color: #990000;">stat</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'config'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'site_root'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #000088;">$args</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'src'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>   <span style="color: #000088;">$version</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$stat</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'mtime'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>   <span style="color: #b1b100;">echo</span> <span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'!\.([a-z]+?)$!'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;.v<span style="color: #006699; font-weight: bold;">$version</span>.<span style="color: #000099; font-weight: bold;">\$</span>1&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$args</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'src'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
OUTPUT<span style="color: #339933;">:</span>
<span style="color: #339933;">&lt;</span>link xhref<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;/css/group.v1234567890.css&quot;</span> mce_href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;/css/group.v1234567890.css&quot;</span> rel<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;stylesheet&quot;</span> type<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;text/css&quot;</span> <span style="color: #339933;">/&gt;</span></pre></div></div>

<p>对每个链接到的资源文件，我们得到它在磁盘上的路径，检查它的mtime（文件最后修改的日期和时间），然后把这个时间当作版本号插入到url中。对于低流量的站点（它们的stat操作开销不大）或者开发环境来说，这个方案不错，但对于高容量的环境就不适用了——因为每次stat操作都要磁盘读取（导致服务器负载升高）。</p>
<p>解决方案相当简单。在大型系统中每个资源都已经有了一个版本号，就是版本控制的修订号（你们应该使用了版本控制，对吧？）。当我们建立站点准备部署的时候，可以轻易的查到每个文件的修订号，写在一个静态配置文件里。</p>
<blockquote>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'config'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'resource_versions'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>   <span style="color: #0000ff;">'/images/foo.gif'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'2.1'</span><span style="color: #339933;">,</span>   <span style="color: #0000ff;">'/css/main.css'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'1.27'</span><span style="color: #339933;">,</span>   <span style="color: #0000ff;">'/javascript/md5.js'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'6.1.4'</span><span style="color: #339933;">,</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

</blockquote>
<p>当我们发布产品时，可以修改模板函数来使用版本号。</p>
<blockquote>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">function</span> smarty_version<span style="color: #009900;">&#40;</span><span style="color: #000088;">$args</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>   <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'config'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'is_dev_site'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>     <span style="color: #000088;">$stat</span> <span style="color: #339933;">=</span> <span style="color: #990000;">stat</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'config'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'site_root'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #000088;">$args</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'src'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>     <span style="color: #000088;">$version</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$stat</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'mtime'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>   <span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>     <span style="color: #000088;">$version</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'config'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'resource_versions'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$args</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'src'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>   <span style="color: #009900;">&#125;</span>   <span style="color: #b1b100;">echo</span> <span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'!\.([a-z]+?)$!'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;.v<span style="color: #006699; font-weight: bold;">$version</span>.<span style="color: #000099; font-weight: bold;">\$</span>1&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$args</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'src'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

</blockquote>
<p>就这样，不需要改文件名，也不需要记住改了哪些文件——当文件有新版本发布时它的url就会自动更新——有意思吧？我们就快搞定了。</p>
<h3>只欠东风</h3>
<p>之前谈到为静态文件发送超长周期（very-long-period）的缓存header时曾说过，如果不用php输出，就不能轻易的发送缓存header。很显然，有两个办法可以解决：用php输出，或者让apache来做。</p>
<p>php出马，手到擒来。我们要做的仅仅是改变rewrite规则，把静态文件指向php脚本，用php在输出文件内容之前发送header。</p>
<blockquote>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">Apache<span style="color: #339933;">:</span>
RewriteRule ^<span style="color: #339933;">/</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">.*</span>\<span style="color: #339933;">.</span><span style="color: #009900;">&#41;</span>v<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">-</span><span style="color:#800080;">9.</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">+</span>\<span style="color: #339933;">.</span><span style="color: #009900;">&#40;</span>css<span style="color: #339933;">|</span>js<span style="color: #339933;">|</span>gif<span style="color: #339933;">|</span>png<span style="color: #339933;">|</span>jpg<span style="color: #009900;">&#41;</span>$  <span style="color: #339933;">/</span>redir<span style="color: #339933;">.</span>php?path<span style="color: #339933;">=</span>$<span style="color: #cc66cc;">1</span>$<span style="color: #cc66cc;">2</span>  <span style="color: #009900;">&#91;</span>L<span style="color: #009900;">&#93;</span>
&nbsp;
PHP<span style="color: #339933;">:</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Expires: &quot;</span><span style="color: #339933;">.</span><span style="color: #990000;">gmdate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;D, d M Y H:i:s&quot;</span><span style="color: #339933;">,</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">315360000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot; GMT&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Cache-Control: max-age=315360000&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># 忽略带有“..”的路径
</span><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'!\.\.!'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span>path<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> go_404<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># 保证路径开头是确定的目录
</span><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'!^(javascript|css|images)!'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span>path<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> go_404<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># 文件不存在？
</span><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">file_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span>path<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> go_404<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># 发出一个文件类型header
</span><span style="color: #000088;">$ext</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_pop</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'.'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span>path<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">switch</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$ext</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>   <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'css'</span><span style="color: #339933;">:</span>     <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Content-type: text/css&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>     <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>   <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'js'</span> <span style="color: #339933;">:</span>     <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Content-type: text/javascript&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>     <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>   <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'gif'</span><span style="color: #339933;">:</span>     <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Content-type: image/gif&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>     <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>   <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'jpg'</span><span style="color: #339933;">:</span>     <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Content-type: image/jpeg&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>     <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>   <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'png'</span><span style="color: #339933;">:</span>     <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Content-type: image/png&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>     <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>   <span style="color: #b1b100;">default</span><span style="color: #339933;">:</span>     <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Content-type: text/plain&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># 输出文件内容
</span><span style="color: #b1b100;">echo</span> <span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #990000;">file</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span>path<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> go_404<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>   <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;HTTP/1.0 404 File not found&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>   <span style="color: #990000;">exit</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

</blockquote>
<p>这个方案有效，但并不出色。（因为）跟apache相比，php需要更多内存和执行时间。另外，我们还得小心防止可能由path参数传递伪造值引起的exploits。为避免这些问题，应该用apache直接发送header。rewrite规则语句允许当规则匹配时设置环境变量（environment variable），当给定的环境变量设置后，Header命令就可以添加header。结合以下两条语句，我们就把rewrite规则和header设置绑定在了一起：</p>
<blockquote>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">RewriteEngine on
RewriteRule ^<span style="color: #339933;">/</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">.*</span>\<span style="color: #339933;">.</span><span style="color: #009900;">&#41;</span>v<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">-</span><span style="color:#800080;">9.</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">+</span>\<span style="color: #339933;">.</span><span style="color: #009900;">&#40;</span>css<span style="color: #339933;">|</span>js<span style="color: #339933;">|</span>gif<span style="color: #339933;">|</span>png<span style="color: #339933;">|</span>jpg<span style="color: #009900;">&#41;</span>$ <span style="color: #339933;">/</span>$<span style="color: #cc66cc;">1</span>$<span style="color: #cc66cc;">2</span> <span style="color: #009900;">&#91;</span>L<span style="color: #339933;">,</span>E<span style="color: #339933;">=</span>VERSIONED_FILE<span style="color: #339933;">:</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span>
&nbsp;
<span style="color: #990000;">Header</span> add <span style="color: #0000ff;">&quot;Expires&quot;</span> <span style="color: #0000ff;">&quot;Mon, 28 Jul 2014 23:30:00 GMT&quot;</span> env<span style="color: #339933;">=</span>VERSIONED_FILE
<span style="color: #990000;">Header</span> add <span style="color: #0000ff;">&quot;Cache-Control&quot;</span> <span style="color: #0000ff;">&quot;max-age=315360000&quot;</span> env<span style="color: #339933;">=</span>VERSIONED_FILE</pre></div></div>

</blockquote>
<p>考虑到apache的执行顺序，应该把rewrite规则加在主配置文件（httpd.conf）而不是目录配置文件（.htaccess）中。否则在环境变量设置之前，header行会先执行（就那没意义了）。至于header行，则可以放在两文件任何一个当中，没什么区别。</p>
<h3>眼观六路</h3>
<p>（htmlor注：多谢<a href="http://tchaikov.blogsome.com/">tchaikov</a>告知“skinning rabbits”的含义，但我不想翻的太正式，眼下的这个应该不算太离谱吧。）</p>
<p>通过结合使用以上技术，我们可以建立一个灵活的开发环境和一个快速又高性能的产品环境。当然，这离终极目标“速度”还有一段距离。有许多更深层的技术（比如分离伺服静态内容，用多域名提升并发量等）值得我们关注，包括与我们谈到的方法（建立apache过滤器，修改资源url，加上版本信息）殊途同归的其他路子。你可以留下评论，告诉我们那些你正在使用的卓有成效的技术和方法。</p>
<p>（完）</p>
<p>转载自：<a title="http://blog.htmlor.com/2006/08/03/serving_javascript_fast_chinese/" href="http://blog.htmlor.com/2006/08/03/serving_javascript_fast_chinese/">http://blog.htmlor.com/2006/08/03/serving_javascript_fast_chinese/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.xixis.net/archives/flickr-doing-a-good-thing-for-javascript.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wordpress 提速之 Gzip 压缩</title>
		<link>http://www.xixis.net/archives/wordpress-speed-of-gzip-compression.html</link>
		<comments>http://www.xixis.net/archives/wordpress-speed-of-gzip-compression.html#comments</comments>
		<pubDate>Sun, 07 Feb 2010 14:29:23 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[gzip]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.xixis.net/?p=304</guid>
		<description><![CDATA[今天来聊下 wordpress 提速，其实关于这方面的话题网上其实蛮多的，速度对一个网站来说无疑是非常重要的，对于速度的追求也是无止境的，在这方面的表率无疑就是 shawn 了，看他博客的很多技巧都是针对速度来的……不过话说回来，速度也不是绝对的，看很多优秀的博客速度并不占优，有时候追求速度难免还会牺牲一些其它的东西！！此文仅供参考。
废话少说，关于 wordpress 的提速还是可以从很多方面入手的，因为 WP 的灵活而导致其效率和速度的下降，比如因为使用插件而在头部载入的 N 多的 JS 和 CSS 就是最为典型的，就不展开说了，今天我们只说 Gzip！
什么是 Gzip 压缩，为什么要用 Gzip 压缩
说白了就是一种压缩的技术，它将浏览器请求的文件在服务器端进行压缩，然后将文件以压缩的形式传递给浏览器，然后在浏览器端进行解压缩，还原后进行解析。而目前 99% 的浏览器都支持 Gzip ，包括 IE 4+, Netscape 4+, Opera 5+ 和所有版本的 Safari 和 Firefox ，所以大家可以放心使用。
在这里我们的压缩对象是所有的 html、JS、和 CSS 。而他的压缩效率惊人，能减小 60% 到70%。像我的博客一个 10K 的 JS 文件，用 Gzip 压缩后浏览器接收的只有 3K 大小，16K 的 CSS 文件也被压缩到了 5K，很强大吧！
怎么知道我的页面是否 Gzip 压缩过了
Gzip 的方法有很多种，而有很多的服务器是默认开启 Gzip 压缩的，不过据我所知，这种服务器少之又少。怎么确定自己的网页是否被 Gzip 呢！！这种测试的网站网上也很多，不过一般只能测试 html，这里推荐给大家一个测试的网站：Websiteoptimization，输入网址后，输入验证码，就会给出你的 Web Page Speed Report.
貌似很多的“童鞋”看错了，现在补图上来！！其中在下面的 Page Objects 中，会给出所有所加载的文件的信息。在最后一栏的信息中，如果显示：Congratulations! This file was compressed. 说明是被压缩过的，如果是：Up to **** bytes could have been saved through compression，显然是还没被压缩的。
启用 Gzip 的几种方法
是的，有几种方法，是针对不同的情况的。
1、最好的情况是你的主机采用的是 Apache 2，并安装启用了mod_deflate 模块。这样就很简单了，只需要在 .htaccess 文件中加入以下代码可以压缩 HTML, PHP, ...]]></description>
			<content:encoded><![CDATA[<p>今天来聊下 wordpress 提速，其实关于这方面的话题网上其实蛮多的，速度对一个网站来说无疑是非常重要的，对于速度的追求也是无止境的，在这方面的表率无疑就是 <a href="http://ishawn.net/">shawn</a> 了，看他博客的很多技巧都是针对速度来的……不过话说回来，速度也不是绝对的，看很多优秀的博客速度并不占优，有时候追求速度难免还会牺牲一些其它的东西！！此文仅供参考。<span id="more-304"></span></p>
<p>废话少说，关于 wordpress 的提速还是可以从很多方面入手的，因为 WP 的灵活而导致其效率和速度的下降，比如因为使用插件而在头部载入的 N 多的 JS 和 CSS 就是最为典型的，就不展开说了，今天我们只说 Gzip！</p>
<h3>什么是 Gzip 压缩，为什么要用 Gzip 压缩</h3>
<p>说白了就是一种压缩的技术，它将浏览器请求的文件在服务器端进行压缩，然后将文件以压缩的形式传递给浏览器，然后在浏览器端进行解压缩，还原后进行解析。而目前 99% 的浏览器都支持 Gzip ，包括 IE 4+, Netscape 4+, Opera 5+ 和所有版本的 Safari 和 Firefox ，所以大家可以放心使用。</p>
<p><strong>在这里我们的压缩对象是所有的 html、JS、和 CSS 。而他的压缩效率惊人，能减小 60% 到70%。像我的博客一个 10K 的 JS 文件，用 Gzip 压缩后浏览器接收的只有 3K 大小，16K 的 CSS 文件也被压缩到了 5K，很强大吧！</strong></p>
<h3>怎么知道我的页面是否 Gzip 压缩过了</h3>
<p>Gzip 的方法有很多种，而有很多的服务器是默认开启 Gzip 压缩的，不过据我所知，这种服务器少之又少。怎么确定自己的网页是否被 Gzip 呢！！这种测试的网站网上也很多，不过一般只能测试 html，这里推荐给大家一个测试的网站：<a href="http://www.websiteoptimization.com/services/analyze/">Websiteoptimization</a>，输入网址后，输入验证码，就会给出你的 Web Page Speed Report.</p>
<p>貌似很多的“童鞋”看错了，现在补图上来！！其中在下面的 Page Objects 中，会给出所有所加载的文件的信息。在最后一栏的信息中，<strong>如果显示：Congratulations! This file was compressed. 说明是被压缩过的，如果是：Up to **** bytes could have been saved through compression，显然是还没被压缩的。</strong></p>
<h3>启用 Gzip 的几种方法</h3>
<p>是的，有几种方法，是针对不同的情况的。</p>
<p>1、最好的情况是你的主机采用的是 Apache 2，并安装启用了mod_deflate 模块。这样就很简单了，只需要在 .<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/htaccess" title="显示htaccess的所有日志" target="_blank">htaccess</a></span> 文件中加入以下代码可以压缩 HTML, PHP, JS, CSS, XML 后缀的文件。</p>
<blockquote><p>&lt;ifmodule mod_deflate.c&gt;</p>
<p>AddOutputFilterByType DEFLATE text/html text/<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/css" title="显示css的所有日志" target="_blank">css</a></span> text/plain text/xml application/x-httpd-php application/x-<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/javascript" title="显示javascript的所有日志" target="_blank">javascript</a></span></p>
<p>&lt;/ifmodule&gt;</p></blockquote>
<p>不过一般的主机都没有这个模块，如果你是独立主机可以自行配置。至于如何检测自己的主机是否有安装这个模块，我还真没找到办法，望高手指点。如果大家有兴趣，可能将上面的代码加好，看是否 Gzip 来试一下！以上方法来自：<a href="http://fairyfish.net/2008/04/07/gzip/">我爱水煮鱼</a></p>
<p>2、用 PHP 来压缩</p>
<p>此方法也需要 PHP 模块 zlib 的支持，不过这是一个基本的模块，一般都开启了！！所以我们主要讲下这部分。</p>
<h3>用 PHP 压缩动态页面</h3>
<p>我们先来看所谓的 html 的压缩，其实也就是由 PHP 动态生成的 html 。这样的方法有很多，我用的是 <a href="http://ishawn.net/tips/enable-gzip-function-of-hostgator.html">shawn 的方法</a> ，还有 <a href="http://wmrpd.com/blog/?p=300">几种方法</a> 供参考。</p>
<h3>用 PHP 压缩 JS 和CSS</h3>
<p><strong>关于 JS 和 CSS 的压缩也有几种方法，目前比较多的是像 K2 学习，将 JS 和 CSS 改为 .php 的方法</strong>。这个前辈已经介绍过了，请移步：<a href="http://sexywp.com/simple-guide-to-css-js-compress.htm">简述对WP博客样式表和JS脚本的压缩</a></p>
<p>这种方法的缺点是要修改每个 JS 和 CSS 文件，有点不太方便。对于将所有插件中的 JS 和CSS 都合并的博客来说还算容易，但没有合并的来说无疑是一项巨大的工程，而且插件更新也是件麻烦的事。另外看着好好的 CSS 文件变成了 PHP ，看着挺怪的，呵呵！！好处是有好的适应性，因为这 K2 用的方法！</p>
<p><strong>第二种方法是老N提供的方法</strong>：<a href="http://neolee.cn/wordpress/compress-js-css/">加速blog，压缩js,css，减省带宽</a> ，这种方法应该说比较简单，而且默认对所有的 JS 和 CSS 生效。原理就是把 JS 和 CSS 利用 .<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/htaccess" title="显示htaccess的所有日志" target="_blank">htaccess</a></span> 交给一个 PHP 文件来处理进行压缩。</p>
<p>老N那的代码貌似复制出来有些问题，我再贴一下，呵呵：</p>
<blockquote><p>1、创建 <span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/gzip" title="显示gzip的所有日志" target="_blank">gzip</a></span>.php 文件并上传到博客根目录，代码如下：</p>
<p>下载: <a href="http://www.xiaorsz.com/wp-content/plugins/coolcode/coolcode.php?p=632&amp;download=gzip.php">gzip.php</a></p></blockquote>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;!--</span>p  <span style="color: #000088;">$allowed</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>  <span style="color: #0000ff;">'<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/css" title="显示css的所有日志" target="_blank">css</a></span>'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'text/<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/css" title="显示css的所有日志" target="_blank">css</a></span>'</span><span style="color: #339933;">,</span>  <span style="color: #0000ff;">'js'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'text/<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/javascript" title="显示javascript的所有日志" target="_blank">javascript</a></span>'</span><span style="color: #339933;">,</span>  <span style="color: #0000ff;">'html'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'text/html'</span><span style="color: #339933;">,</span>  <span style="color: #0000ff;">'htm'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'text/html'</span><span style="color: #339933;">,</span>  <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #000088;">$file</span> <span style="color: #339933;">=</span> <span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'url'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'url'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">:</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>  <span style="color: #000088;">$extension</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'.'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #000088;">$extension</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_pop</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$extension</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$allowed</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$extension</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>  <span style="color: #009900;">&#123;</span>  <span style="color: #000088;">$pos</span> <span style="color: #339933;">=</span> <span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'..'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$pos</span> <span style="color: #339933;">===</span> <span style="color: #009900; font-weight: bold;">false</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> <span style="color: #990000;">is_file</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>  <span style="color: #009900;">&#123;</span>  <span style="color: #339933;">@</span><span style="color: #990000;">ob_start</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ob_gzhandler'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span>Content<span style="color: #339933;">-</span>type<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><span style="color: #000088;">$allowed</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$extension</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span> charset<span style="color: #339933;">:</span> UTF<span style="color: #339933;">-</span><span style="color: #cc66cc;">8</span><span style="color: #339933;">&amp;</span>quot<span style="color: #339933;">;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #990000;">readfile</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>  <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'HTTP/1.1 404 Not Found'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #009900;">&#125;</span>  <span style="color: #009900;">&#125;</span> <span style="color: #339933;">--&gt;</span></pre></div></div>

<blockquote><p>2、更改.<span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/htaccess" title="显示htaccess的所有日志" target="_blank">htaccess</a></span>文件，在.htaccess中添加：</p>
<p>RewriteCond %{REQUEST_FILENAME} -f</p>
<p>RewriteCond %{REQUEST_FILENAME} ^.*\.(css|js|html|htm)$</p>
<p>RewriteRule ^(.*)$ <span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/gzip" title="显示gzip的所有日志" target="_blank">gzip</a></span>.php?url=$1 [QSA,L]</p>
<p>就 OK 了~，的确很简单</p></blockquote>
<p>但上面两种方法还有一个问题，就是会吃服务器的资源，占用一定的 CPU 和内存，因为每次访问页面都要执行一下。但具体吃到什么程度，我就不清楚了，据说在服务器资源紧张的情况下压缩的效率会比较低，不过我想一般大型的主机提供商的主机还是不会有什么问题的。</p>
<p>第三种我们来看 <a href="http://www.thirdinfo.com/how-to-better-wp.htm">辐射鱼提供的方法</a></p>
<blockquote><p>1. 下载 <a href="http://wopus.googlecode.com/files/gzip.php">Gzip.php</a> 文件并上传到你的Wordpress安装目录</p>
<p>2. 在你的 Wordpress 根目录建立 wp-cache 文件夹并确保其可写入</p>
<p>3. 在.htaccess里面加上</p>
<p>RewriteRule (.*.css$|.*.js$) gzip.php?$1 [L]</p>
<p>即可</p></blockquote>
<p>也非常的简单，而且此种方法的优点是：自动读取并 gzip 压缩 css 和 js，访问时直接调用生成的 .gz 文件，节约带宽也不占用服务器资源，<strong>但不适用空间下安装了多个 Wordpress 的博友</strong>，可能导致二级目录下的某些 <span class='wp_keywordlink_affiliate'><a href="http://www.xixis.net/archives/tag/wordpress" title="显示WordPress的所有日志" target="_blank">WordPress</a></span> 无法加载 CSS 样式。这些都是辐射鱼的原话，呵呵！另外就是当 CSS 和 JS 有更新时要手动清除缓存才行。符合条件的同志推荐用这种方法！！</p>
<p>转载自：<a title="http://www.xiaorsz.com/wordpress-gzip-compression-improve-the-speed/" href="http://www.xiaorsz.com/wordpress-gzip-compression-improve-the-speed/">http://www.xiaorsz.com/wordpress-gzip-compression-improve-the-speed/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.xixis.net/archives/wordpress-speed-of-gzip-compression.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

