GZIP 在各种网站上的万能应用 (以WordPress举例)

July 12, 2009 by SLJ | Category:Apache, PHP | 1 Comment Font size: AA   AA

转载请注明来源:关于 GZIP 在各种网站上的万能应用 (以WordPress举例) | 奇亚

每次更新WordPress是一个痛苦的过程,会把原先我对奇亚的优化全部覆盖掉。比如GZIP这一方面。趁这个机会我总结一下关于 GZIP 在各种网站上的万能应用

对于一些网速比较慢的服务器来说,在页面上启用GZIP对访问者的下载效率是有很大好处的。
下面是一个万能方法,无论你有没有PHP或者Apache的知识,照着做就对了。

CSS和JS方面

我们使用网络上一个流行的脚本Gzip.php来处理,按照代码,.htaccess将检查用户的请求,发现扩展名以js或者css结尾的,首先去找是否在其目录下有.js.gz文件,如果没有的话就运用gzip.php来生成它。(例,用户请求/js/jQuery.js,会先自动找/js/jQuery.js.gz,如果没有发现调用gzip.php来生成它)
这个脚本的好处在于,由于js和css一般不是动态的,所以通过一次性生成,而每次请求时不必再次压缩,提高了效率。
但要注意,若你的js文件或者css文件有更新的话,需要把其目录下已经生成的.js.gz和.css.gz删除,否则浏览者访问的仍然是旧版本的文件。

1、 修改根目录的.htaccess

<Files *.js.gz>
AddEncoding gzip .js
ForceType application/x-javascript
</Files>
<Files *.css.gz>
AddEncoding gzip .css
ForceType text/css
</Files>

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule ^(.*).css $1.css.gz [L,QSA]

RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule ^(.*).js $1.js.gz [L,QSA]

RewriteRule (.*.css$|.*.js$) gzip.php?$1 [L]
</IfModule>

这里就不注解了,如果想知道上面是什么内容,可以看看我以前发过的一篇Apache Rewrite 规则详解

2、上传gzip.php到根目录
PHP代码:


define('ABSPATH', dirname(__FILE__).'/');
$cache = true;//Gzip压缩开关
$cachedir = 'wp-cache/';//存放gz文件的目录,确保可写
$gzip = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
$deflate = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate');
$encoding = $gzip ? 'gzip' : ($deflate ? 'deflate' : 'none');
if(!isset($_SERVER['QUERY_STRING'])) exit();
$key=array_shift(explode('?', $_SERVER['QUERY_STRING']));
$key=str_replace('../','',$key);
$filename=ABSPATH.$key;
$symbol='^';
$rel_path=str_replace(ABSPATH,'',dirname($filename));
$namespace=str_replace('/',$symbol,$rel_path);
//$cache_filename=ABSPATH.$cachedir.$namespace.$symbol.basename($filename).'.gz';//生成gz文件路径
$cache_filename=$filename.'.gz';//生成gz文件路径
$type="Content-type: text/html"; //默认的类型信息
$ext = array_pop(explode('.', $filename));//根据后缀判断文件类型信息
       switch ($ext){
              case 'css':
               $type="Content-type: text/css";
               break;
              case 'js':
               $type="Content-type: text/javascript";
               break;
              default:
               exit();
       }
