Blog · 2026-08-30

sitemap 的 lastmod 天天說謊,Google 就不聽你的——內容雜湊狀態機做法

靜態站每次重建就把 lastmod 蓋成建置時間,等於天天對 Google 說謊;正解是剝除雜訊後對內容做雜湊、配一個狀態機,讓日期只在內容真的變了才動。

打開自家 sitemap.xml,幾百個 URL 的 lastmod 全是今天凌晨同一分鐘——因為部署排程剛跑完。內容一個字都沒改,變的只有建置時間。這種 sitemap 每天都在對 Google 喊「全站都更新了」,喊久了,連你真的更新的那一頁,它也懶得來看了。這不是冷門災情,是多數靜態站產生器的預設行為。

病徵:全站 lastmod 同一個時間戳

診斷只要一眼:打開 sitemap,如果每個 <lastmod> 都是同一個時間,而且剛好等於上次部署的時間,你的產生器八成是拿「現在時間」當修改時間在用——date.today() 塞進 dateModified,或建置腳本直接把 lastmod 蓋成 build 當下。另一個旁證在 Search Console:sitemap 明明顯示已讀取,真正改過的頁面卻遲遲等不到重爬。

這在「排程自動重建」的站上最嚴重。我們自己維護一個 402 頁、一天自動重建 4 次的賽事內容站(積分、賽程天天在變,重建是必要的),如果拿建置時間當 lastmod,等於每天對每一頁宣稱「它更新了 4 次」——但多數頁面的正文其實一個位元組都沒動。更糟的是同一個謊通常會說兩次:sitemap 說一次,頁面裡結構化資料的 dateModified 再說一次。

Google 的立場:不準的 lastmod,直接當不存在

Google 官方 sitemap 文件寫得很直白:lastmod 要「持續且可被驗證為準確」(consistently and verifiably accurate)才會被採用,驗證方式例如拿它去比對頁面實際的修改。同一份文件也定義了什麼叫值得標記的更新:主要內容、結構化資料、頁面連結變了才算;換個著作權年份,不算。

lastmod 的用途是幫爬蟲排優先序——告訴它「先來爬這幾頁,其他不用」。全站天天喊更新,這個訊號就歸零:Google 無從分辨哪一頁真的變了,你等於親手把最值錢的爬取提示丟掉。對一天重建多次、又希望更新盡快被收錄的站,這是拿石頭砸自己的腳。

正解:內容雜湊狀態機,日期跟著內容走

原則一句話:lastmod 不該來自「什麼時候建置」,該來自「內容什麼時候變」。做法是替每一頁維護一個跨建置存活的狀態檔:

{ "/match/group-a/": {
    "hash": "3f2a…",
    "publishedAt": "2026-06-10",
    "updatedAt": "2026-08-12" } }

每次建置對每一頁跑同一套流程:

  1. 產出 HTML 後,抽出正文、正規化、算 SHA256。
  2. 狀態檔裡沒有這頁 → 新頁,publishedAt 與 updatedAt 都寫今天。
  3. 雜湊跟上次相同 → 什麼都不動,沿用舊日期。
  4. 雜湊不同 → updatedAt 改成今天,寫回狀態檔。

sitemap 的 lastmod、結構化資料的 dateModified、頁面上顯示的「最後更新」,全部從狀態檔讀——三個地方共用同一個真相來源。狀態檔跟著版本庫或部署工件走,重建幾次都不會失憶。寫回的時機也要想清楚:等部署確定成功才落盤,失敗的建置不准汙染狀態,不然一次炸掉的 build 會把全站日期一起拖下水。

雜湊前先剝乾淨:script 和追蹤碼不算內容

這套機制最常死在雜湊算得太粗。直接對整份 HTML 做雜湊,你會發現每次建置全站都「變了」:追蹤碼片段換版、資產檔名帶的快取指紋(app.a1b2c3.js)、隨機 nonce、頁尾自動帶的年份——任何一項動了,全站雜湊翻新,狀態機形同虛設。同理,「相關文章」這種每次建置隨機抽選的區塊,也要劃在雜湊範圍之外。

所以雜湊之前要先剝。用真的 HTML parser(不是正規表達式)把 <script><style>、註解整段拆掉,清掉追蹤參數與版本指紋,只留主內容區的文字與結構,正規化空白之後再算。你剝掉的這些東西,恰好就是 Google 定義裡「不算重大更新」的東西——雜湊的邊界,就照官方對 significant 的邊界來切。

發布日與更新日是兩個欄位,別混用

另一個常見錯誤是整站只有一個日期欄位。發布日(publishedAt)寫下去就不該再動;更新日(updatedAt)只在雜湊變了才動。輸出規則一行講完:

lastmod = updatedAt ?? publishedAt

沒改過的頁面,lastmod 誠實停在發布日,這不丟臉;真的改過的頁面,lastmod 精準指到那一天,這才有價值。

驗收要做負面測試,兩條都得過:連續跑兩次建置,第二次必須是零頁變動;接著改某一頁的一個段落,只允許那一頁的 lastmod 動。任何一條不過,代表雜訊還沒剝乾淨,你的 sitemap 還在說謊。

結語

lastmod 是你跟爬蟲之間的信用額度,而信用靠「不亂動」累積。把日期綁到內容雜湊上,說謊這件事就從流程裡被拿掉了——不靠自律,靠機制。如果你的站也是幾百頁、排程天天重建,sitemap 卻從來沒讓 Google 認真看過一眼,這套狀態機我們自己營運的內容站就在跑,歡迎找我們聊聊。

這類問題,我們天天在解

把你的情境描述給我們,直接告訴你做不做得到、大概多少錢。

用 Telegram 聊需求
評估與報價不收費 · 回覆你的是工程師本人
TG 聊需求