結論先講
網站搬家沒做 redirect = SEO 自殺。 我自己就犯了這個錯:300 篇文章從 Hexo 搬到 Quartz,URL 結構全變,沒做任何 redirect。結果 Google 索引的全是 404 的舊頁面,新文章一篇都搜不到。
這篇不是教科書,是驗屍報告。所有的「正確做法」都是我踩完坑之後才學到的。
我的搬家時間線
2024-09 Hexo 部落格正常運作,Google 收錄約 30 頁
URL 格式:/{category}/{YYYYMMDD}/{abbrlink}/
例:/devOps/20240915/3152381087/
2025-02 搬家到 Quartz,重新設計 URL 結構
URL 格式:/{category}/{slug}
例:/git/08-release
2025-02~ Google 還在索引舊 URL,全部 404
2026-03 新 URL 一篇都沒被收錄
搜 "site:terryyaowork.github.io" 只有 6 筆結果
全部都是舊的 404 頁面 💀
一年多的時間,300 篇新文章對 Google 來說完全不存在。
為什麼會這樣?
URL 結構變了但沒告訴 Google
Hexo 用 abbrlink 產生數字 hash 當 URL:
/devOps/20240915/3152381087/ ← Hexo (abbrlink)
/git/08-release ← Quartz (slug)
兩個 URL 完全不同。Google 不會自動知道它們是同一篇文章。
Google 的行為邏輯
1. Google 資料庫裡有舊 URL
2. Googlebot 去爬 → 404
3. Google 不會立刻刪除索引,會重試幾次
4. 持續 404 → 最終降權或移除
5. 但新 URL 沒有任何入口 → Google 不知道它存在
6. 即使有 sitemap,Google 也不信任一個「舊頁面都壞掉」的網站
結果:舊的被移除或降權,新的沒被發現。兩頭空。
正確的搬家 SEO 流程
Phase 1:搬家前(準備)
1. 記錄舊 URL 清單
搬家前最重要的事:把所有舊 URL 存下來。
# 從舊站的 sitemap 匯出
curl -s https://your-old-site.com/sitemap.xml | grep "<loc>" > old-urls.txt
# 或從 Google Search Console 匯出
# GSC → 成效 → 匯出 → 所有頁面如果你跟我一樣沒存… 只能從 Google 搜尋結果反推了:
# 搜尋 Google 索引中的舊頁面
# site:your-site.com inurl:20242. 建立舊→新 URL 對照表
舊 URL → 新 URL
/devOps/20240915/3152381087/ → /git/08-release
/devOps/20240915/2194877756/ → /git/05-git-flow
/express/web-develop/20241017/368853435/ → /express/01-init
如果文章很多,用腳本比對標題自動配對:
// match-urls.mjs
// 從舊 URL 的標題比對新文章
import { readdirSync, readFileSync } from 'fs';
const OLD_URLS = [
{ url: '/devOps/20240915/3152381087/', title: 'Release 管理' },
// ...
];
// 掃描新文章的 title
function findNewUrl(oldTitle) {
// 遞迴搜尋 content/ 底下所有 .md
// 比對 frontmatter title 包含 oldTitle
// 回傳新的 URL path
}3. 在 GSC 確認目前索引狀態
GSC → 索引 → 涵蓋範圍
- 看有多少頁被索引
- 記錄下來,搬家後比較
Phase 2:搬家時(執行)
4. 建立 Redirect
最佳方案:伺服器端 301 redirect
如果你用 Nginx / Apache:
# nginx.conf
location ~ ^/devOps/20240915/3152381087/ {
return 301 /git/08-release;
}GitHub Pages 方案:HTML meta refresh
GitHub Pages 不支援伺服器端 redirect。替代方案是在舊路徑放 HTML 檔案:
<!-- public/devOps/20240915/3152381087/index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="canonical" href="https://site.com/git/08-release">
<meta http-equiv="refresh" content="0; url=https://site.com/git/08-release">
<meta name="robots" content="noindex">
<script>window.location.replace("https://site.com/git/08-release");</script>
</head>
<body>
<p>已搬移至 <a href="/git/08-release">新頁面</a></p>
</body>
</html>三重保險:
canonical— 告訴 Google 正版 URLmeta refresh— 瀏覽器自動跳轉noindex— 不要索引這個 redirect 頁面
5. 智慧 404 頁面
處理已知的 redirect 之後,還要處理未知的舊 URL。在 404 頁面加 JS,偵測舊 URL 格式並導向:
// 注入到 404.html
(function() {
var path = window.location.pathname;
// 已知的 redirect
var map = {
'/devOps/20240915/3152381087/': '/git/08-release',
'/devOps/20240915/2194877756/': '/git/05-git-flow',
// ...
};
if (map[path]) {
window.location.replace(map[path]);
return;
}
// 通用規則:/{category}/{date}/{hash}/ → /{category}/
var match = path.match(/^\/([a-zA-Z-]+)\/\d{8}\/\d+\//);
if (match) {
var catMap = {
'devOps': '/devOps/',
'git': '/git/',
'express': '/express/',
'aws': '/aws/'
};
window.location.replace(catMap[match[1]] || '/');
}
})();6. 更新 Sitemap
確保新的 sitemap.xml 包含所有新 URL,不包含舊 URL。
<!-- sitemap.xml -->
<url>
<loc>https://site.com/git/08-release</loc>
<lastmod>2025-02-09</lastmod>
</url>
<!-- 不要包含舊的 /devOps/20240915/... -->Phase 3:搬家後(驗證)
7. 到 GSC 提交新 Sitemap
GSC → Sitemap → 新增 Sitemap
輸入:sitemap.xml → 提交
8. 用「網址審查」要求重新索引
對最重要的幾篇文章,手動要求 Google 重新爬取:
GSC → 網址審查 → 輸入新 URL
→ 要求建立索引
每天有配額限制(約 10-50 次),先提交最重要的頁面。
9. 監控索引狀態
每週檢查:
- GSC 涵蓋範圍 → 已索引頁面數是否增加
- Google 搜尋 site:your-site.com → 結果數是否增加
- 舊 URL 是否逐漸從索引中消失
完整恢復通常需要 2-8 週,取決於網站規模和 Google 爬取頻率。
自動化:CI/CD 整合 Redirect
如果用 GitHub Actions 部署,把 redirect 建立整合進 build 流程:
# .github/workflows/deploy.yml
- name: Build Quartz
run: node quartz/bootstrap-cli.mjs build
- name: Setup redirects for old URLs
run: node scripts/setup-redirects.mjs
# 這個腳本:
# 1. 在 public/ 建立舊路徑的 redirect HTML
# 2. 注入 redirect JS 到 404.html
- name: Upload artifact
uses: actions/upload-pages-artifact@v3這樣每次部署都會自動建立 redirect,不用擔心手動維護。
搬家 SEO 檢查清單
搬家前
- 匯出舊 URL 完整清單
- 建立舊→新 URL 對照表
- 記錄 GSC 目前索引數量
- 備份舊站(以防萬一)
搬家時
- 所有舊 URL 有 redirect 到新 URL
- Redirect 包含 canonical + noindex
- 404 頁面有智慧 redirect 邏輯
- 新 sitemap 只包含新 URL
- robots.txt 正確(Allow + Sitemap)
搬家後
- GSC 提交新 sitemap
- GSC 網址審查重點頁面
- 每週監控索引恢復狀態
- 確認舊 URL 被正確 redirect(不是 404)
我的教訓總結
| 我做錯的 | 正確做法 |
|---|---|
| 沒存舊 URL 清單 | 搬家前先匯出 |
| 沒做 redirect | 每個舊 URL 都要 redirect |
| 沒提交新 sitemap | 搬完立刻提交 |
| 等了一年才發現 | 搬完一週內就該檢查 GSC |
| 以為 Google 會自己找到 | Google 不會,要你告訴它 |
最痛的教訓:搬家不是搬完就結束,SEO 的處理才是搬家最重要的一步。 寫了 300 篇文章,但 Google 看不到,等於沒寫。