WordPress 指定頁面替換為純靜態 HTML 教學
透過 mu-plugins 機制,在不修改主題、不怕更新覆蓋的情況下,將 WordPress 特定 URL 的內容替換為你自己的純 HTML 頁面。
為什麼需要這樣做?
用 WordPress 建站,有時某些頁面需要 100% 自訂 HTML + CSS(例如用 Tailwind CSS CDN 做 landing page),但 WordPress 有以下限制:
- 主題模板會強制載入 header、footer、sidebar
- 頁面編輯器無法完全自訂 HTML 結構
- 直接改 PHP 檔案,主題一更新就全部消失
我們需要一個方法:保留原本的 URL 不變,但輸出完全由你控制的靜態 HTML,而且不會被任何更新覆蓋。
方案比較
| 方案 | 會被更新覆蓋? | 風險 |
|---|---|---|
| 直接改主題 PHP | 會 | 主題更新即失效 |
| .htaccess RewriteRule | 可能 | WordPress 儲存永久連結時會重寫 .htaccess |
| 改插件檔案 | 會 | 插件更新即失效 |
| mu-plugins(推薦) | 不會 | 穩定,獨立於主題和插件之外 |
為什麼 mu-plugins 不受影響?
mu-plugins 是完全獨立的存在,以下任何操作都不會影響到它:
- WordPress 核心更新:核心更新只動
wp-admin/和wp-includes/,不會碰wp-content/mu-plugins/ - 主題更新:主題檔案在
wp-content/themes/裡面,跟 mu-plugins 毫無關係 - 插件更新:一般插件在
wp-content/plugins/,mu-plugins 是另一個獨立目錄 - .htaccess 被重寫:WordPress 在後台「儲存永久連結」時會重寫
.htaccess,但 mu-plugins 運作在 PHP 層面,完全不依賴.htaccess - 切換主題:換主題只影響
wp-content/themes/下的檔案 - 停用 / 刪除其他插件:mu-plugins 不在一般插件管理介面中,其他插件的操作對它零影響
簡單來說,mu-plugins 只有一種方式會消失:有人手動去伺服器刪除 mu-plugins/ 裡面的檔案。日常的 WordPress 維護操作完全不會碰到它。
什麼是 mu-plugins?
mu-plugins(Must-Use Plugins)是 WordPress 的一個特殊機制:
- 放在
wp-content/mu-plugins/目錄下 - WordPress 每次載入都會自動執行,不需要在後台啟用
- WordPress 核心更新、主題更新、插件更新都不會影響它
- 不會出現在一般插件列表,不會被人誤停用
實作步驟
Step 1:建立靜態 HTML 檔案存放目錄
透過 FTP/SFTP 連接你的伺服器,在 WordPress 根目錄(即 wp-config.php 所在的位置)建立一個資料夾:
/your-wordpress-root/
├── wp-admin/
├── wp-content/
├── wp-includes/
├── static-pages/ ← 新建這個資料夾
│ └── my-landing.html ← 你的靜態 HTML 檔案
├── wp-config.php
└── ...
Step 2:上傳你的靜態 HTML 檔案
將你準備好的純 HTML 檔案放入 static-pages/ 資料夾。例如 my-landing.html:
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>你的頁面標題</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
<!-- 100% 你控制的內容,不受 WordPress 主題影響 -->
<h1 class="text-4xl font-bold text-center mt-20">Hello World</h1>
</body>
</html>
Step 3:建立 mu-plugin
確認 wp-content/mu-plugins/ 資料夾存在(如果沒有就建立一個),然後在裡面新增一個 PHP 檔案,例如 custom-static-pages.php:
/your-wordpress-root/
└── wp-content/
└── mu-plugins/ ← 如果沒有就新建
└── custom-static-pages.php ← 新建這個檔案
檔案內容如下:
<?php
/*
* Plugin Name: Custom Static Pages
* Description: 指定 URL 載入純靜態 HTML 取代 WP 模板
*/
add_action('template_redirect', function () {
// ===== 設定區:在這裡加入你要替換的頁面 =====
$static_pages = [
// '原本的 URL 路徑' => '對應的靜態 HTML 檔案路徑',
'/2025/08/11/my-example-post/' => '/static-pages/my-landing.html',
// 需要更多頁面就繼續加:
// '/2025/09/01/another-post/' => '/static-pages/another.html',
];
// ===== 設定區結束 =====
$request_uri = urldecode($_SERVER['REQUEST_URI']);
$path = parse_url($request_uri, PHP_URL_PATH);
$path = rtrim($path, '/') . '/';
foreach ($static_pages as $url => $file) {
$url = rtrim($url, '/') . '/';
if ($path === $url) {
$file_path = ABSPATH . ltrim($file, '/');
if (file_exists($file_path)) {
header('HTTP/1.1 200 OK');
header('Content-Type: text/html; charset=utf-8');
readfile($file_path);
exit;
}
}
}
});
Step 4:防止靜態檔案被直接存取(選做但建議)
在 static-pages/ 資料夾內新增一個 .htaccess 檔案:
# 防止用戶直接訪問靜態 HTML 檔案
# 所有流量應經過原本的 WordPress URL
Order Deny,Allow
Deny from all
這樣別人就不能直接打開 yourdomain.com/static-pages/my-landing.html,所有流量都會經過原本的 WordPress URL。
完成!驗證效果
上傳完成後,直接打開你設定的原始 URL,例如:
https://yourdomain.com/2025/08/11/my-example-post/
你應該會看到你的純靜態 HTML 頁面,而不是 WordPress 主題模板。URL 完全不變,訪客和搜尋引擎都不會察覺任何分別。
之後要加新頁面怎麼辦?
只需要兩步:
- 將新的 HTML 檔案上傳到
static-pages/ - 在
custom-static-pages.php的$static_pages陣列加一行
$static_pages = [
'/2025/08/11/my-example-post/' => '/static-pages/my-landing.html',
'/2025/09/15/new-post/' => '/static-pages/new-page.html', // 新加
];
不需要重啟任何東西,儲存即生效。
注意事項
-
SEO 標籤要自己管理:因為繞過了 WordPress,Yoast / RankMath 等 SEO 插件不會在這些頁面運作。記得在你的 HTML 裡面手動加入
<title>、<meta name="description">、canonical、OG tags、Schema markup 等。 -
不影響其他頁面:只有你在
$static_pages裡面設定的 URL 會被替換,其他所有 WordPress 頁面完全不受影響。 -
更新安全:mu-plugins 不受 WordPress 核心、主題、插件更新影響。唯一會消失的情況是有人手動刪除
mu-plugins裡的檔案。 -
效能更好:因為
readfile()直接輸出靜態檔案後就exit,WordPress 的主題、sidebar、footer、插件都不會載入,頁面載入速度會比正常 WP 頁面快。
進階用法:用同一個 mu-plugin 管理 URL Redirect
除了替換靜態頁面,同一個 mu-plugin 也可以處理 URL 跳轉。常見場景包括:
- 短網址跳轉到外部 PDF 下載(PDF 太大,放在另一台 server 或 CDN)
- 舊頁面 301 跳轉到新頁面
- 自訂短連結跳轉到合作夥伴頁面
完整版 mu-plugin(靜態頁面 + Redirect 二合一)
將原本的 custom-static-pages.php 替換為以下完整版:
<?php
/*
* Plugin Name: Custom Static Pages & Redirects
* Description: 管理靜態 HTML 頁面替換 + URL 跳轉
*/
add_action('template_redirect', function () {
// =========================================
// 設定一:靜態頁面替換
// 格式:'WordPress URL 路徑' => '本機靜態 HTML 檔案路徑'
// =========================================
$static_pages = [
'/2025/08/11/my-example-post/' => '/static-pages/my-landing.html',
];
// =========================================
// 設定二:301 永久跳轉
// 格式:'短網址路徑' => '目標完整 URL'
// =========================================
$redirects_301 = [
'/dl/price' => 'https://cdn.example.com/files/price-list.pdf',
'/dl/brochure' => 'https://cdn.example.com/files/brochure-2025.pdf',
'/go/partner' => 'https://www.partner-site.com/landing',
];
// =========================================
// 設定三:302 臨時跳轉(適合經常更換目標的連結)
// 格式同上
// =========================================
$redirects_302 = [
'/promo' => 'https://www.example.com/current-promotion',
];
// ===== 以下為執行邏輯,不需要改動 =====
$request_uri = urldecode($_SERVER['REQUEST_URI']);
$path = parse_url($request_uri, PHP_URL_PATH);
$path_trimmed = rtrim($path, '/');
$path_with_slash = $path_trimmed . '/';
// 處理靜態頁面
foreach ($static_pages as $url => $file) {
if ($path_with_slash === rtrim($url, '/') . '/') {
$file_path = ABSPATH . ltrim($file, '/');
if (file_exists($file_path)) {
header('HTTP/1.1 200 OK');
header('Content-Type: text/html; charset=utf-8');
readfile($file_path);
exit;
}
}
}
// 處理 301 跳轉
foreach ($redirects_301 as $from => $to) {
if ($path_trimmed === rtrim($from, '/')) {
header('Location: ' . $to, true, 301);
exit;
}
}
// 處理 302 跳轉
foreach ($redirects_302 as $from => $to) {
if ($path_trimmed === rtrim($from, '/')) {
header('Location: ' . $to, true, 302);
exit;
}
}
});
301 vs 302 應該用哪個?
| 301 永久跳轉 | 302 臨時跳轉 | |
|---|---|---|
| 搜尋引擎 | 會把 SEO 權重轉移到新 URL | 權重保留在原 URL |
| 瀏覽器快取 | 瀏覽器會記住,下次直接跳轉 | 每次都會經過你的伺服器 |
| 適合場景 | PDF 下載連結、舊頁面永久搬家 | 推廣活動頁面、經常更換目標的連結 |
簡單判斷:目標 URL 以後不太會變 → 用 301;目標可能隨時換 → 用 302。
使用範例
設定完成後,效果如下:
yourdomain.com/dl/price → 301 跳轉到 cdn.example.com 下載 PDF
yourdomain.com/dl/brochure → 301 跳轉到 cdn.example.com 下載 PDF
yourdomain.com/go/partner → 301 跳轉到合作夥伴網站
yourdomain.com/promo → 302 跳轉到當前推廣頁面(可隨時改目標)
要加新的 redirect 就在對應的陣列加一行,儲存即生效,不需要裝任何 redirect 插件。
與 Redirect 插件的比較
你可能會問:為什麼不直接用 Redirection 之類的 WordPress 插件?
| mu-plugin 方式 | Redirect 插件 | |
|---|---|---|
| 執行時機 | template_redirect 階段,非常早 |
同樣早期,但多了插件框架開銷 |
| 依賴 | 零依賴,純 PHP | 需要插件持續啟用 |
| 更新風險 | 不受任何更新影響 | 插件更新可能出問題 |
| 管理介面 | 需要編輯 PHP 檔案 | 有後台 GUI |
| 適合誰 | 會用 FTP 的技術人員 | 不想碰程式碼的人 |
如果你的 redirect 數量不多(幾十條以內),mu-plugin 方式更輕量、更穩定。如果有幾百條規則而且需要非技術同事管理,才考慮用插件。
總結
WordPress URL 請求
↓
mu-plugin 攔截 (template_redirect)
↓
靜態頁面 match? ─── 是 → 讀取 HTML 檔案 → 直接輸出 → exit
↓ 否
301 redirect match? ── 是 → 發送 301 header → exit
↓ 否
302 redirect match? ── 是 → 發送 302 header → exit
↓ 否
正常載入 WordPress 主題
一個檔案搞掂靜態頁面替換 + URL 跳轉管理,簡單、穩定、不怕更新。