if($cache){
       if(file_exists($cache_filename)){//假如存在gz文件
              $mtime = filemtime($cache_filename);
              $gmt_mtime = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';
              if( (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
                 array_shift(explode(';', $_SERVER['HTTP_IF_MODIFIED_SINCE'])) ==  $gmt_mtime)
                     ){
                     // 浏览器cache中的文件修改日期是否一致,将返回304
                     header ("HTTP/1.1 304 Not Modified");
                     header("Expires: ");
                     header("Cache-Control: ");
                     header("Pragma: ");
                     header($type);
                     header("Tips: Cache Not Modified (Gzip)");
                     header ('Content-Length: 0');
              }else{
                     //读取gz文件输出
                     $content = file_get_contents($cache_filename);
                     header("Last-Modified:" . $gmt_mtime);
                     header("Expires: ");
                     header("Cache-Control: ");
                     header("Pragma: ");
                     header($type);
                     header("Tips: Normal Respond (Gzip)");
                     header("Content-Encoding: gzip");
                     echo $content;
              }
       }else if(file_exists($filename)){ //没有对应的gz文件
              $mtime = mktime();
              $gmt_mtime = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';
              $content = file_get_contents($filename);//读取文件
              $content = gzencode($content, 9, $gzip ? FORCE_GZIP : FORCE_DEFLATE);//压缩文件内容
              header("Last-Modified:" . $gmt_mtime);
              header("Expires: ");
              header("Cache-Control: ");
              header("Pragma: ");
              header($type);
              header("Tips: Build Gzip File (Gzip)");
              header ("Content-Encoding: " . $encoding);
        header ('Content-Length: ' . strlen($content));
              echo $content;
              if ($fp = fopen($cache_filename, 'w')) {//写入gz文件,供下次使用
                fwrite($fp, $content);
                fclose($fp);
            }
       }else{
              header("HTTP/1.0 404 Not Found");
       }
}else{ //处理不使用Gzip模式下的输出。原理基本同上
       if(file_exists($filename)){
              $mtime = filemtime($filename);
              $gmt_mtime = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';
              if( (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
              array_shift(explode(';', $_SERVER['HTTP_IF_MODIFIED_SINCE'])) ==  $gmt_mtime)
              ){
              header ("HTTP/1.1 304 Not Modified");
              header("Expires: ");
              header("Cache-Control: ");
              header("Pragma: ");
              header($type);
              header("Tips: Cache Not Modified");
              header ('Content-Length: 0');
       }else{
              header("Last-Modified:" . $gmt_mtime);
              header("Expires: ");
              header("Cache-Control: ");
              header("Pragma: ");
              header($type);
              header("Tips: Normal Respond");
              $content = readfile($filename);
              echo $content;
              }
       }else{
              header("HTTP/1.0 404 Not Found");
       }
}

3,如果需要压缩页面,可以在头部加上(一定是php文件)

if(ereg('gzip',$_SERVER['HTTP_ACCEPT_ENCODING'])){ //判断浏览器是否支持Gizp
ob_start('ob_gzhandler'); //打开Gzip压缩
}

==========================================================

下面是以WordPress为实例说明一下应用:

CSS/JS方面:
使用上面的通用例子即可,即:
1、修改.htaccess,

<files *.js.gz>
AddEncoding gzip .js
ForceType application/x-javascript
</files>
<files *.css.gz>
AddEncoding gzip .css
ForceType text/css
</files>

<ifmodule mod_rewrite.c>
RewriteEngine On
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule ^(.*).css $1.css.gz [L,QSA]

RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule ^(.*).js $1.js.gz [L,QSA]

RewriteRule (.*.css$|.*.js$) gzip.php?$1 [L]
</ifmodule>

2、增加gzip.php

页面方面:
在根目录中找到 wp-load.php,加上代码:

if(ereg('gzip',$_SERVER['HTTP_ACCEPT_ENCODING'])){ //判断浏览器是否支持Gizp
if(substr($_SERVER['REQUEST_URI'],0,10)!='/wp-content/uploads/') //排除不需要Gzip压缩的目录
ob_start('ob_gzhandler'); //打开Gzip压缩
}

Ps:很多人的博文里是说是在index.php里加,这样一来,后台页面是不压缩的,而加在wp-load.php就是全站压缩了。

其他方法:
方法1:

如果服务器支持.htaccess文件,那么在wordpress根目录的.htaccess增加以下代码,如果没有.htaccess则新建后增加代码。增加完成后上传到wordpress根目录后即可。

php_value output_handler ob_gzhandler

方法2: 非常推荐此方法,但是需要服务器支持改写php.ini

通过php.ini 启用Gzip, 添加如下代码来开启gzip。
output_buffering = Off
output_handler =
zlib.output_compression = On
zlib.output_compression_level = 6
;zlib.output_compression_level = 一个1—9的值,1的压缩比率最低, 建议取大于6

需要注意的是如果在.htaccess文件中禁止了gzip功能的话,那在php.ini文件中开启后需在.htaccess文件中开启,否则无效。
开启wordpress的gzip功能后,服务器将在页面传输前将页面压缩后传送,可以有效减少服务器的带宽使用,也可以加速页面下载。

Other Posts / 其他文章



1 Comment

我要评论
  • 小V July 14, 2009

    呵呵 ,wp最近更新确实有点快了。 学习一下你的gzip技巧

Leave a Comment:

*
*
*
*
↑ Top