请求中的“开源节流”--用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,就可以灵活选择压缩引擎了)