![](/img/trans.png)
[英]gzip without mod_gzip nor mod_deflate and pre gzipped files
[英]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看起來是一個很好的解決方案,但我無法讓它工作。 有沒有其他人成功使用這種方法?
對於延遲感到抱歉 - 這對我來說是忙碌的一周。
假設:
.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);
您當然應該在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.