首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP Gzip 壓縮合併輸出 JS/CSS 檔案

     編輯:PHP 綜合知識

減少 HTTP 請求數與傳輸體積是前端效能優化核心。本文提供一個 combine.php 進入點,支援:多檔案合併、Gzip/Deflate 壓縮、Etag/304 快取、快取檔案落地、User-Agent 相容性處理 (IE6 降級)、檔案型別驗證、基礎路徑配置。

核心邏輯流程

  1. 解析參數:t=j|c (js/css)、b=basePath、fs=file1,file2 (無副檔名)。
  2. 構建絕對路徑,驗證副檔名、路徑穿越、檔案存在性。
  3. 計算所有檔案最大 mtime 生成 Etag,支援 If-None-Match 返回 304。
  4. 檢查 Accept-Encoding 決定 gzip/deflate/none,IE6 降級不壓縮。
  5. 讀取快取檔 (cache-{etag}.js.gz) 存在則直接輸出。
  6. 否則合併內容、壓縮、寫入快取、輸出。

關鍵代碼片段

// 參數解析與安全檢查
$type = $_GET['t'] ?? ''; // j 或 c
$base = $_GET['b'] ? $_SERVER['DOCUMENT_ROOT'] . '/' . str_replace('.', '/', $_GET['b']) : $_SERVER['DOCUMENT_ROOT'];
$fs   = $_GET['fs'] ?? '';
$ext  = $type === 'j' ? '.js' : '.css';
$files = array_map(fn($f) => $base . '/' . $f . $ext, explode(',', $fs));

// 驗證每個檔案
foreach ($files as $f) {
    if (!is_file($f) || strpos(realpath($f), realpath($base)) !== 0) {
        http_response_code(404); exit('Not Found');
    }
}

// Etag 與 304
$mtime = max(array_map('filemtime', $files));
$etag = $mtime . '-' . md5($fs);
header("Etag: \"$etag\"");
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == "\"$etag\"") {
    header('Content-Type: text/' . ($type === 'j' ? 'javascript' : 'css'));
    header('Content-Length: 0');
    http_response_code(304); exit;
}

// 壓縮輸出
$content = implode("\n\n", array_map('file_get_contents', $files));
$encoding = 'none';
if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) $encoding = 'gzip';
elseif (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') !== false) $encoding = 'deflate';

if ($encoding !== 'none') {
    $content = gzencode($content, 9, $encoding === 'gzip' ? FORCE_GZIP : FORCE_DEFLATE);
    header("Content-Encoding: $encoding");
}
header('Content-Type: text/' . ($type === 'j' ? 'javascript' : 'css'));
header('Content-Length: ' . strlen($content));
echo $content;

// 快取落地 (需可寫目錄)
$cacheDir = $_SERVER['DOCUMENT_ROOT'] . '/public/cache';
$cacheFile = "$cacheDir/cache-$etag.$ext" . ($encoding !== 'none' ? ".$encoding" : '');
@file_put_contents($cacheFile, $content);

HTML 引用方式

<!-- 合併 jquery.js + common.js -->
<script src="combine.php?t=j&fs=lib.jquery,common"></script>

<!-- 指定基礎路徑 public/js -->
<script src="combine.php?t=j&b=public.js&fs=lib.jquery,common"></script>

<!-- CSS 合併 -->
<link rel="stylesheet" href="combine.php?t=c&fs=reset,layout,theme">

現代替代方案

  • 建構時期合併:Webpack/Vite/Rollup/esbuild 打包階段合併、壓縮、Tree-shaking、Hash 命名、Code Splitting,無需運行時 PHP。
  • HTTP/2 + 多路複用:啟用 HTTP/2 後,多檔案並行傳輸無阻塞,合併優先級降低,但壓縮 (Gzip/Brotli) 仍需啟用。
  • CDN 邊緣壓縮:Cloudflare/阿里雲 CDN 可自動 Brotli/Gzip 壓縮並快取,源站無需處理。

本方案適用於無建構流程的傳統 PHP 專案快速優化。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved