對於「內容不常變、訪問量大」的頁面(如文章詳情、商品詳情),生成靜態 HTML 文件能將響應時間從 100ms+ 降至 5ms 以內。本文演示基於 Smartty 的 ob_start() 緩衝區捕獲 + 文件寫入 + 過期檢查 + 後台觸發再生成的完整方案。
include 靜態文件(繞過 PHP 解析、DB 查詢、模板渲染)ob_start() 開啟緩衝區 → 執行正常邏輯(查 DB、assign、display)→ ob_get_contents() 獲取輸出 → file_put_contents() 寫文件 → ob_end_flush() 輸出給用戶Header() 跳轉前台生成頁面 → 生成完成再跳回後台(用戶無感)<?php
$cache_file = "./cache/article_{$id}.html"; // 每篇文章獨立緩存文件
$cache_time = 3600; // 1 小時過期
// 1. 緩存有效性檢查
if (!file_exists($cache_file) || filemtime($cache_file) + $cache_time < time()) {
// 2. 開啟輸出緩衝區
ob_start();
// 3. 正常業務邏輯:查 DB、assign、display
$article = $db->getArticle($id);
$smarty->assign('article', $article);
$smarty->display('article_detail.tpl');
// 4. 捕獲緩衝區內容並寫入靜態文件
$html = ob_get_contents();
file_put_contents($cache_file, $html);
// 5. 輸出並關閉緩衝區
ob_end_flush();
} else {
// 6. 直接輸出靜態文件
include $cache_file;
}
?>
<?php
// admin/edit_article.php - 編輯保存後
if ($article_model->save($data)) {
// 跳轉前台生成靜態頁(用戶無感,瞬間完成)
header("Location: /article.php?id={$id}®enerate=1");
exit;
}
?>
<?php
// article.php 前台入口
if (isset($_GET['regenerate'])) {
// 強制重新生成:刪除舊緩存
$cache_file = "./cache/article_{$id}.html";
@unlink($cache_file);
// 正常走緩存未命中邏輯重新生成
}
?>
| 策略 | 實現要點 |
|---|---|
| 分佈式部署 | 靜態文件存 NFS/對象存儲,多 Web 節點共享 |
| CDN 加速 | 靜態文件推送 CDN,源站壓力為零 |
| 增量生成 | 僅更新受影響頁面(文章詳情、列表首頁、分類頁、標籤頁、Sitemap) |
| 併發安全 | flock() 或 Redis 分布式鎖防止並發重複生成 |
| 緩存預熱 | 發布後主動推送熱門頁面生成,避免首次訪問慢 |
| 版本管理 | 文件名含版本號 article_{id}_v{version}.html,滾動更新 |
| 維度 | Smarty caching | 手動 ob_start 靜態化 |
|---|---|---|
| 原理 | 模板輸出序列化存檔 | 捕獲最終 HTML 存檔 |
| 靈活度 | 支援 {insert} 局部動態 | 完全靜態,無動態能力 |
| 性能 | 需 PHP 解析 Smartty 緩存文件 | Web Server 直接發送文件,最快 |
| 部署 | 需 PHP 運行環境 | 純靜態,可離線部署 CDN |
手動 ob_start() 靜態化雖然失去 Smartty 內建緩存的局部動態能力,但換來的是極致的靜態文件性能與部署靈活性,是高流量內容型站點的首選方案。