2008-09-07 73 views
8

我在运行Apache 2的共享主机上有几个站点。我想压缩传递给浏览器的HTML,CSS和Javascript。主机已禁用mod_deflate和mod_gzip,因此这些选项已禁用。尽管如此,我也可以使用PHP 5,所以我可以使用它的gzip组件。禁用mod_deflate和mod_gzip禁用压缩HTML,CSS和JS的最佳方法

我目前把我的.htaccess文件如下:

php_value output_handler ob_gzhandler

但是,这仅压缩HTML和离开了CSS和JS。

有没有一种可靠的方法来透明地压缩CSS和JS的输出而不必更改每个页面?我搜索了Google,并提供了一些解决方案,但我还没有找到一个工作。如果任何人都可以提出他们知道的解决方案,那将非常感激。

注意,方法2The Definitive Post on Gzipping your CSS看起来像一个很好的解决方案,但我无法得到它的工作。有没有其他人使用这种方法成功?

+0

只是好奇 - 为什么主机公司禁用mod_deflate和mod_gzip ?!其实它*他们*的兴趣,让他们打开! – scunliffe 2010-11-05 10:38:16

回答

1

你可以用mod_rewrite来试试你的运气。

创建一个脚本,将本地静态文件名作为输入,例如通过$_SERVER['QUERY_STRING']并以压缩格式输出。许多提供商不允许配置mod_rewrite.htaccess文件,或者让它完全禁用。

如果你以前没有用改写,我推荐一个好的初学者指南,比如可能是this one。 这样你可以让Apache将一个静态文件的所有请求重定向到一个php脚本。 style.css将被重定向到compress.php?style.css

由于始终你接受输入极其谨慎或者你有一个XSS利用在你的手中!

+0

@macbirdie,非常感谢这个建议。你能提供或链接到这种方法的任何例子吗?我也有兴趣听到一些关于保护这种脚本的一般技巧。 – 2008-09-07 17:20:18

4

我做什么:

  • 我分别放在一个js脚本和样式在css目录。
  • 在Apache的配置,我想补充的指令,像这样:

    <Directory /data/www/path/to/some/site/js/> 
        AddHandler application/x-httpd-php .js 
        php_value auto_prepend_file gzip-js.php 
        php_flag zlib.output_compression On 
    </Directory> 
    <Directory /data/www/path/to/some/site/css/> 
        AddHandler application/x-httpd-php .css 
        php_value auto_prepend_file gzip-css.php 
        php_flag zlib.output_compression On 
    </Directory> 
    
  • 用gzip js.php在js目录如下:

    <?php 
        header("Content-type: text/javascript; charset: UTF-8"); 
    ?> 
    
  • ...和gzip-CS。PHP在css目录如下:

    <?php 
        header("Content-type: text/css; charset: UTF-8"); 
    ?> 
    

这可能不是最完美的解决方案,但它肯定是一个简单的,需要一些改变和行之有效的。

+0

我刚刚尝试过这一点,但无法让它工作。当我按照建议添加指令时,出现内部服务器错误。 – 2008-09-07 17:38:02

1

你做什么都,要小心在客户端缓存:

浏览器完成所有类型的招数,试图尽量减少带宽和有在HTTP协议中许多方法可以做到这一点,所有的由apache处理 - 如果你只是提供本地文件。

如果您不是,那么这是您的责任

看看至少在所有当前浏览器支持的ETag和If-Modified-Since机制,似乎是查询服务器更新内容的最可靠方法。

一种可能的方式来服务于一个CSS文件,使用浏览器IF-Modified-Since的标头是这样的(空的头关闭任何非缓存头的PHP将每默认):

$p = 'path/to/css/file' 
$i = stat($p); 
if ($_SERVER['HTTP_IF_MODIFIED_SINCE']){ 
    $imd = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']); 
    if (($imd > 0) && ($imd >= $i['mtime'])){ 
     header('HTTP/1.0 304 Not Modified'); 
     header('Expires:'); 
     header('Cache-Control:'); 
     header('Last-Modified: '.date('r', $i['mtime'])); 
     exit; 
    } 
} 
header('Last-Modified: '.date('r', $i['mtime'])); 
header('Content-Type: text/css'); 
header('Content-Length: '.filesize($p)); 
header('Cache-Control:'); 
header('Pragma:'); 
header('Expires:'); 
readfile($p); 

