很多人在架設部落格時,會把部落格放在子網域(blog.example.com)而不是主網域(example.com)。這是因為多數部落格平台和 CMS 預設就以子網域運作,部署起來最省事。
但如果你在乎 SEO,可能要重新考慮這個選擇。
為什麼要放在子目錄?
SEO 優勢
子網域在搜尋引擎眼中是獨立的網站,必須從頭累積權重。而子目錄(example.com/blog)繼承主網域累積的所有域名權重,理論上能更快獲得好的排名。
Google 官方曾表示子網域不會被視為獨立實體,但實際數據顯示子目錄的表現普遍更好。ButterCMS 有一篇文章指出,子目錄的 SEO 效果比子網域高出約 40%。
我的個人經驗也印證了這一點。將一個部落格從子網域遷移到子目錄後,在沒有發表新文章、也沒有推廣的情況下,有機流量和搜尋排名在幾週內就有明顯提升。
子目錄的缺點
架構更複雜。多數部落格平台原生支援子網域,要改造成子網域需要多一步處理。不過一旦完成,整體維護成本其實不高。
實作方案:Cloudflare Workers
以下是我的完整設定流程。範例中假設:
- 主網站(
example.com)託管在 Render(靜態主機) - 部落格(
blog.example.com)託管在 Vercel(Next.js)
流程中的多數步驟適用於任何主機提供商,關鍵操作都在 Cloudflare Dashboard 完成。
注意: Cloudflare 時常更新後台介面和路由。如果操作畫面與本文截圖不符,使用後台的搜尋功能找到對應項目即可。
步驟一:設定主網站的 DNS 紀錄
進入 Cloudflare Dashboard,點選你的網域:
- SSL/TLS → Overview → Configure,選擇 Full
- 進入 DNS → DNS Records,新增以下紀錄(以 Render 為例):
| Type | Name | Target | Proxy status | TTL |
|---|---|---|---|---|
| CNAME | @ | my-site.onrender.com | Proxied | Auto |
| CNAME | www | my-site.onrender.com | Proxied | Auto |
| CNAME | api | my-api.onrender.com | Proxied | Auto |
務必將 Proxy status 設為 Proxied,且不要新增萬用字元紀錄(如 *.example.com)。
步驟二:設定部落格的 DNS 紀錄
確認部落格已可在子網域正常存取後,再新增一筆 DNS 紀錄:
| Type | Name | Target | Proxy status | TTL |
|---|---|---|---|---|
| CNAME | blog | cname.vercel-dns.com | Proxied | Auto |
步驟三:調整部落格的路由設定
在部落格的 next.config.js 或 next.config.mjs 中加入 basePath: "/blog":
/** @type {import('next').NextConfig} */
const nextConfig = {
basePath: "/blog",
images: {
remotePatterns: [
{
protocol: "https",
hostname: "imagedelivery.net",
},
],
},
};
export default nextConfig;
請確認部落格的路由目前指向 / 而非 /blog。不應該有包含 /blog 的路由。
步驟四:建立 Cloudflare Worker
在 Cloudflare Dashboard:
- 點選 Workers & Pages
- 點選 Create → Create Worker
- 選擇 Start with Hello World!,命名為
blog-worker,點選 Deploy
部署完成後,進入 Worker 編輯器,將程式碼替換為以下內容:
export default {
async fetch(request, env, ctx) {
async function MethodNotAllowed(request) {
return new Response(`Method ${request.method} not allowed.`, {
status: 405,
headers: {
Allow: "GET",
},
});
}
if (request.method !== "GET") return MethodNotAllowed(request);
const url = new URL(request.url);
const originUrl = url.toString().replace(
'https://example.com/blog',
'https://blog.example.com/blog'
).replace(
'https://www.example.com/blog',
'https://blog.example.com/blog'
);
const originPage = await fetch(originUrl);
const newResponse = new Response(originPage.body, originPage);
return newResponse;
},
};
替換掉範例中的網址為你自己的網域。儲存後,點選版本 ID 的雜湊值(如 b30983e0),再點選 Apply 來部署。
步驟五:連接 Worker 與路由
回到 Cloudflare Dashboard,進入 Worker Routes:
-
新增第一條路由:
- Route:
example.com/blog/* - Worker:
blog-worker
- Route:
-
新增第二條路由(處理靜態資源):
- Route:
example.com/blog/_next/static/* - Worker:
blog-worker
- Route:
設定完成後,理論上就能透過 example.com/blog 存取原本在 blog.example.com 的部落格了。
步驟六:防止子網域被搜尋引擎索引
因為部落格現在同時存在於子網域和子目錄,必須確保搜尋引擎只索引子目錄,否則會因重複內容而傷害 SEO。
更新 Next.js 設定
在 next.config.js 中加入 headers 設定,讓子網域的所有頁面都回傳 noindex:
/** @type {import('next').NextConfig} */
const nextConfig = {
basePath: "/blog",
images: {
remotePatterns: [
{
protocol: "https",
hostname: "imagedelivery.net",
},
],
},
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'X-Robots-Tag',
value: 'noindex, nofollow',
},
],
},
];
},
};
export default nextConfig;
更新 Cloudflare Worker
修改 Worker 程式碼,在轉發回應時移除 x-robots-tag header:
export default {
async fetch(request, env, ctx) {
async function MethodNotAllowed(request) {
return new Response(`Method ${request.method} not allowed.`, {
status: 405,
headers: {
Allow: "GET",
},
});
}
if (request.method !== "GET") return MethodNotAllowed(request);
const url = new URL(request.url);
const originUrl = url.toString().replace(
'https://example.com/blog',
'https://blog.example.com/blog'
).replace(
'https://www.example.com/blog',
'https://blog.example.com/blog'
);
const originPage = await fetch(originUrl);
let newResponse = new Response(originPage.body, originPage);
newResponse.headers.delete("x-robots-tag");
return newResponse;
},
};
這樣子目錄收到的回應會是乾淨的,不帶 noindex header;而子網域則維持 X-Robots-Tag: noindex, nofollow。
步驟七:驗證結果
驗證子網域未遭索引
開啟你部落格的 Vercel 部署網址(https://vercel.com/my-projects/...),在瀏覽器開發者工具的 Network 分頁中,確認回應 header 沒有 X-Robots-Tag。如果沒有這個 header,表示 Next.js 設定正確。
驗證子目錄已被索引
前往 Google URL Inspection Tool,輸入你的子目錄網址(如 example.com/blog),確認 Google 已將其編入索引。
適用於 Hugo 的對應調整
如果你使用的是 Hugo 而不是 Next.js,核心概念相同,但實作細節不同:
- basePath 概念:Hugo 輸出靜態檔案到
public/目錄。如果要讓產出的 HTML 資源路徑前綴/blog,可在hugo.toml中設定:
[permalinks]
blog = "/blog/:slug"
-
Cloudflare Worker 不變:不管前端用什麼框架,Worker 的 URL 置換邏輯完全相同。
-
404 處理:Hugo 的靜態頁面需要確認所有內部連結都已更新為
/blog/前綴,否則圖片、CSS、JS 會404。
結語
用 Cloudflare Workers 將部落格從子網域遷移到子目錄,技術上可行且效果顯著。整個流程的核心優點是:
- 不改變既有主機設定:部落格依然託管在原本的平台上
- DNS 集中管理:所有流量經過 Cloudflare,可擴充其他規則
- SEO 提升:子目錄繼承主網域權重,長期來說值得投資
代價是初期設定需要一些時間,特別是 Worker 的路由邏輯要處理乾淨。不過一旦架好,之後的維護成本極低,是一勞永逸的方案。
如果你對自己的 Hugo 網站有 SEO 需求,值得評估是否要進行這次遷移。