sitemap 與 robots.txt:把 SEO 地基交給 Next.js Metadata,而不是自己寫 endpoint

部落格內容漸漸累積後,我想補上 SEO 地基:sitemap 與 robots.txt。原本想自己寫 endpoint,最後改用 Next.js Metadata 路由,再用 Google Search Console 驗證、記下幾個坑。

  • Next.js
  • SEO

這幾天陸續在幫 blog 補基礎建設,先是把 MDX 渲染引擎換了血。累積了幾篇文章之後,我開始想到下一件事——SEO。內容還很少,但總覺得該趁早把地基打好,免得以後要補的時候,已經忘記當初是怎麼決定的。我最先想到的兩個東西,是 sitemap.xmlrobots.txt

示意圖:Next.js 的 sitemap.ts 與 robots.ts 產出內容,經 Google 的 DNS 驗證與爬蟲探索後成功送達

sitemap.xmlrobots.txt 在做什麼,Next.js 怎麼原生接住

這兩個檔案其實一直都是很純粹的靜態協定,不需要框架也能存在。sitemap.xml 是給搜尋引擎爬蟲看的「這個網站有哪些頁面」清單;robots.txt 則是爬蟲能不能爬、要不要爬的規則書。兩者分工很清楚——一個負責「告訴你有什麼」,一個負責「告訴你能不能碰」。

Next.js 16 的 App Router 把這兩個協定變成了 Metadata 路由的檔案慣例:在 app/ 底下寫一個 sitemap.ts、一個 robots.ts,各自 export default function,回傳型別分別是 MetadataRoute.SitemapMetadataRoute.Robots。框架在 build 時會把這兩個函式的回傳值轉成真正的 sitemap.xmlrobots.txt,本質上它們是特殊的 Route Handler,只是被框架用檔名慣例接管掉了。形狀大致長這樣:

import type { MetadataRoute } from "next";
 
export default function robots(): MetadataRoute.Robots {
  return {
    rules: { userAgent: "*", allow: "/" },
    sitemap: "https://example.com/sitemap.xml",
  };
}

決定不自己寫 endpoint,改用 Metadata 路由

我其實已經知道,可以直接寫一個 API endpoint,自己組一段 XML 字串或 robots.txt 文字,設好 Content-Type 再回傳 Response。這條路完全可行,很多教學也是這樣示範的。但最後我決定用 Next.js 內建的 Metadata 路由。

先講框架通用的好處:export default function sitemap(): MetadataRoute.Sitemap 這個型別簽章,讓 TypeScript 在 compile time 就檢查我回傳的物件形狀對不對——url 有沒有漏、日期欄位是不是字串。比起手寫 endpoint 自己維護 XML schema、自己記得設對 header,這樣少了一層「格式正確性要自己把關」的心智負擔。app/sitemap.tsapp/robots.ts 本身就是官方框架慣例的檔案,路由怎麼掛、Content-Type 怎麼設,都不用我自己決定。

用 Google Search Console 驗證,而不是自己盯著 XML 看

實作完成後,問題來了。怎麼知道我寫的 sitemap 跟 robots.txt 內容是對的?本機跑起來看 XML、看文字檔沒有語法錯誤,不代表 Google 的爬蟲讀到的就是我以為的樣子——這種落差光靠肉眼看本機產出根本看不出來,唯一能確認的辦法,是換到搜尋引擎的視角去看。我用的方法,是直接把網站加進 Google Search Console(以下簡稱 GSC)。

GSC 是 Google 官方提供、免費讓網站擁有者檢視自己網站在 Google 搜尋中的狀態與健康度的工具。

我的 domain 是在 Cloudflare 買的,加入資源時選了官方的 DNS 驗證方式——照 Google 給的 TXT record 加進 DNS 設定,驗證幾乎是秒過,快速又方便。

設定完之後,到 GSC 提交我的 sitemap 網址,馬上就能看到讀取狀態有沒有跳出「成功」,以及探索到的網頁數量。

關鍵學習:本機看起來語法正確的 sitemap 或 robots.txt,不代表爬蟲眼中也是正確的——唯一能確認的方式,是站到搜尋引擎的視角去看它實際讀到什麼、探索到多少頁面,而不是自己在本機猜。

幾個容易踩的坑

實作跟驗證的過程中,我順手整理了幾個常見、也很容易一不小心就犯的坑:

這些坑沒有一個特別難懂,但每一個都是「不知道要注意,才會漏掉」的類型。

不是 AI 會自動幫你避坑,而是我要記得開口問

在不熟悉 web 生態的情況下,上面那幾個坑很容易一個一個踩過去——不是因為粗心,而是根本不知道有這些坑存在。這也是現在用 agentic coding 跟 AI 一起討論規劃、設計方案時,真正能幫上忙的地方:它見過的坑,遠比我一個人踩過的多。

但這裡的重點順序容易被誤解。不是我先做完設計、AI 再幫我抓錯;而是我要在一開始的 prompt 裡,就主動要求 AI 先幫我評估「這個設計可能有哪些坑」,再據此決定怎麼避開。AI 不會自己想到要做這件事——這件事會不會發生,取決的不是 AI 夠不夠聰明,而是我記不記得開口問。