CSS和JS合并优化工具-minify
下载地址:http://code.google.com/p/minify/
把min目录上传根目录,根目录打开http://example.com/min/
Note: Please set $min_cachePath in /min/config.php to improve performance.
设置/min/config.php文件 ,$min_cachePath 有3个选择。
//$min_cachePath = ‘c:\\WINDOWS\\Temp’;
//$min_cachePath = ‘/tmp’;
//$min_cachePath = preg_replace(‘/^\\d+;/’, ”, session_save_path());
选择第2个,去除// .设置tmp属性777
在显示的界面中加入你想合并压缩的 js/css 路径,点击 ‘Update’ 之后会为你生成一个 url,如:http://localhost/min/b=googletesting/js&f=mootools.js,iAction.js,iAjax.js,global.js
css和JS分别合并,2个地址。如果需要组合的文件很多,url 就会变得很长,Minify 支持 group,可以将这些文件分组,这样 url 中只需指定 g=group名字 就可以了。
安装完毕后删除min/builder/index.php 文件。防止其他人登陆!后期如需编辑再次上传!
#2楼发布者:superadmin时间:2010-07-29 10:29:06
这几天在思索口碑网的CSS Minify的实现方式,询问之后,悟出点原理,示例:
上面的示例中,将三个css文件压缩为一个css文件,减少了两个HTTP请求,性能上确实能提高不少,特别是对于访问量大的页面。但是之前一直在思索两个问题:
1.文件名中包含不规则的字符,在windows操作系统下是不允许作为文件名的。
2.浏览器的缓存怎么处理。
通过一些时间摸索和跟同事进行探讨,迷雾渐渐清晰了。对于一个问题,服务器端是进行了urlrewrite了,比如上面图示的url链接其实是障眼法,是给别人看是这么个东东(它包含了一些版本和文件名的信息,使用版本号的一个好处就是可以在版本升级的时候可以及时更新缓存,保持更行的css文件的及时生效),其实是服务器端会将它rewrite到另外一个文件里。这个文件是会自动通过参数整合三个css文件到一个css文件里,最后download到客户端。那么对于第二个问题也就好解释了,url不变,浏览器就会从缓存里读取。
问题想清楚了,偶也就开始思索着自己去怎么实现这么个功能,下面是我摸索过程中所想到的办法(经测试,都不太理想):
第一:通过服务端的一个程序文件(这里是PHP的一个小程序)来获取客户端发送的几个javascript或者CSS的URL信息,之后通过PHP脚本将这几个文件整合为一个文件并把整合后的文件发送到客户端,在客户端再通过responseText把代码动态生成script或者style,插入到head中。
<?php
//////////////// test.php file: ////////////////
//file path param
$path=$_GET["jspath"];
//split param
$split=$_GET["split"];
//file path array
$path_arr=split($split,$path);
//store all files text
$js_str="";
//the count of file path array
$count=count($path_arr);
//read each file
for($i=0;$i<$count;$i++){
$file_read=fopen($path_arr[$i],"r");
while(!feof($file_read)){
$line=fgets($file_read);
if(strlen($line) ===1){
$js_str=$js_str.$line."\n";
}else{
$js_str=$js_str.$line;
}
}
fclose($file_read);
}
echo($js_str); // flush all content to client.
?>
///////////////// combine.js file /////////////////
(function(global){
var XHR=function(){
var xhr=false;
if(window.XMLHttpRequest){
xhr=new XMLHttpRequest();
}else{
try{
xhr=new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
xhr=new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xhr;
}
var InsertElement={
"js":function(text){
var script=document.createElement("script");
script.setAttribute("type","text/javascript");
script.text=text;
document.getElementsByTagName("head")[0].appendChild(script);
},
"javascript":this["js"],
"css":function(text){
var style=document.createElement("style");
style.setAttribute("type","text/css");
style.innerHTML=text;
document.getElementsByTagName("head")[0].appendChild(style);
}
}
var combineJS=function(urls,path,type,split,compress){
split = split || ",";
type = type || "js";
var url=path+"?jspath="+urls.join(split)+"&split="+split;
var xhr=XHR();
xhr.open("GET",url,true);
xhr.onreadystatechange=function(){
if(xhr.readyState === 4 && xhr.status === 200){
InsertElement[type](xhr.responseText);
}
}
xhr.send(null);
}
global.combineJS=combineJS;
})(window);
//combine files
combineJS(["test1.js","test2.js","test3.js","http://localhost/sizzle.js"],"combine.php");
上面的方式是通过动态生成script或者style的方式来达到合并文件,减少HTTP请求的目的。但是测试中发现一个问题:客户端请求合并后的文件会等待比较长的时间,这跟直接链入几个文件比起来,消耗的时间差距比较大。如下图示显示的合并后的文件插入到了文档中,以及一直处于等待状态的一个问题(1s~6s之间)。《测试用例》
第二:合并几个文件的方法和上面的一样,只是我将合并后的文件内容返回来的时候插入到当前发送请求的script标签内,这得益于一个技巧:在加载的时候,当前的script元素永远是处于scripts.length-1的索引位置。因此可以在js代码里面进行改写:《测试用例》
(function(global){
var XHR = function(){
var xhr = false;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else {
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xhr;
}
// Check DOM whether is rendered.
var DOMReady = function(fn){
fn = typeof fn === "function" ? fn : function(){
};
(function(){
if (document && document.getElementsByTagName && document.getElementById && document.body) {
fn();
}
else {
setTimeout(arguments.callee, 10);
}
})();
}
//Execute the code from server.
var evalJS = function(text){
DOMReady(function(){
eval(text);
});
}
var InsertElement = {
"js": function(text){
var scripts = document.getElementsByTagName("script");
var script = scripts[scripts.length - 1];
script.text += text;
evalJS(text);
},
"javascript": this["js"],
"css": function(text){
var style = document.createElement("style");
style.setAttribute("type", "text/css");
style.innerHTML = text;
document.getElementsByTagName("head")[0].appendChild(style);
}
}
var combineJS = function(urls, path, type, split, compress){
split = split || ",";
type = type || "js";
var url = path + "?jspath=" + urls.join(split) + "&split=" + split;
var xhr = XHR();
xhr.open("GET", url, true);
xhr.onreadystatechange = function(){
if (xhr.readyState === 4 && xhr.status === 200) {
InsertElement[type](xhr.responseText);
}
}
xhr.send(null);
}
global.combineJS = combineJS;
})(window);
combineJS(["test1.js", "test2.js", "test3.js"], "combine.php", "js");
经过测试,上面的方式跟第一种是一样的效果,不理想。虽然减少了HTTP的请求数目,但是增加了服务器响应的等待时间。
第三:仿照口碑网的实现方式,通过在服务端动态生成一个合并了几个javascript或者CSS的文件,之后把整合后的文件的url返回给客户端,之后进行引用。《测试用例》
<?php
//file path param
$path=$_GET["jspath"];
//$path="/test/test/test1.css,/test/test/test2.css,/test/test/test3.css";
//split param
$split=$_GET["split"];
//$split=",";
//file path array
$path_arr=split($split,$path);
//store all files text
$js_str="";
//the count of file path array
$count=count($path_arr);
//read each file
for($i=0;$i<$count;$i++){
$file_read=fopen("http://www.ilovejs.net/lab/combine/".$path_arr[$i],"r");
while(!feof($file_read)){
$line=fgets($file_read);
if(strlen($line) ===1){
$js_str=$js_str.$line."\n";
}else{
$js_str=$js_str.$line;
}
}
fclose($file_read);
}
//write content to a file.
$write_file=fopen("http://www.ilovejs.net/lab/combine/".$path,"w+");
fwrite($write_file,$js_str);
fclose($write_file);
// response to client.
echo($path);
?>
之后客户端通过resonseText获得这个url,动态插入一个script或者link元素到head中。测试之后,上面的问题还是没有解决。
总结下:上面的实现方式都是存在问题的:通过客户端发送urls,服务端再整合文件,之后发送url或者内容。这已经存在了两个必须的HTTP请求。这个就存在许多客观的因素来影响这两个HTTP请求的反应时间:一个是网速,一个是客户端和服务端操作系统的性能。
所以,比较合理的做法是通过参数,在服务端直接整合成一个文件,生成之后客户端再通过url链入到head中,这中间就需要一个跟普通通过script或者link链入文件的开销,却减少了许多个HTTP请求的开销,这才能起到优化的目的。下面是口碑网的最佳实践方式:
<jsp:include page=”/CMS/headers/wrap/header.jsp”>
<jsp:param name=”css” value=”<%=STYLE_BASE_4_X_X+”,”+STYLE_HEAD+”,”+STYLE_XXX%>”/>
<jsp:param name=”charset” value=”utf-8″ />
</jsp:include>
通过上面参数的设置,事先在服务端生成这个整合的文件,之后页面内就通过script或者link来链入这个文件。