簡體   English   中英

禁用mod_deflate和mod_gzip壓縮HTML,CSS和JS的最佳方法

[英]Best way to compress HTML, CSS & JS with mod_deflate and mod_gzip disabled

我在運行Apache 2的共享主機上有幾個站點。我想壓縮傳遞給瀏覽器的HTML,CSS和Javascript。 主機已禁用mod_deflate和mod_gzip,因此這些選項已經用完。 不過我可以使用PHP 5,所以我可以使用gzip組件。

我目前在.htaccess文件中放置以下內容:

php_value output_handler ob_gzhandler

但是,這只會壓縮HTML並省略CSS和JS。

是否有一種可靠的方法透明地壓縮CSS和JS的輸出而無需更改每一頁? 我搜索過谷歌並提供了一些解決方案,但我還沒有找到一個解決方案。 如果有人可以建議他們知道可以工作的解決方案,那將非常感激地收到。

注意, 關於Gzipping你的CSS的權威帖子 方法2看起來是一個很好的解決方案,但我無法讓它工作。 有沒有其他人成功使用這種方法?

對於延遲感到抱歉 - 這對我來說是忙碌的一周。

假設:

  • .htaccesscompress.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);

您當然應該在switch語句中添加更多mime類型。 我不想讓解決方案依賴於pecl fileinfo擴展或任何其他神奇的mime類型檢測庫 - 這是最簡單的方法。

至於保護腳本 - 我在文件系統中轉換為真實路徑,因此沒有黑客'../../../etc/passwd'或其他shellcript文件路徑不通過。

那就是

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

片段。 雖然我很確定除了$ basedir之外的其他層次結構中的大多數路徑都會在Apache到達腳本之前由Apache處理。

另外,我檢查結果路徑是否在腳本的目錄樹中。 像pilif建議的那樣添加緩存控制的標題,你應該有一個解決問題的工作方案。

我所做的:

  • 我將腳本分別放在css目錄中的js和樣式表中。
  • 在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> 
  • js目錄中的gzip-js.php如下所示:

     <?php header("Content-type: text/javascript; charset: UTF-8"); ?> 
  • ...和css目錄中的gzip-cs.php如下所示:

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

這可能不是最優雅的解決方案,但它肯定是一個簡單的解決方案,只需要很少的更改並且運行良好。

當用戶請求CSS和JavaScript文件時,您可以提前gzip,而不是動態gzip。 只要Apache使用正確的標題為他們服務,你就是金色的。

例如,在Mac OS X上,在命令行上壓縮文件就像以下一樣簡單:

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

可能不是那種適合你的工作流程。

你可以試試mod_rewrite的運氣。

創建一個腳本,該腳本將本地靜態文件名作為輸入,例如$_SERVER['QUERY_STRING']並以壓縮形式輸出。 許多提供程序不允許使用.htaccess文件配置mod_rewrite或將其完全禁用。

如果您以前沒有使用過重寫 ,我推薦一個很好的初學者指南,就像這個一樣。 這樣,您可以使apache將所有靜態文件請求重定向到php腳本。 例如,style.css將被重定向到compress.php?style.css

一如既往地對您接受的輸入非常謹慎,或者您手上有XSS漏洞!

無論你做什么,都要小心客戶端的緩存:

瀏覽器會嘗試各種技巧來最小化帶寬,HTTP協議中有很多方法可以做到這一點,所有這些都由apache處理 - 如果你只是服務本地文件。

如果你不是,那么這是你的責任

至少看一下所有當前瀏覽器都支持的ETag和If-Modified-Since機制,它們似乎是查詢服務器獲取更新內容的最強大的方法。

使用If-Modified-Since-Header向瀏覽器提供CSS文件的一種可能方法是這樣的(關閉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-Header。 客戶端將使用If-None-Match標頭發送回來,允許服務器不僅決定上次修改的日期,還決定內容本身。

這只是讓代碼更復雜,所以我把它留了出來。 FF,IE和Opera(也可能是Safari)都會在收到帶有Last-Modified標頭的內容時發送If-Modified-Since標頭,所以這樣可以正常工作。

還要記住,某些版本的IE(或它使用的JScript-Runtime) 仍然存在GZIP傳輸內容的問題。

哦。 我知道這不是問題的一部分,但Acrobat在某些版本中也是如此。 我在使用gzip傳輸編碼提供PDF時遇到了白屏的案例和案例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM