2007年04月08日

  之前接确Mootools时,发现其官方网站的下载页面提供定制下载功能。除了定制包之外,还可定制所下载脚本的压缩比,对缩后的脚本体积更小,但能正确在主流浏览器中运行。对在流量大的网站来说,更小的页面体积(包括HTML、JavaScript、CSS等)意味着可以节省更多的服务器资源、网络带宽和流量,因此JavaScript的压缩在Web开发中有着重要的意义。该压缩功能是用一个叫“JavaScript Packer”的类库实现的,原版由Dean Edwards提供,其PHP版本可在http://joliclic.free.fr/php/javascript-packer/en/下载得到,由于用了相关的面向对象特性,所以该版本只支持PHP 5。

  该类库的使用方法很简单,很看一个最简单的例子:
<?php
require ‘class.JavaScriptPacker.php’;//导入包
$packer = new JavaScriptPacker($script);//构造压缩器对象
$result = $packer->pack();//执行压缩并返回结果
?>
以上例子中,变量$script代表要所压缩的JavaScript脚本(字符串形式),$result而存放了压缩后的脚本。我们就拿Mootools的库来做实验,从官方下载某版本的所有包,未经压缩的源代码一共是139kb,使用默认参数压缩后,得到的大小为35.1kb,经测试,其功能能正常使用。

  JavaScriptPacker这个类的构造函数还可以接受其它的参数,实现对压缩行为的更详细定制。先看看其函数原形

public function __construct($_script, $_encoding = 62, $_fastDecode = true, $_specialChars = false)

一共有四个参数:$_script是输入的脚本字符串;$_encoding是压缩比,可接受0,10,62,95四个压缩级别,默认值62;$_fastDecode是快速解压器的开关,打开后会略为增加文件大小,但能提高脚本运行速度,默认true;$_specialChars用于指示脚本中是否有特殊字符,默认false。

  知道了以上这些,我们就可以写出相关的脚本,帮助我们定制压缩JavaScript。以下是我写好的两个版本的脚本,读者可以直接保存使用。前者是在web服务器中运行的,接受上传一个脚本,压缩返还给浏览器下载。后者是可运行在系统控制台的脚本,配置好PHP CLI的运行环境之后,调用php console.php input.js output.js即可使用默认参数把input.js文件压缩并输出为output.js,而使用php console.php则可查看使用方法。

web.php 运行于Web服务器上版本


<?php
error_reporting
(0);
require 
'class.JavaScriptPacker.php';

if (!empty($_FILES['source_file'])) {
    
$_POST['encoding'] = isset($_POST['encoding']) ? (int) $_POST['encoding'] : 62;
    
$_POST['fastdecode'] = isset($_POST['fastdecode']) ? (bool) $_POST['fastdecode'] : true;
    
$_POST['specialchars'] = isset($_POST['specialchars']) ? (bool) $_POST['specialchars'] : true;

    $packer = new JavaScriptPacker(file_get_contents($_FILES['source_file']['tmp_name']), $_POST['encoding'], $_POST['fastdecode'], $_POST['specialchars']);

    if (preg_match('/^(.*)\.js$/i'$_FILES['source_file']['name'], $matches) == 0) {
        
$matches = array('none.js''none');
    }

    header('Content-Type: application/x-javascript'true);
    
header('Content-Disposition: attachment; filename='.$matches[1].'_packed.js');
    echo 
$packer->pack();
    exit;
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JavaScript Packer</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data" name="file_form" id="file_form">
  <input type="file" name="source_file" id="source_file" />
  <select name="encoding" id="encoding">
    <option value="0">None</option>
    <option value="10">Numeric</option>
    <option value="62" selected="selected">Normal</option>
    <option value="95">High ASCII</option>
  </select>
  <input type="checkbox" name="fastdecode" value="true" id="fastdecode" />
  <label for="fastdecode">fast deconde</label>
  <input type="checkbox" name="specialchars" value="true" id="specialchars" />
  <label for="specialchars">special characters</label>
  <input type="submit" name="submit_button" value="start pack" id="submit_button" />
</form>
</body>
</html>





console.php 运行于控制台的脚本

<?php
error_reporting
(0);

$help = <<<EOF
Usage:
    $argv
[0] [options] <input_file> <output_file>

Options:
    -e int     level of encoding
               0: None, 10: Numeric, 62: Normal, 95: High ASCII
               default: 62
    -f bool    include the fast decoder in the packed result
               0: false, 1: true
               default : true
    -s bool    if you are flagged your private and local variables in the script
               0: false, 1: true
               default : false

EOF;

function packJavaScript($script$output$encoding$fastDecode$specialChars) {
    include_once 
'class.JavaScriptPacker.php';
    
$packer = new JavaScriptPacker(file_get_contents($script), $encoding$fastDecode$specialChars);
    
file_put_contents($output$packer->pack());
}

if ($argc 3) {
    echo 
$help;
    exit;
} elseif (!
file_exists($_SERVER['argv'][$argc 2])) {
    echo 
"\nError, your input file dose not exist!\n\n";
    echo 
$help;
    exit;
} elseif (
file_exists($_SERVER['argv'][$argc -1])) {
    
$input_stream fopen('php://stdin','r');
    echo 
"\nOutput file ".$_SERVER['argv'][$argc 1]." already exist, cancle process(c), rename(r), or override(o)?(a/r/o) ";
    
$action fread($input_stream1);
    if (
strcasecmp($action'a') == 0) {
        echo 
"\nprogram terminated\n";
        exit;
    }  elseif (
strcasecmp($action'r') == 0) {
        echo 
"\nPlease input new file name, less than 255 characters: ";
        
$output trim(fread($input_stream255));
    }
    
fclose($input_stream);
}

$script       $_SERVER['argv'][$argc 2];
$output       = !isset($output) ? $_SERVER['argv'][$argc -1] : $output;
$encoding     = ($index array_search('-e'$_SERVER['argv'])) !== false ? (int) $_SERVER['argv'][$index 1] : 62;
$fastDecode   = ($index array_search('-f'$_SERVER['argv'])) !== false ? (bool) $_SERVER['argv'][$index 1] : true;
$specialChars = ($index array_search('-s'$_SERVER['argv'])) !== false ? (bool) $_SERVER['argv'][$index 1] : false;

packJavaScript($script$output$encoding$fastDecode$specialChars);

echo "\nOriginal file size:\t".filesize($script)."\tbytes";
echo 
"\nCompressed file size:\t".filesize($output)."\tbytes\n";
?>


2007年04月01日

一次,我们几位同学去拜访大学时的老师。老师问我们生活得怎么样。一句话勾出了大家的满腹牢骚,大家纷纷诉说着生活的不如意:工作压力大呀,生活烦恼多呀,做生意的商战不顺呀,当官的仕途受阻呀……一时间,大家仿佛都成了上帝的弃儿。

  老师笑而不语,从房间里拿出许许多多的杯子,摆在茶几上。这些杯子各式各样,有瓷器的,有玻璃的,有塑料的,有的杯子看起来高贵典雅,有的杯子看起来粗陋低廉……老师说:“都是我的学生,我就不把你们当客人看待了。你们要是渴了,自己倒水喝吧。”

我们说得已经口干舌燥了,便纷纷拿了自己中意的杯子倒水喝。等我们手里都端了一杯水时,老师讲话了,他指着茶几上剩下的杯子说:“大家有没有发现,你们挑 选去的杯子都是最好看最别致的杯子,而像这些塑料杯就没有人选中它。”我们并不觉得奇怪,谁都希望手里拿着的是一只好看的杯子。

老师说:“这就是你们烦恼的根源。大家需要的是水,而不是杯子,但我们有意无意地会去选用好的杯子。这就如我们的生活——如果生活是水的话,那么,工作、 金钱、地位这些东西就是杯子,它们只是我们用来盛起生活之水的工具。杯子的好坏,并不能影响水的质量,如果将心思花在杯子上,你哪有心情去品尝水的苦甜, 这不是自寻烦恼吗?”