本文主要如何使用GruntJS来作简单的前端性能优化的自动化处理,我写了一个完整的例子放在Github上,可以参考一下。关于Yahoo的前端优化规则请参考:Best Practices for Speeding Up Your Web Site
前端性能主要有图片的压缩,JS和CSS的合并、压缩,对所有静态文件的文件根据其内容加上hash,然后把CSS、HTML等文件中对所有的静态文件名替换成加上hash的新文件名。对所有的静态内容的路径上加上CDN的URL,最后将所有的静态文件上传到七牛CDN上去。下面我们按功能来说一下。
许多图片尤其是png图片有时候含有大量无意义的填充,增加图片的大小。我们可以通过contrib-imagemin对所有的图片进行压缩优化,从而减小图片的大小。根据我们使用经验来看,一般可以压缩5%到10%左右。
合并JS和CSS可以大量的减少HTTP请求,达到优化前端性能的目的。同时CSS和JS文件是静态文件,可以压缩到非常小的大小。GruntJS官方提供了contrib-concat,contrib-cssmin,contrib-uglify等对应的插件来做对应的事情。我们这里因为要文件名的替换,使用了usemin插件,它会自动调用上述几个插件的,所以在我们的Gruntfile.js里并没有这3个插件的配置信息,而只是在task列表里调用了这几个插件。具体请参考:usemin。
为了最大程度的提高浏览器的加载速度,最好的方法是让浏览器将所有的静态文件都缓存在客户端,这里的缓存是指expire和cache-control的max-age,而不是Last-Modified,因为使用Last-Modified 和 If-Modified-Since还是会发出请求的,只是没有更新就返回304状态码而max-age则是不会发出请求的,而是直接使用本地的缓存。使用缓存的面临的一个比较在的问题是如果文件有更新如果清理缓存或者如果让用户下载最新的文件。一种做法是静态文件加上版本号,例如 style.css?v=1.1。这种做法可以达到清除缓存的目的,但是维护起来相对麻烦,比较版本号没有办法自动化,没有办法判断文件是否有更新。另外一种做法是对文件内容进行hash,然后将hash值加入到文件名中,例如style.abd1q2.css。这样就很容易进行自动化处理,我们这里使用了yeoman开发的filerev插件,它可以对文件内容进行MD5运算,然后将运算后的hash加到文件名中去,这样就很容易判断文件是否被修改,同时它可以和usemin进行完美的结合起来。
对CSS和JS进行压缩合并以及对所有静态资源进行filerev处理后,原来HTML、CSS、JS等静态资源的引用文件名就需要替换成新的文件名了。例如HTML中对CSS和JS的引用,CSS中对图片的引用。我们使用了Yeoman开发的usemin进行替换。它的工作原理是,对需要处理的文件中的静态资源,在指定的文件夹查找经过filerev处理过的对应文件,如果找到则替换成相应的文件。例如,我们在代码中对CSS的引用代码如下:<link type="text/css" href="style.css">,usemin会在指定的文件夹下面寻找类似style.abd1q2.css的文件,如果找到则会把我们的CSS引用代码自动替换成:<link type="text/css" href="style.abd1q2.css">。具体请参考:usemin。
开发过程中对所有静态资源的引用都是指向项目自己的domain。如果要使用CDN,则需要将所有静态资源的引用Domain指向CDN的domain。这里使用GruntJS插件cdn来对所有静态资源进行全局替换。
当以上步骤完成后就可以将所有的静态文件上传到CDN了。七牛官方提供了NodeJS的SDK,但是貌似比较难用。我们例子里使用了第三方开发的NodeJS模块qn,非常简单,详见:qn。我的做法是将图片和CSS/JS所在的目录分别遍历上传,对图片和CSS/JS分别加上不同的前缀。因为七牛是不提供在里面建文件夹的。详见cdn.js文件。