2008-09-07 74 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 

可能不是那種工作流程,對你雖然工作。