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

PHP CSS 靜態資源版本控制類別:自動為圖片 URL 附加時間戳防快取

     編輯:PHP 相關知識

前端效能優化中,CSS 內引用的圖片、字型等靜態資源需長期快取(`Cache-Control: max-age=31536000`),但更新時必須強制瀏覽器下載新版。常見做法是在 URL 後附加版本參數(如 `bg.png?v=202401151200`)。本文實作 CSSUpdate 類別,掃描 CSS 模板目錄,自動為指定副檔名的 URL 附加時間戳,輸出至正式目錄,實現零手工維護的版本控制。

核心功能

  • 遞迴掃描 CSS 模板目錄(可選是否掃描子目錄)。
  • 針對指定副檔名(`.png`、`.jpg`、`.gif`、`.woff` 等)的 `url()` 參考附加時間戳。
  • 保持目錄結構輸出至目標目錄,自動建立子目錄。
  • 記錄轉換檔案數與日誌輸出。

類別程式碼

<?php
class CSSUpdate {
    private $csstmpl_path = null;
    private $css_path = null;
    private $replacetags = [];
    private $search_child = false;
    private $convert_num = 0;
    private $is_ready = 0;

    public function __construct($csstmpl_path, $css_path, array $replacetags = [], $search_child = false) {
        if (!is_dir($csstmpl_path) || !is_dir($css_path) || empty($replacetags)) {
            $this->is_ready = 0;
        } else {
            $this->csstmpl_path = $csstmpl_path;
            $this->css_path = $css_path;
            $this->replacetags = $replacetags;
            $this->search_child = $search_child;
            $this->is_ready = 1;
        }
    }

    public function update() {
        if ($this->is_ready == 0) {
            $this->response('csstmpl or csspath or replacetags error');
            return;
        }
        $this->traversing($this->csstmpl_path);
        $this->response('convert num: ' . $this->convert_num);
    }

    private function traversing($path) {
        $handle = opendir($path);
        while (($file = readdir($handle)) !== false) {
            if ($file === '.' || $file === '..') continue;
            $curfile = $path . '/' . $file;
            if (is_dir($curfile)) {
                if ($this->search_child) {
                    $this->traversing($curfile);
                }
            } elseif ($this->checkExt($curfile)) {
                $dfile = str_replace($this->csstmpl_path, $this->css_path, $curfile);
                $this->create($curfile, $dfile);
                $this->response($curfile . ' convert to ' . $dfile . ' success');
                $this->convert_num++;
            }
        }
        closedir($handle);
    }

    private function checkExt($file) {
        $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
        return $ext === 'css';
    }

    private function create($tmplfile, $dfile) {
        $content = file_get_contents($tmplfile);
        foreach ($this->replacetags as $tag) {
            // 替換 url(...) 內的指定副檔名
            $content = str_replace($tag, $tag . '?' . date('YmdHis'), $content);
        }
        $dir = dirname($dfile);
        if (!is_dir($dir)) mkdir($dir, 0755, true);
        file_put_contents($dfile, $content);
    }

    private function response($msg) {
        echo $msg . "
\n"; } } ?>

使用範例

<?php
require 'CSSUpdate.class.php';

define('ROOT_PATH', dirname(__FILE__));
$csstmpl_path = ROOT_PATH . '/csstmpl';  // 模板目錄(開發維護)
$css_path = ROOT_PATH . '/css';           // 正式目錄(Web 存取)
$replacetags = ['.png', '.jpg', '.gif', '.woff', '.woff2', '.ttf', '.eot', '.svg'];

$css = new CSSUpdate($csstmpl_path, $css_path, $replacetags, true); // true=掃描子目錄
$css->update();

運作示意

進階改良建議

  • MD5 內容雜湊版本:替換時間戳為 `md5_file($img_path)` 前 8 碼,內容未變則版本不變,最大化快取效益。
    $hash = substr(md5_file($real_img_path), 0, 8);
  • 支援 `url()` 變體:單引號、雙引號、無引號、含空白:url(image.png)、url("image.png")、url('image.png')。使用正則替換:
    preg_replace('/url\([\s"\']*([^)\s"\']+' . preg_quote($tag) . ')[\s"\']*\)/', 'url($1?' . $version . ')', $content)
  • 整合建置流程:納入 Composer scripts、Gulp/Webpack、CI/CD 管線,部署時自動執行。
  • 多環境區隔:開發環境不附加版本(便於除錯),正式環境才執行版本控制。
  • Manifest 對應表:生成 `rev-manifest.json` 供前端框架(Laravel Mix、Webpack)參考。

部署架構圖

專案根目錄
├── csstmpl/          # 開發維護的 CSS 模板(無版本參數)
│   ├── style.css
│   └── module/
│       └── button.css
├── css/              # 正式環境 Web 根目錄下的 CSS(含版本參數)
│   ├── style.css
│   └── module/
│       └── button.css
├── img/              # 圖片資源
└── deploy.php        # 部署腳本,呼叫 CSSUpdate::update()

注意事項

  • 時間戳版本每次部署皆不同,會導致所有資源重新下載;MD5 版本僅更新變動檔案,建議生產環境採用。
  • CSS 中使用絕對路徑 `/img/logo.png` 時,需計算實體路徑對應;相對路徑 `../img/logo.png` 需根據 CSS 檔位置解析。
  • 若使用 CSS 預處理器(Less/Sass),建議在編譯階段注入版本,而非編譯後字串替換。
  • 字型檔(woff2 等)同樣需版本控制,避免字型更新不生效。

CSSUpdate 以簡單的字串替換實現靜態資源版本控制自動化,適合中小專案快速導入;大型專案建議結合建置工具(Webpack/Vite/Laravel Mix)實現基於內容雜湊的精準版本管理,達成最佳快取策略。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
階段內容
模板檔 csstmpl/style.css.logo { background: url(../img/logo.png); }
執行 update()掃描到 `.png`,替換為 `.png?20240115120000`
輸出檔 css/style.css.logo { background: url(../img/logo.png?20240115120000); }