请求中的“开源节流”--用smasher来实时压缩前端代码(配合YUI Compressor)

首先,smasher是个什么东东,翻译过来是“粉碎者”的意思,- -!,它是使用PHP写成的一个小工具,可以直接放在线上,实时合并+压缩你的JS和CSS代码。

在一个比较依赖前端代码(比如说前端代码的人工代码量大于后端的人工代码量)的工程中,如何很好地部署前端代码,似乎也是前端们的一项很重要的工作。之前常用(包括现在)的部署工具是Apache Ant配合YUI Compressor来进行前端代码的压缩和部署,但是比较缺少灵活性。

smasher是一个比较轻灵的工具,点击这里进入它的github,和Apache Ant比较相似的是,它也是读取一个配置文件(其实可以根据不同的项目分布,编写不同的smasher入口文件,实例化不同的Smasher对象,再接受不同的参数(通过xml文件来配置),来合并压缩不同的文件(现在仅限于js+css)),然后通过一个入口文件来灵活地应用合并和压缩。为了更加详细的说明,看下原装的小例子吧:(在本地进行了适当的修改,可能和原装的例子有一些小差别,可以点击这里下载修改后的)

文件分布:

文件 

从下往上看,smasher_web.php是smasher小工具的入口文件,它可以通过get传值获取部分参数,并且读取本地配置文件smasher.xml

smasher.php是smasher的主文件,定义了smasher工具类本身。

那个没有后缀名的smasher则是在php命令行下运行的文件(和smasher_web.php几乎完全相同)。

tmp文件夹作为存放临时文件的文件夹。

jars文件夹里面藏着yuicompressor.jar文件(需要本机配置好java运行环境)。

files里面则作为演示用的待压缩的源文件。

看下files文件夹:

源文件

对smasher整个结构有个小的认识就可以开始仔细地看看它是怎么实现的了,懂的原理,就能灵活运用,还能再此基础上开发出更加适合自己项目的工具。

 

smasher.xml

<?xml version="1.0" encoding="utf-8"?>
<smasher>
	<!-- 设置缓存文件夹 -->
    <temp_dir>tmp/</temp_dir>
	<!-- 设置源文件路径 -->
    <root_dir>files/</root_dir>
	<!-- java bin -->
    <java_bin>C:/WINDOWS/system32/java</java_bin>
	<!-- YUI Compressor的路径 -->
    <yuicompressor>jars/yuicompressor.jar</yuicompressor>

    <!-- YUI 每一个group作为一个操作单位,拥有唯一的ID,可以再操作时指定压缩JS或者CSS-->
    <group id="yui">
		<!-- css -->
        <file type="css" src="reset.css" />
        <file type="css" src="fonts.css" />
		<!-- js -->
        <file type="js" src="yahoo.js" />
        <file type="js" src="dom.js" />
        <file type="js" src="event.js" />
    </group>

    <group id="test">
		<!--涉及到Javascript预编译,先不涉及
        <macro name="DEBUG" value="1" />
        -->
		<file type="js" src="test.js" />
    </group>

</smasher>

上面是smasher的配置文件,需要关注的就是,每一个group可以看做是一个操作单位,它拥有一个唯一的groupid,group中有许多file节点,每一个file节点要标明自己是css文件,或是js文件,上面的四种路径的配置要符合主机的配置,才能运行无误。

smasher_web.php

<?php

//设置自定义的错误处理函数
set_exception_handler('handle_exception');

require 'smasher.php';

$options = array(
    'conf'     => 'smasher.xml',//目标配置文件
    'type'     => NULL,//文件类型(从url获得)
    'group'    => NULL,//设置xml中的目标操作组ID
    'nominify' => false//不压缩
);

if (isset($_GET['conf'])) {
    $options['conf'] = $_GET['conf'];
}

if (!isset($_GET['type'])) {
    throw new Exception('No type specified');
} else {
    $options['type'] = $_GET['type'];
}

if (!isset($_GET['group'])) {
    throw new Exception('No group specified');
} else {
    $options['group'] = $_GET['group'];
}

$minify = !isset($_GET['nominify']);
//实例化Smasher
$smasher = new Smasher($options['conf']);

if ($options['type'] === 'css') {
    header('Content-Type: text/css');
    echo $smasher->build_css($options['group'], !$options['nominify']);
} else if ($options['type'] === 'js') {
    header('Content-Type: text/javascript');
    echo $smasher->build_js($options['group'], !$options['nominify']);
} else {
    throw new Exception('Invalid type: ' . $options['type']);
}

// -- Functions ---------------------------------------------------------------

function handle_exception(Exception $ex)
{
    header('HTTP/1.0 404 Not Found');
    header('Content-type: text/html');

    echo '<html>',
           '<head><title></title></head>',
           '<body>',
             '<h1>Smasher error</h1>',
             '<p>', htmlentities($ex->getMessage()), '</p>',
           '</body>',
         '</html>';

    exit;
}

上面说到了,smasher_web.php作为一个可以直接在浏览器中请求的入口文件,会接受两个参数:一个是type(取值为js/css),一个是group(取值要等于xml配置中的某一个groupid),否则就会报错。之后,smasher会读取响应group中的文件,合并,压缩,输出。我们的目的达到了。(可以下载源码,然后在本地请求:http://localhost/smasher/smasher_web.php?type=js&group=yui,就能看到实时压缩后的代码,它会将YUI group中的三个js文件合并压缩然后输出)

smasher.php的源码就不在页面上展现了,感兴趣的可以从上面给的两个链接中下载源码学习。

其实说到底,smasher最灵活的地方就在xml配置文件和入口文件上面,可以通过重写来为自己的项目量身定做一套更加合身的smasher套件。

(近期还会给smasher添加一个缓存机制,这样就不会一直麻烦服务器一直合来合去,压来压去的了,当然,可以配置它强制压缩(默认有缓存就不会再次压缩);还想给它再配上一个压缩引擎,默认的是YUI Compressor,再给它配上一个更霸道的Closure Compiler,就可以灵活选择压缩引擎了)

posted @ 2012-01-09 17:19  无墨来点睛  Views(1740)  Comments(1Edit  收藏  举报