前面在《浅谈网站的gzip输出优化》中,我介绍了gzip优化的好处,同时初步使用了gzip.php手工为javascript及css文件提供gzip压缩加速输出。
但当时的方法不好,有两个缺点:
1) 必须手工修改源文件,修改了index.php,element.php及插件中的很多js/css相关的文件里面的Javascript及css文件的载入路径,如,把src=xxx.js改为src=/gzip.php?url=/folder/js/xxx.js。不修改就没有gzip输出的功能。
2) 修改的路径必须是?url=/folder/等绝对引用的路径,相对路径不可以。这会导致文件中相关引用的失败(主要是指css文件中用url(xxx.gif))。所以当时模板文件中的css文件我本想用gzip输出,后来发现会导致css中的图片引用会失败,原因是经过gzip.php输出后,css文件的存在路径不是原路径,而是/gzip.php所在的根目录了。
针对这个问题,我在Bo-blog的BBS上看到了修改.htaccess文件后自动用URLRewrite匹配条件,进行gzip输出。
于是,我把原来的gzip.php改动一下,先将原来的接口一分为二,原来的url参数保留,以供将来万一需要手工输出gzip时需要。新增了一个$_ENV['REQUEST_URI']接口,这主要是为了匹配.htaccess的。.htaccess文件的修改处如下:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /blog/
# 下面这句表示针对/blog/目录下的所有*.css及*.js文件,转给/gzip.php处理,不需要提供参数url。
RewriteRule (.*.css$|.*.js$) /gzip.php [L]
#New rules since 2.1.0 beta 2
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [L]
...(下略)
当Apache服务器的URLRewrite模块将某个css文件传给gzip.php时,gzip.php能得到环境变量$_ENV['DOCUMENT_ROOT'],代表了网站根目录在硬盘上的绝对路径。而$_ENV['REQUEST_URI']则代表Apache服务器接收到的文件访问需求,比如模板文件的css路径的/blog/template/xxxx/style.css。这样,拼合得到的$file则代表了此文件在硬盘上的绝对路径。
然后,用is_file($file)判断是否存在此文件,如果不存在,则报错:invalid URI(无效路径)。
如果存在,继续判断是否为.css和.js结尾,如果不是,报错forbidden URI(禁止访问的路径),以免暴露php源代码等。事实上,Apache是默认支持将php及html页面自动以gzip方式压输出的,所以没必要对php及html文件进行gzip输出。
如果确实是.css和.js结尾,则判断应该输出什么Content-Type,然后输出合适的Content-Type。
再接下来就是以file_get_contents($file)输出文件内容了。
这个.htaccess这么修改还能进行cache,我正在研究。如果研究出来了,还可以将博客上的具体日志进行缓存,减少对MySQL的压力和依赖。