代码将使用浏览器发送的if-modified-since-header来检查服务器上的实际文件自浏览器发出日期以来是否发生了更改。如果是,则发送该文件,否则,将返回304 Not Modified,并且浏览器不必重新下载整个内容(如果足够智能,它也会将解析的CSS保存在内存中)。

还有一种机制涉及服务器为每个内容发送一个唯一的ETag标题。客户端将使用If-None-Match标头发回,以便服务器不仅可以决定上次修改的日期,还可以决定内容本身。

虽然这只是使代码更复杂,所以我已经将它遗漏了。 FF,IE和Opera(可能也是Safari)都会在接收到带有Last-Modified标头的内容时发送If-Modified-Since标头,所以这可以正常工作。

也请记住,某些版本的IE(或其使用的JScript-Runtime)仍然在使用GZIP传输的内容时遇到问题。

哦。我知道这不是问题的一部分,但Acrobat在某些版本中也是如此。使用gzip传输编码提供PDF时,我遇到了白屏案例和案例。

+0

你有使用GZIP内容的IE/JScript问题的src/url吗?我记得IE的老版本(例如在IE6之前)不支持gzip,但这只意味着它们获得了较慢的未压缩内容。如果IE浏览器仍然存在问题,我肯定想知道! – scunliffe 2010-11-05 10:42:04

+0

我曾经遇到IE无法解析使用gzip传输的外部JS文件的情况。 Acrobat插件的某些版本(甚至是当前版本)也不能处理压缩,尽管他们声称他们可以。 – pilif 2010-11-05 12:37:08

7

抱歉,延迟 - 对我来说这是忙碌的一周。

假设:

  • .htaccess是在同一个文件compress.php
  • 静态文件被压缩在static子目录

我开始在设置以下指令我的解决办法。htaccess的:

RewriteEngine on 
RewriteRule ^static/.+\.(js|ico|gif|jpg|jpeg|png|css|swf)$ compress.php [NC] 

它要求你的供应商允许你覆盖.htaccess文件mod_rewrite选项。 然后compress.php文件本身可以是这样的:

<?php 

$basedir = realpath(dirname($_SERVER['SCRIPT_FILENAME'])); 
$file = realpath($basedir . $_SERVER["REQUEST_URI"]); 

if(!file_exists($file) && strpos($file, $basedir) === 0) { 
    header("HTTP/1.0 404 Not Found"); 
    print "File does not exist."; 
    exit(); 
} 

$components = split('\.', basename($file)); 
$extension = strtolower(array_pop($components)); 

switch($extension) 
{ 
    case 'css': 
     $mime = "text/css"; 
     break; 
    default: 
     $mime = "text/plain"; 
} 

header("Content-Type: " . $mime); 
readfile($file); 

你当然应该增加更多的MIME类型switch语句。我不想让解决方案依赖于pecl fileinfo扩展或任何其他神奇的mime类型检测库 - 这是最简单的方法。

至于保护脚本 - 我在文件系统中做了一个真正的路径翻译,所以没有黑客'../../../etc/passwd'或其他shellcript文件路径不经过。

这就是

$basedir = realpath(dirname($_SERVER['SCRIPT_FILENAME'])); 
$file = realpath($basedir . $_SERVER["REQUEST_URI"]); 

片段。虽然我非常确定,在$ baseir之外的其他层次结构中,大部分路径在Apache到达脚本之前都将由Apache处理。

另外我检查路径是否在脚本的目录树内。 按照pilif的建议添加缓存控制头文件,并且应该为您的问题提供工作解决方案。

1

当用户请求CSS和JavaScript文件时,您可以提前gzip,而不是在用户请求CSS和JavaScript文件时进行gzip。只要Apache为他们提供正确的头文件,你就是金。

例如,在Mac OS X,在命令行中使用gzip压缩文件一样简单:

gzip -c styles.css > styles-gzip.css 

可能不是那种工作流程,对你虽然工作。