為什麼要靜態化?
- 響應極快:無需 PHP 解析編譯,Web Server 直接發送文件,QPS 提升 10-100 倍。
- SEO 友好:靜態 URL 利於蜘蛛抓取、收錄與排名。
- 降低負載:減少數據庫查詢、模板渲染、內存佔用。
三種形態對比
| 類型 | 原理 | 優點 | 缺點 | 適用場景 |
| 純靜態 | 生成 .html 文件,Nginx/Apache 直接讀取 | 性能最強、最安全 | 更新麻煩、不適合高頻變動 | 文章詳情、商品頁、幫助中心 |
| 偽靜態 | Rewrite 將 /article/123.html 映射到 /article.php?id=123 | URL 美觀、SEO 同純靜態 | 仍經 PHP 處理、消耗資源 | 列表頁、搜索結果、個人中心 |
| 局部動態 (ESI/AJAX) | 靜態頁內嵌 JS 異步請求動態片段 | 兼顧性能與實時性 | 增加請求數、首屏延遲 | 評論、購物車、用戶狀態、推薦位 |
核心技術:Output Buffer 控制
// 開啟緩衝
ob_start();
// 業務邏輯、模板渲染、echo 輸出...
$content = ob_get_clean(); // 獲取並清空緩衝區
// 寫入靜態文件
file_put_contents('article_123.html', $content);
完整靜態化生成流程
<?php
$cacheFile = __DIR__ . '/cache/article_' . $id . '.html';
$cacheTime = 3600; // 1 小時
// 1. 緩存有效直接輸出
if (is_file($cacheFile) && (time() - filemtime($cacheFile) < $cacheTime)) {
readfile($cacheFile);
exit;
}
// 2. 緩存失效:重新生成
ob_start();
// ---- 業務邏輯區 ----
require_once 'db.php';
$stmt = $pdo->prepare('SELECT title, content FROM article WHERE id=?');
$stmt->execute([$id]);
$article = $stmt->fetch();
// ---- 模板渲染 ----
include 'template/article.php';
// -------------------
$html = ob_get_clean();
// 3. 寫入緩存(原子寫入防止讀到半寫文件)
$tmp = $cacheFile . '.tmp';
file_put_contents($tmp, $html);
rename($tmp, $cacheFile); // rename 在同分區是原子操作
// 4. 輸出
echo $html;
局部動態化:AJAX 方案
<!-- 靜態頁面 -->
<div id="comments">載入中...</div>
<script>
fetch('/api/comments?article_id=123')
.then(r => r.json())
.then(data => { document.getElementById('comments').innerHTML = render(data); });
</script>
偽靜態配置示例
Nginx
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# 具體規則
rewrite ^/article/(\d+)\.html$ /article.php?id=$1 last;
Apache (.htaccess)
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^article/(\d+)\.html$ article.php?id=$1 [L]
緩存失效策略
- 定時過期:
filemtime + TTL,簡單通用。
- 事件驅動:文章發布/編輯/刪除時
unlink($cacheFile)。
- 標籤/依賴緩存:記錄「文章ID→緩存文件」映射,批量清理關聯頁面。
- CDN 配合:靜態文件推送至 CDN,配置
Cache-Control,邊緣節點直接服務。
避坑指南
- 併發寫入:使用
flock 或臨時文件 rename 保證原子性。
- 用戶態區分:含登錄狀態的頁面不可全頁靜態,需 ESI/JS 動態填充。
- 目錄權限:緩存目錄需 Web Server 寫入權限,防止權限提升風險。
- 清理機制:定期
find /cache -mtime +30 -delete 防止磁盤爆滿。