<?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>西红柿爱番茄 &#187; minify</title>
	<atom:link href="http://www.ilovejs.net/archives/tag/minify/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ilovejs.net</link>
	<description>到了创造为主的阶段，不忘继续学习</description>
	<lastBuildDate>Thu, 15 Dec 2011 06:18:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>WEB性能优化系列一</title>
		<link>http://www.ilovejs.net/archives/810</link>
		<comments>http://www.ilovejs.net/archives/810#comments</comments>
		<pubDate>Sat, 05 Jun 2010 20:57:13 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[性能优化]]></category>
		<category><![CDATA[Compression]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[Gzip]]></category>
		<category><![CDATA[HTTP请求]]></category>
		<category><![CDATA[minify]]></category>
		<category><![CDATA[Web Performance]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=810</guid>
		<description><![CDATA[最近一直在看Google Page Speed中介绍的Web Performance Best Practices以及Yahoo！的 Best Practices for Speeding Up Your Web Site，并且浏览了很多其他叙述有关WEB性能优化的文章后有一点感悟：当新技术新思想引进国内的时候，国外已经发展相对比较或者绝对成熟、研究有一定深度而且最主要的是理念已经被广为传播开来并为大家所熟知。而联想到国内当前的技术环境和理念创新方面，还是有待提高的。下面是我在浏览了众多有关WEB性能优化方面的论述后的一个总结，因为内容比较多，而且翻译总结时间比较长点，所以初步打算是逐步逐步共享一下自己的心得，后续的将会陆陆续续推出，说的有不正确的地方，欢迎指正~ 因为总结是写在word文档里的，所以就顺便保存了一份pdf格式的文件，需要的童鞋可以自行下载：《WEB性能优化系列一》。 Serve resources from a consistent &#8230; <a href="http://www.ilovejs.net/archives/810" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>
最近一直在看Google Page Speed中介绍的<a  href="http://code.google.com/speed/page-speed/docs/rules_intro.html">Web Performance Best Practices</a>以及Yahoo！的<br />
<a  href="http://developer.yahoo.com/performance/rules.html">Best Practices for Speeding Up Your Web Site</a>，并且浏览了很多其他叙述有关WEB性能优化的文章后有一点感悟：当新技术新思想引进国内的时候，国外已经发展相对比较或者绝对成熟、研究有一定深度而且最主要的是理念已经被广为传播开来并为大家所熟知。而联想到国内当前的技术环境和理念创新方面，还是有待提高的。下面是我在浏览了众多有关WEB性能优化方面的论述后的一个总结，因为内容比较多，而且翻译总结时间比较长点，所以初步打算是逐步逐步共享一下自己的心得，后续的将会陆陆续续推出，说的有不正确的地方，欢迎指正~
</p>
<p>
因为总结是写在word文档里的，所以就顺便保存了一份pdf格式的文件，需要的童鞋可以自行下载：《<a  href="/download/performance/Web Performance series 1.pdf">WEB性能优化系列一</a>》。
</p>
<ol>
<li><a href="/archives/810#consistentURL">Serve resources from a consistent URL：使用一个确定的URL来引用资源</a></li>
<li><a href="/archives/810#scaledImages">Serve scaled images：衡量图片的大小缩放</a></li>
<li><a href="/archives/810#optimizeImages">Optimize images：优化图片</a></li>
<li><a href="/archives/810#loadout">拆分初始化负载</a></li>
<li><a href="/archives/810#minifyHTML">Minify HTML</a></li>
<li><a href="/archives/810#minifyCSS">Minify CSS</a></li>
<li><a href="/archives/810#minifyJavascript">Minify JavaScript</a></li>
<li><a href="/archives/810#RemoveUnusedCSS">Remove unused CSS：删除无用的CSS</a></li>
<li><a href="/archives/810#EnableCompression">Enable compression：允许压缩</a></li>
<li><a href="/archives/810#MinimizeRequestSize">Minimize request size：最小化request请求头信息的大小</a></li>
<li><a href="/archives/810#CookielessDomain">Serve static content from a cookieless domain：减小静态资源的cookie的大小</a></li>
<li><a href="#OptimizeOrder">Optimize the order of styles and scripts：优化js和css文件的加载顺序</a></li>
</ol>
<p><span id="more-810"></span></p>
<p id="consistentURL">
<strong>1. Serve resources from a consistent URL：使用一个确定的URL来引用资源</strong><br />
这个主要是避免不必要的资源重复下载和DNS查询。这种情况主要是当同一个资源（尤其是图片）在几个页面或者几个站点之间重复使用的时候，特别是公司内的各个站点，比如：a.example.com和b.example.com中同时引用了example.png这个图片，所以现在就要把这个图片放在a或者b域名下，而不能既放在a又放在b，这样会造成不必要的重复下载同一个图片，而且也增加了DNS的查询时间，造成性能问题。<br />
同时还有一点需要指出的是：相对URL和绝对URL的问题。如果是在同一个站点内，/images/example.gif和www.example.com/images/exampl.gif是一样的，站内页面之间可以使用相对地址来引用图片，从而减少页面的大小。但是在站点之间的时候，就会有一个问题：图片所在的站点使用相对URL/images/example.gif来引用资源，而另外站点通过www.example.com/images/example.gif来引用的时候，IE和FF下都能够很好的处理，无论在哪一个站点访问了这个图片，在另外一个站点就可以在浏览器的缓存里读取图片，可是在Chrome下却不会，即使是一个相同的URL页面，不同的Tab下浏览都会重新下载资源。测试页面：<a  href="http://www.ilovejs.net/lab/domain.html">http://www.ilovejs.net/lab/domain.html</a>，<a  href="http://www.webairness.com/apps/domain.html">http://www.webairness.com/apps/domain.html</a>。<br />
因此：将想要共享使用的资源（图片、CSS，JS等等）存放到一个唯一的站点里，其他站点都引用这个唯一的URL。
</p>
<p id="scaledImages">
<strong>2. Serve scaled images：衡量图片的大小缩放</strong><br />
我们都知道页面中的图片最好能明确的通过HTML标签属性或者CSS来声明它实际的尺寸，而不要强制声明的尺寸跟图片实际尺寸不符合。但是有种情况是：在一个页面中需要显示一个图片的好几个不同的尺寸，而不想下载几个尺寸不同的图片。比如一个250&#215;250的图片，需要在页面中显示一个缩略图是10&#215;10尺寸的，这种场景经常在一个Tab组件中见到。Google Page Speed提到，如果图片的实际尺寸跟页面中几个尺寸中至少一个尺寸相符，并且是最大的那个，比如这里的是250&#215;250，那么这对性能会有所提高。<br />
对于上面提到的情况：到底是使用一个图片并在页面中强制声明缩放图片尺寸，还是加载几个尺寸不同的图片，从而在页面中显示不同尺寸但是内容相同的图片？我写了两个测试页面：<a  href="http://www.ilovejs.net/lab/scale-img/test1.html">http://www.ilovejs.net/lab/scale-img/test1.html</a>，<a  href="http://www.ilovejs.net/lab/scale-img/test2.html">http://www.ilovejs.net/lab/scale-img/test2.html</a>。<br />
从对上面两个页面测试中发现：当时第一次浏览空缓存的时候，两个页面的渲染速度没什么差别，而总的加载时间是有缩放图片的页面快；当有缓存的时候，这就排除了HTTP请求数的影响，此时页面的渲染速度明显是几个尺寸不同的图片快。因此：这就需要一个衡量的事情。<br />
<strong>附：</strong>在Google Page Speed中关于这个有一句En文不明白意思“However, if you serve an image that is larger than the dimensions used in all of the markup instances, you are sending unnecessary bytes over the wire.”希望懂的人指明一二~
</p>
<p id="optimizeImages">
<strong>3. Optimize images：优化图片</strong><br />
优化图片方面主要是利用好三种图片格式：PNG（又分为PNG8，PNG24）、GIF、JPG/JPEG。这三种格式各有用途，而总得来说：PNG用在Sprites背景图片、修饰页面的icon以及渐变图片中；GIF虽然也可以用在一些背景图片，视情况而定，主要就是因为GIF图片格式相对其他两种来说文件大小会小很多，适合用于一些清晰度要求不高的图片中；JPG/JPEG格式的文件大小一般都是最大的，因为它的色素高，适合展示相片之类对清晰度要求高的图片。<br />
除了选择好了图片格式之外，还得利用工具来压缩图片，对于JPG/JPEG格式的图片，可以使用<a  href="http://jpegclub.org/">jqegtran</a>和<a  href="http://freshmeat.net/projects/jpegoptim/">jpegoptim</a>这两个工具；对于PNG，则可以使用<a  href="http://optipng.sourceforge.net/">OptiPNG</a>和<a  href="http://www.advsys.net/ken/util/pngout.htm">PNGOUT</a>。<br />
同时，在HTML编写方面，需要明确的指定图片的尺寸（显式声明width、height属性），避免浏览器不必要的渲染性能消耗。
</p>
<p id="loadout">
<strong>4. 拆分初始化负载</strong><br />
随页面一起加载的Javascript中，有些函数是用于在加载页面的同时就起作用的，但是还有一部分的代码是在页面加载的过程中不会执行或者用不到的，如果让这部分代码连同需要执行的函数代码随页面一起加载的话，将会阻塞后续资源的加载，造成更多的时间延迟。所以我们需要将需要立即执行的代码和在页面onload之后才有可能出发的代码拆分开来，而这个拆分的平衡点就是：那些需要在页面的onload事件触发前需要执行的以及哪些是在onload之后才有可能执行的。 将那部分不会立即执行的代码通过onload事件来动态的加载，减小页面加载的总时间。
</p>
<p id="minifyHTML">
<strong>5. Minify HTML</strong><br />
Minify HTML文档的内容（包括行内脚本和行内样式），这样就可以减小页面的大小，更快的加载HTML页面、渲染和Layout文档。<br />
Minify HTML文档跟缩小JS、CSS一样会得到非常多的好处：减小网络延迟、增进压缩、更快的加载和渲染。而且HTML经常会包含行内脚本和行内样式，压缩它们也都非常有必要。举个简单的例子：行内脚本使用script标签来引入，页面内只需要写script，而不需要写language和type属性，style标签也一样，不需要写明type属性，浏览器发现这些没写明的话，会采取默认的执行方式。<br />
同时对于HTML标签的写法，也有几点建议：</p>
<ol>
<li>对于属性用单引号还是双引号的问题。建议统一使用单引号或者双引号，或者在DOCTYPE允许的情况下，省略掉。</li>
<li>对于属性的顺序问题。比如a标签，应该把href属性放在最前面来声明，其他属性根据字符顺序排序来声明：&lt;a href=”#” alt=””title=””&gt;link&lt;/a&gt;。</li>
<li>在标签于标签之间，去掉不必要的空格和\t\r\n等等，例如可以看看http://www.ilovejs.net 站点的HTML源码。</li>
<li>对于CSS的key-value的编写方式建议按照字母顺序a-z来组织。</li>
</ol>
<p id="minifyCSS">
<strong>6. Minify CSS</strong><br />
Minify CSS代码（移除不必要的空格、注释、换行符等等）可以节省字节数、加快下载、渲染和执行时间。<br />
有几个工具可以用来实现压缩CSS：<a  href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a>、 <a  href="http://www.phpied.com/cssmin-js/">cssmin.js</a>。<br />
同时，对于Minify CSS在编写代码方面尽量保持简写和归类的方式，这样一来容易维护，二来在性能上也会有所提高。比如：<br />
简写：background:url(example.png) no-repeat 0 0;<br />
归类：#test1,#test2,…#testN{background:url(example.png) no-repeat;}
</p>
<p id="minifyJavascript">
<strong>7. Minify JavaScript</strong><br />
Minify Javascript代码（移除不必要的空格、注释、换行符等等）可以节省字节数、加快下载、渲染和执行时间。<br />
Minify Javascript之后有三个好处：</p>
<ol>
<li>如果有些行内脚本和外部脚本不想要缓存的时候，文件越小网络延迟加载的时间就越短。</li>
<li>Minify Javascript之后可以更加增进外部脚本代码的压缩以及HTML内的行内脚本。</li>
<li>更小的文件可以更快的被浏览器加载和执行。</li>
</ol>
<p>有几个工具可以用来压缩Javascript代码：<a  href="http://www.crockford.com/javascript/jsmin.html">JSMin</a>，<a  href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a>，<a  href="http://code.google.com/closure/compiler/">Closure Compiler</a>，<a  href="http://shrinksafe.dojotoolkit.org/">Dojo Shrinksafe</a>。
</p>
<p id="RemoveUnusedCSS">
<strong>8. Remove unused CSS：删除无用的CSS</strong><br />
删除或者推迟加载一些当前文档用不到的样式规则，可以避免不必要的下载字节数以至于让浏览器更快的开始渲染页面。<br />
在浏览器开始渲染页面之前，它必须要下载和解析全部的用于布局页面的样式表。即时一个外部的样式表已经存在于缓存中，页面渲染也都会被阻塞直到浏览器从缓存中加载了全部的样式表。另外，一旦样式表被加载下来，浏览器的CSS引擎就会执行每一条样式规则，从而确定每一条声明的样式规则对当前文档是否得到应用。但现实中的情况是很多网站从始至终在网站的每一个页面中都使用同一个样式表，而不管样式表中有些规则是否会被当前文档用到。<br />
所以，最好的方式就是最小化由样式表加载和解析所造成的延迟时间，而解决方案就是移除或者延迟加载那些不被当前文档使用到的样式规则。<br />
对此，Google Page Speed做如下建议：</p>
<ol>
<li>在行内样式中删除掉任何不为当前页面使用的样式规则。</li>
<li>如果你的站点中在几个页面中都引用了同一个样式文件，考虑下将样式文件拆分为更小的文件来为特定的页面特定的样式。</li>
<li>如果一些样式规则在页面加载的时候不需要使用，最好将他们放置到另外一个文件里，在页面的onload事件里加载它。</li>
<li>如果使用Javascript来动态生成样式规则时，确保那些会生成当前页面不需要的的样式规则的Javascript函数不会被执行。</li>
</ol>
<p>上面提到的四点对于清除无用的CSS是比较良好的解决方案和建议。口碑网现在加载页面的样式表同样使用了Minify的方式，因为头部和底部是全部页面都通用的，所以页面统一都加载了base.css和header.css。但是口碑网站中包括了许多中不同样式的头和底部，base库里也会有非常多的样式不能在全部的页面中都使用上，所以就造成了在当前页面非常多的无用的CSS规则，这一来影响了CSS文件的加载，二来影响了CSS引擎的解析。<br />
所以，更理想的方式是将Minify的方式更加的颗粒化，将base.css和header.css更加的细分，真正做到按需加载。
</p>
<p id="EnableCompression">
<strong>9. Enable compression：允许压缩</strong><br />
用Gzip或者deflate来压缩资源可以减少大部分的网络传输数据量，这点是毋庸置疑的。可以压缩HTML文档内容、CSS文件、Javascript文件等等来使得页面加载速度更快。<br />
当前主流浏览器都支持使用gzip/deflate来压缩HTML文档、CSS和Javascript文件，从而使得从服务端发送回来的数据量比原始大小减少了许多（通常在50%上下），这是非常可观的。Gzip压缩的原理非常简单，就是将指定的文件类型在服务器端打包压缩，在发送回浏览器解压，这个过程是服务器和浏览器会自动处理的，我们只需要正常的使用普通的方式链入CSS、Javascript文件即可。<br />
但是我们也知道，这个压缩和解压的过程，是需要消耗CPU和内存的，所以gzip压缩一般只在压缩大文件的时候才能显示出它的优势。Google Page Speed经过测试发现：当使用gzip来压缩一个大小在150到1000 bytes的文件时，实际上会使他们更大，体现不出gzip的优势了。所以尽量保持在只对1000 bytes大小以上的资源进行gzip压缩。<br />
同时还有一点需要指出的是：不要对图片或者其他的二进制的文件（比如：PDF，video，ppt等等）进行gzip压缩，因为它们已经进行过压缩了。如果对它们使用了gzip压缩之后，不仅不会带来应有的好处，还会实际上使它们更大。如果要压缩图片，可以查看上面的：<strong>Optimize images：优化图片</strong>。
</p>
<p id="MinimizeRequestSize">
<strong>10. Minimize request size：最小化request请求头信息的大小</strong><br />
尽量保持request请求头信息的短小能确保HTTP的request请求可以通过发送一个数据包就可以完成请求信息的传输。<br />
理想的情况下，一个HTTP请求尽量不要超过一个数据包来发送到服务器。当前大部分的在使用的网络对一个数据包大小的限制是在1500 kytes左右，所以当你限制每个请求的头信息的大小在1500 bytes以内，你就可以减少发送请求头的时间总开销。而HTTP请求头信息一般包括：</p>
<ol>
<li>Cookies。如果请求一些资源必须要发送cookie的时候，尽量保持cookie的大小尽量的小，来确保HTTP请求头信息的总大小在限制的范围内。因此，发送的每一个cookie尽量保持在1000 bytes以内。建议是每个域名下发送的全部的Cookies的平均值在400 bytes以下，将没用的或者是重复的Cookies给删除掉。</li>
<li>浏览器自动设置的信息。许多头信息都是由用户代理自动地设置的，这部分是无法控制的。</li>
<li>请求的URL（GET或者Host头）。如果URL设置了很多参数的话，这会无疑的增加了HTTP请求头总体的大小。所以尽量保持URL的大小越小越好，建议是至少是在几百bytes之内。</li>
<li>Referer URL。有时候请求头中会包含referer头指定的URL，这个URL跟第三点就有相同的要求了。</li>
</ol>
<p>因此，尽量保持HTTP请求头信息总大小在限制的范围内，对提高页面加载速度，还是有效果的。
</p>
<p id="CookielessDomain">
<strong>11. Serve static content from a cookieless domain：减小静态资源的cookie的大小</strong><br />
通常如果在一个域名下（比如www.example.com）的HTML页面在发送请求的时候设置了cookie，那么在页面中的一些静态资源的请求头中也会发送这些cookie，而服务器对于静态资源发送的cookie是毫无作用的，反而是徒增了HTTP请求头的大小。所以，确保静态资源的HTTP请求头中不发送这些cookie来减小HTTP请求头信息的大小。<br />
解决这个问题的方案是：创建一个子域名或者购买一个新域名来映射静态文件，跟当前域名隔离开来。<br />
比如：你的域名是www.example.com，你就可以创建一个子域名static.example.com来映射静态文件。但是，如果你是将cookie设置到最高级的example.com域名下，那么子域名下的静态资源也都会发送cookie，这个时候，你就不得不花钱购买一个新的域名来映射这些静态资源。<br />
同时，移除静态资源的cookie的另外一个好处是避免一些代理对静态资源拒绝缓存的情况，因为一些代理会拒绝缓存一些HTTP请求头中包含cookie信息的静态资源。所以从这方面出发，避免静态资源的HTTP请求头中包含cookie信息，益处是颇大的。<br />
还有一点需要说明的是，对于Javascript文件，如果它一定要放置在head里并需要在页面中即时加载，最好将这个Javascript文件放置到跟HTML文档同一个域下，因为反正Javascript文件的加载都会阻塞页面其他资源的加载和阻塞页面的渲染，所以就没有必要将这个Javascript文件放置到其他域下，增加DNS查找的延迟时间。
</p>
<p id="OptimizeOrder">
<strong>12. Optimize the order of styles and scripts：优化js和css文件的加载顺序</strong><br />
正确对外部的样式表文件和脚本文件或者行内脚本进行排列加载，会得到更好的并行下载数和加快浏览器渲染页面。<br />
这个主要是因为Javascript代码可能会改变页面的内容和布局，所以浏览器在遇到script标签的时候，会延迟渲染页面任何内容，直到脚本下载并执行完毕。而还有一点就是加载脚本会阻塞后续任何资源的加载，这个是最致命的。但是另一方面，在页面的加载队列里，如果在脚本文件的前面已经存在有另外的文件需要加载，那么脚本文件将会跟这些文件并行加载。<br />
所以这就有几种情况：</p>
<ol>
<li>当js文件穿插在css文件中来加载。这样的后果就是每到加载js文件的时候，就会阻塞后续的js或者css文件的加载，这无疑就没有利用好浏览器的并行加载的机制。</li>
<li>当js文件都放在css文件的最末尾来加载。因为css文件的加载不会阻塞后续资源的加载，而且还可以跟其他资源并行加载，所以前面的样式表和样式表后的第一个js文件可以并行加载。这比第一点就快速多了，具体图示可以浏览《<a  href="http://code.google.com/speed/page-speed/docs/rtt.html#PutStylesBeforeScripts">Optimize the order of styles and scripts</a>》。</li>
</ol>
<p>这里还有一种情况需要说明的是：当行内脚本紧跟在样式表后面的时候，将会阻塞后续资源的加载（这里我提一点：是当script标签紧跟在样式表link标签后面的时候，也将会阻塞后续资源的加载，测试页面：<a  href="http://www.ilovejs.net/lab/script-after-styylesheet.html">http://www.ilovejs.net/lab/script-after-styylesheet.html</a>）。当行内脚本紧跟在样式表后面的时候，浏览器要在样式表完全下载之后才开始执行行内脚本，如果行内脚本又需要执行比较长的时间，这可能还会更糟。这是因为行内脚本有可能含有依赖于样式表中样式的代码，比如HTML5中的getElementsByClassName方法。浏览器按顺序下载样式表和执行行内脚本是为了保证一致的结果。
</p>
<p>
====================== 待续 ======================
</p>
<p>
<strong>Updates:</strong>
</p>
<p>
以下是瓶子对第一点“Serve scaled images：衡量图片的大小缩放”的一个翻译，觉得比较符合英文愿意：
</p>
<blockquote><p>
有时候，你或许想用不同尺寸显示同一张图片，因此你会传输同一张图片，然后用html或者css去缩放它。例如，你想把一个250*250的图片缩放到10*10大小的图片，通常不是倾向于强制用户下载2个独立的文件，你会用标记去重定义小图片的大小。这意味着实际图片的尺寸应该至少与页面的一个图片（尺寸最大的那个）相匹配，本例是指那个250*250的。然而，如果你传送了一个比所有标记的图片尺寸都大的图片，那么你就是在发送不必要的字节。你应该使用一个图片编辑器来缩放图片到页面需要的最大尺寸的那个标记的图片，同时确保你在页面中指定了这些尺寸。
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/810/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Javascript,CSS Minify</title>
		<link>http://www.ilovejs.net/archives/449</link>
		<comments>http://www.ilovejs.net/archives/449#comments</comments>
		<pubDate>Tue, 13 Apr 2010 13:21:38 +0000</pubDate>
		<dc:creator>Supersha</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[minify]]></category>

		<guid isPermaLink="false">http://www.ilovejs.net/?p=449</guid>
		<description><![CDATA[这几天在思索口碑网的CSS Minify的实现方式，询问之后，悟出点原理，示例： 上面的示例中，将三个css文件压缩为一个css文件，减少了两个HTTP请求，性能上确实能提高不少，特别是对于访问量大的页面。但是之前一直在思索两个问题： 文件名中包含不规则的字符，在windows操作系统下是不允许作为文件名的。 浏览器的缓存怎么处理。 通过一些时间摸索和跟同事进行探讨，迷雾渐渐清晰了。对于一个问题，服务器端是进行了urlrewrite了，比如上面图示的url链接其实是障眼法，是给别人看是这么个东东（它包含了一些版本和文件名的信息，使用版本号的一个好处就是可以在版本升级的时候可以及时更新缓存，保持更行的css文件的及时生效），其实是服务器端会将它rewrite到另外一个文件里。这个文件是会自动通过参数整合三个css文件到一个css文件里，最后download到客户端。那么对于第二个问题也就好解释了，url不变，浏览器就会从缓存里读取。 问题想清楚了，偶也就开始思索着自己去怎么实现这么个功能，下面是我摸索过程中所想到的办法（经测试，都不太理想）： 第一：通过服务端的一个程序文件（这里是PHP的一个小程序）来获取客户端发送的几个javascript或者CSS的URL信息，之后通过PHP脚本将这几个文件整合为一个文件并把整合后的文件发送到客户端，在客户端再通过responseText把代码动态生成script或者style，插入到head中。 [php] &#60;?php //////////////// test.php file: //////////////// //file path param $path=$_GET[&#34;jspath&#34;]; //split param &#8230; <a href="http://www.ilovejs.net/archives/449" class="more-link">了解更多</a>]]></description>
			<content:encoded><![CDATA[<p>这几天在思索<a  href="http://www.koubei.com">口碑网</a>的CSS Minify的实现方式，询问之后，悟出点原理，示例：</p>
<p>
<a href="http://www.ilovejs.net/wp-content/uploads/2010/04/QQ截图未命名1.png"><img src="http://www.ilovejs.net/wp-content/uploads/2010/04/QQ截图未命名1.png" alt="" title="koubei css minify" width="576" height="163" class="alignnone size-full wp-image-458" /></a>
</p>
<p>上面的示例中，将三个css文件压缩为一个css文件，减少了两个HTTP请求，性能上确实能提高不少，特别是对于访问量大的页面。但是之前一直在思索两个问题：</p>
<ol>
<li>文件名中包含不规则的字符，在windows操作系统下是不允许作为文件名的。</li>
<li>浏览器的缓存怎么处理。</li>
</ol>
<p>
通过一些时间摸索和跟同事进行探讨，迷雾渐渐清晰了。对于一个问题，服务器端是进行了urlrewrite了，比如上面图示的url链接其实是障眼法，是给别人看是这么个东东（它包含了一些版本和文件名的信息，使用版本号的一个好处就是可以在版本升级的时候可以及时更新缓存，保持更行的css文件的及时生效），其实是服务器端会将它rewrite到另外一个文件里。这个文件是会自动通过参数整合三个css文件到一个css文件里，最后download到客户端。那么对于第二个问题也就好解释了，url不变，浏览器就会从缓存里读取。
</p>
<p>
问题想清楚了，偶也就开始思索着自己去怎么实现这么个功能，下面是我摸索过程中所想到的办法（经测试，都不太理想）：
</p>
<p><span id="more-449"></span></p>
<p>
<strong>第一：</strong>通过服务端的一个程序文件（这里是PHP的一个小程序）来获取客户端发送的几个javascript或者CSS的URL信息，之后通过PHP脚本将这几个文件整合为一个文件并把整合后的文件发送到客户端，在客户端再通过responseText把代码动态生成script或者style，插入到head中。</p>
<p>[php]<br />
&lt;?php<br />
//////////////// test.php file: ////////////////<br />
//file path param<br />
$path=$_GET[&quot;jspath&quot;];</p>
<p>//split param<br />
$split=$_GET[&quot;split&quot;];</p>
<p>//file path array<br />
$path_arr=split($split,$path);</p>
<p>//store all files text<br />
$js_str=&quot;&quot;;</p>
<p>//the count of file path array<br />
$count=count($path_arr);</p>
<p>//read each file<br />
for($i=0;$i&lt;$count;$i++){<br />
  $file_read=fopen($path_arr[$i],&quot;r&quot;);<br />
  while(!feof($file_read)){<br />
    $line=fgets($file_read);<br />
	  if(strlen($line) ===1){<br />
	    $js_str=$js_str.$line.&quot;\n&quot;;<br />
	  }else{<br />
	    $js_str=$js_str.$line;<br />
	  }<br />
  }<br />
  fclose($file_read);<br />
}<br />
echo($js_str); // flush all content to client.<br />
?&gt;<br />
[/php]<br />
[javascript]<br />
///////////////// combine.js file /////////////////<br />
(function(global){<br />
	var XHR=function(){<br />
		var xhr=false;<br />
		if(window.XMLHttpRequest){<br />
			 xhr=new XMLHttpRequest();<br />
		}else{<br />
			 try{<br />
				xhr=new ActiveXObject(&quot;Msxml2.XMLHTTP&quot;);<br />
			 }catch(e){<br />
				xhr=new ActiveXObject(&quot;Microsoft.XMLHTTP&quot;);<br />
			 }<br />
		}<br />
		return xhr;<br />
	}<br />
	var InsertElement={<br />
		&quot;js&quot;:function(text){<br />
			var script=document.createElement(&quot;script&quot;);<br />
			script.setAttribute(&quot;type&quot;,&quot;text/javascript&quot;);<br />
			script.text=text;<br />
			document.getElementsByTagName(&quot;head&quot;)[0].appendChild(script);<br />
		 },<br />
		&quot;javascript&quot;:this[&quot;js&quot;],<br />
		&quot;css&quot;:function(text){<br />
			var style=document.createElement(&quot;style&quot;);<br />
			style.setAttribute(&quot;type&quot;,&quot;text/css&quot;);<br />
			style.innerHTML=text;<br />
			document.getElementsByTagName(&quot;head&quot;)[0].appendChild(style);<br />
		 }<br />
	}<br />
	var combineJS=function(urls,path,type,split,compress){<br />
		split = split || &quot;,&quot;;<br />
		type = type || &quot;js&quot;;<br />
		var url=path+&quot;?jspath=&quot;+urls.join(split)+&quot;&amp;split=&quot;+split;<br />
		var xhr=XHR();<br />
		xhr.open(&quot;GET&quot;,url,true);<br />
		xhr.onreadystatechange=function(){<br />
			if(xhr.readyState === 4 &amp;&amp; xhr.status === 200){<br />
				InsertElement[type](xhr.responseText);<br />
			}<br />
		}<br />
		xhr.send(null);<br />
	}<br />
	global.combineJS=combineJS;<br />
})(window);<br />
//combine files<br />
combineJS([&quot;test1.js&quot;,&quot;test2.js&quot;,&quot;test3.js&quot;,&quot;http://localhost/sizzle.js&quot;],&quot;combine.php&quot;);<br />
[/javascript]</p>
<p>
上面的方式是通过动态生成script或者style的方式来达到合并文件，减少HTTP请求的目的。但是测试中发现一个问题：客户端请求合并后的文件会等待比较长的时间，这跟直接链入几个文件比起来，消耗的时间差距比较大。如下图示显示的合并后的文件插入到了文档中，以及一直处于等待状态的一个问题（1s~6s之间)。《<a  href="http://www.ilovejs.net/lab/combine/combine.html">测试用例</a>》
</p>
<p>
<a href="http://www.ilovejs.net/wp-content/uploads/2010/04/QQ截图未命名332.png"><img src="http://www.ilovejs.net/wp-content/uploads/2010/04/QQ截图未命名332.png" alt="" title="QQ截图未命名33" width="425" height="204" class="alignnone size-full wp-image-461" /></a><br />
<a href="http://www.ilovejs.net/wp-content/uploads/2010/04/QQ截图未命名11.png"><img src="http://www.ilovejs.net/wp-content/uploads/2010/04/QQ截图未命名11.png" alt="" title="QQ截图未命名1" width="624" height="96" class="alignnone size-full wp-image-460" /></a>
</p>
<p>
<strong>第二：</strong>合并几个文件的方法和上面的一样，只是我将合并后的文件内容返回来的时候插入到当前发送请求的script标签内，这得益于一个技巧：在加载的时候，当前的script元素永远是处于scripts.length-1的索引位置。因此可以在js代码里面进行改写：《<a  href="http://www.ilovejs.net/lab/combine/combine2.html">测试用例</a>》
</p>
<p>[javascript]<br />
(function(global){<br />
   var XHR = function(){<br />
      var xhr = false;<br />
      if (window.XMLHttpRequest) {<br />
         xhr = new XMLHttpRequest();<br />
      }<br />
      else {<br />
         try {<br />
            xhr = new ActiveXObject(&quot;Msxml2.XMLHTTP&quot;);<br />
         }<br />
         catch (e) {<br />
            xhr = new ActiveXObject(&quot;Microsoft.XMLHTTP&quot;);<br />
         }<br />
      }<br />
      return xhr;<br />
   }<br />
   // Check DOM whether is rendered.<br />
   var DOMReady = function(fn){<br />
      fn = typeof fn === &quot;function&quot; ? fn : function(){<br />
      };<br />
      (function(){<br />
         if (document &amp;&amp; document.getElementsByTagName &amp;&amp; document.getElementById &amp;&amp; document.body) {<br />
            fn();<br />
         }<br />
         else {<br />
            setTimeout(arguments.callee, 10);<br />
         }<br />
      })();<br />
   }<br />
   //Execute the code from server.<br />
   var evalJS = function(text){<br />
      DOMReady(function(){<br />
         eval(text);<br />
      });<br />
   }<br />
   var InsertElement = {<br />
      &quot;js&quot;: function(text){<br />
         var scripts = document.getElementsByTagName(&quot;script&quot;);<br />
         var script = scripts[scripts.length - 1];<br />
         script.text += text;<br />
         evalJS(text);<br />
      },<br />
      &quot;javascript&quot;: this[&quot;js&quot;],<br />
      &quot;css&quot;: function(text){<br />
         var style = document.createElement(&quot;style&quot;);<br />
         style.setAttribute(&quot;type&quot;, &quot;text/css&quot;);<br />
         style.innerHTML = text;<br />
         document.getElementsByTagName(&quot;head&quot;)[0].appendChild(style);<br />
      }<br />
   }<br />
   var combineJS = function(urls, path, type, split, compress){<br />
      split = split || &quot;,&quot;;<br />
      type = type || &quot;js&quot;;<br />
      var url = path + &quot;?jspath=&quot; + urls.join(split) + &quot;&amp;split=&quot; + split;<br />
      var xhr = XHR();<br />
      xhr.open(&quot;GET&quot;, url, true);<br />
      xhr.onreadystatechange = function(){<br />
         if (xhr.readyState === 4 &amp;&amp; xhr.status === 200) {<br />
            InsertElement[type](xhr.responseText);<br />
         }<br />
      }<br />
      xhr.send(null);<br />
   }<br />
   global.combineJS = combineJS;<br />
})(window);</p>
<p>combineJS([&quot;test1.js&quot;, &quot;test2.js&quot;, &quot;test3.js&quot;], &quot;combine.php&quot;, &quot;js&quot;);<br />
[/javascript]</p>
<p>
经过测试，上面的方式跟第一种是一样的效果，不理想。虽然减少了HTTP的请求数目，但是增加了服务器响应的等待时间。
</p>
<p><a href="http://www.ilovejs.net/wp-content/uploads/2010/04/QQ截图未命名12.png"><img src="http://www.ilovejs.net/wp-content/uploads/2010/04/QQ截图未命名12.png" alt="" title="QQ截图未命名1" width="529" height="390" class="alignnone size-full wp-image-464" /></a></p>
<p>
<strong>第三：</strong>仿照<a  href="http://www.koubei.com">口碑网</a>的实现方式，通过在服务端动态生成一个合并了几个javascript或者CSS的文件，之后把整合后的文件的url返回给客户端，之后进行引用。《<a  href="http://www.ilovejs.net/lab/combine/combine3.html">测试用例</a>》
</p>
<p>[php]<br />
&lt;?php</p>
<p>//file path param<br />
$path=$_GET[&quot;jspath&quot;];<br />
//$path=&quot;/test/test/test1.css,/test/test/test2.css,/test/test/test3.css&quot;;<br />
//split param<br />
$split=$_GET[&quot;split&quot;];<br />
//$split=&quot;,&quot;;<br />
//file path array<br />
$path_arr=split($split,$path);</p>
<p>//store all files text<br />
$js_str=&quot;&quot;;</p>
<p>//the count of file path array<br />
$count=count($path_arr);</p>
<p>//read each file<br />
for($i=0;$i&lt;$count;$i++){<br />
  $file_read=fopen(&quot;http://www.ilovejs.net/lab/combine/&quot;.$path_arr[$i],&quot;r&quot;);<br />
  while(!feof($file_read)){<br />
    $line=fgets($file_read);<br />
	  if(strlen($line) ===1){<br />
	    $js_str=$js_str.$line.&quot;\n&quot;;<br />
	  }else{<br />
	    $js_str=$js_str.$line;<br />
	  }<br />
  }<br />
  fclose($file_read);<br />
}</p>
<p>//write content to a file.<br />
$write_file=fopen(&quot;http://www.ilovejs.net/lab/combine/&quot;.$path,&quot;w+&quot;);<br />
fwrite($write_file,$js_str);<br />
fclose($write_file);</p>
<p>// response to client.<br />
echo($path);<br />
?&gt;<br />
[/php]<br />
之后客户端通过resonseText获得这个url，动态插入一个script或者link元素到head中。测试之后，上面的问题还是没有解决。</p>
<p>
<a href="http://www.ilovejs.net/wp-content/uploads/2010/04/QQ截图未命名331.png"><img src="http://www.ilovejs.net/wp-content/uploads/2010/04/QQ截图未命名331.png" alt="" title="QQ截图未命名33" width="451" height="81" class="alignnone size-full wp-image-453" /></a><br />
<a href="http://www.ilovejs.net/wp-content/uploads/2010/04/QQ截图未命名13.png"><img src="http://www.ilovejs.net/wp-content/uploads/2010/04/QQ截图未命名13.png" alt="" title="QQ截图未命名1" width="676" height="72" class="alignnone size-full wp-image-466" /></a><br />
<a href="http://www.ilovejs.net/wp-content/uploads/2010/04/QQ截图未命名551.png"><img src="http://www.ilovejs.net/wp-content/uploads/2010/04/QQ截图未命名551.png" alt="" title="QQ截图未命名55" width="623" height="76" class="alignnone size-full wp-image-454" /></a>
</p>
<p>
总结下：上面的实现方式都是存在问题的：通过客户端发送urls，服务端再整合文件，之后发送url或者内容。这已经存在了两个必须的HTTP请求。这个就存在许多客观的因素来影响这两个HTTP请求的反应时间：一个是网速，一个是客户端和服务端操作系统的性能。
</p>
<p>
所以，比较合理的做法是通过参数，在服务端直接整合成一个文件，生成之后客户端再通过url链入到head中，这中间就需要一个跟普通通过script或者link链入文件的开销，却减少了许多个HTTP请求的开销，这才能起到优化的目的。下面是<a  href="http://www.koubei.com">口碑网</a>的最佳实践方式：
</p>
<p>&lt;jsp:include page=”/CMS/headers/wrap/header.jsp”&gt;<br />
  &lt;jsp:param name=”css” value=”&lt;%=STYLE_BASE_4_X_X+”,”+STYLE_HEAD+”,”+STYLE_XXX%&gt;”/&gt;<br />
  &lt;jsp:param name=”charset” value=”utf-8&#8243; /&gt;<br />
&lt;/jsp:include&gt; </p>
<p>
通过上面参数的设置，事先在服务端生成这个整合的文件，之后页面内就通过script或者link来链入这个文件。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ilovejs.net/archives/449/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

