大型網站優化四大支柱:SEO、頁面靜態化、記憶體快取、叢集架構。本文聚焦頁面靜態化,從原理到代碼落地,解決「動態查詢慢、SEO 不友好、資料庫壓力大」三大痛點。
| 類型 | URL 特徵 | 本質 |
|---|---|---|
| 靜態頁 | `/article/123.html` | 純 HTML 檔案,Web 伺服器直接發送,無 PHP 解析 |
| 動態頁 | `/article.php?id=123` | 每請求執行 PHP、查詢 DB、組裝 HTML |
| 偽靜態 | `/article/123.html` (實際 `/article.php?id=123`) | URL 重寫掩蓋動態腳本,SEO 友好但仍消耗 PHP 資源 |
真靜態化:將動態頁「預渲染」生成實體 HTML 檔案,後續請求直接由 Nginx/Apache 靜態服務,零 PHP 開銷。
| 維度 | 全頁靜態化 | 局部靜態化 (AJAX/ESI) |
|---|---|---|
| 實現難度 | 低 | 中(需切分片段、處理快取失效) |
| 適用場景 | 內容頁、列表頁、首頁 | 個性化區塊(用戶資訊、購物車、推薦) |
| 更新策略 | 發布/編輯時重新生成 | 片段級快取過期/主動刷新 |
// 基礎流程
ob_start(); // 開啟緩衝,所有 echo 輸出導向記憶體
// ... 執行業務邏輯、include 模板、echo 內容 ...
$html = ob_get_contents(); // 取得緩衝內容
ob_end_clean(); // 關閉並丟棄緩衝(或 ob_end_flush() 輸出給瀏覽器)
// 寫入靜態檔案
file_put_contents('/path/to/static/article_123.html', $html);
OB 緩衝層級關係: PHP OB → PHP 程式緩衝 → Web Server 緩衝 → 瀏覽器緩衝。`ob_flush()` 推送到程式緩衝,`flush()` 推送到 Web Server/瀏覽器。
<html><head><title>{TITLE}</title></head><body>
<h1>{TITLE}</h1>
<div class="meta">發布:{DATE} 作者:{AUTHOR}</div>
<div class="content">{CONTENT}</div>
</body></html>
<?php
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
if (!$id) exit('Invalid ID');
// 1. 查詢資料 (PDO 範例)
$pdo = new PDO('mysql:host=127.0.0.1;dbname=news;charset=utf8mb4', 'user', 'pass');
$stmt = $pdo->prepare('SELECT title, author, content, created_at FROM articles WHERE id = ?');
$stmt->execute([$id]);
$article = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$article) exit('Article not found');
// 2. 讀取模板
$tpl = file_get_contents(__DIR__ . '/template_news.html');
// 3. 佔位符替換
$replacements = [
'{TITLE}' => htmlspecialchars($article['title']),
'{AUTHOR}' => htmlspecialchars($article['author']),
'{DATE}' => date('Y-m-d H:i', strtotime($article['created_at'])),
'{CONTENT}' => $article['content'], // 假設內容已過濾或為可信 HTML
];
$html = strtr($tpl, $replacements);
// 4. 寫入靜態檔 (目錄需可寫)
$staticDir = __DIR__ . '/static';
if (!is_dir($staticDir)) mkdir($staticDir, 0755, true);
$file = $staticDir . '/article_' . $id . '.html';
file_put_contents($file, $html);
echo "Generated: $file";
// 可選:直接輸出給瀏覽器
// header('Content-Type: text/html; charset=utf-8');
// echo $html;
?>
大量生成時,採用 AJAX 輪詢回報進度:
<button onclick="startGen()">開始生成</button>
<div id="progress"></div>
<script src="jquery.min.js"></script>
<script>
function startGen() {
$.get('batch_gen.php?action=start', function(res) {
var data = JSON.parse(res);
pollProgress(data.all, 0);
});
}
function pollProgress(total, done) {
$('#progress').text('已處理 ' + done + ' / ' + total);
if (done >= total) { alert('完成'); return; }
$.get('batch_gen.php?action=process&offset=' + done, function(res) {
var data = JSON.parse(res);
pollProgress(total, data.done);
});
}
</script>
location /article/ {
try_files /static/article_$arg_id.html @fallback;
}
location @fallback {
fastcgi_pass php-fpm;
# 動態腳本兜底
}
使用 Apache `ab` 工具對比動態 vs 靜態:
ab -n 1000 -c 50 https://localhost/article.php?id=123 # 動態 ab -n 1000 -c 50 https://localhost/static/article_123.html # 靜態 # 關注 Requests per second、Time per request、CPU/記憶體佔用
頁面靜態化是「以空間換時間、以寫入換讀取」的經典架構模式。核心三步:OB 捕獲輸出 → 模板替換生成 HTML → 檔案落地 + Nginx 直服。配合發布流程自動化、增量更新、兜底動態渲染,可支撐百萬級日 PV 內容型站點。