Wordpress

WordPress 快取外掛怎麼選?三種快取類型解析

兩個網站規格相近,同一款熱門快取外掛,連後台勾選的設定都差不多,測出來的效能卻天差地遠。一個首位元組時間穩穩壓在 web.dev 建議的 0.8 秒門檻內,另一個卻拖到快兩秒,問題通常不在主機,也不在外掛本身。

謎底其實藏在「快取外掛」這四個字裡,它從來不是單一功能,而是把頁面快取、物件快取、瀏覽器快取三種完全不同的機制,包進同一張設定畫面裡賣。三層各自卡在請求流程的不同階段,少開一層、開錯一層,網站效能自然差一大截。分清楚這三層的分工,才有辦法真正判斷 WordPress 快取外掛怎麼選,而不是看評價星等隨手裝一款。

接下來就從一次頁面請求的完整路徑講起,看這三種快取分別接手哪一段工作,再回頭對照自己的網站,該優先補齊哪一層。

快取外掛,其實同時在做三件不同的事

你在瀏覽器打開一篇文章的那一刻,伺服器理論上得重新跑一次 PHP、查一次資料庫、把版面組成一份完整的 HTML,才能把頁面交到你手上。這整套流程,WordPress 核心本身並沒有內建完整的捷徑,每一次請求都照著同一條路徑重新跑一遍。快取外掛存在的理由,就是把這條路徑裡最花時間的某一段省略掉,直接把現成的結果交出去。

問題是,「快取外掛」這個詞常常同時打包了三種完全不同的省略方式:省略整頁組裝(頁面快取)、省略資料庫查詢(物件快取)、省略瀏覽器重新下載檔案(瀏覽器快取)。三者分別卡在請求路徑的不同階段,頁面快取發生在伺服器產生內容的階段、物件快取發生在資料庫查詢的階段、瀏覽器快取則發生在使用者裝置端,跟伺服器完全無關。

頁面快取、物件快取、瀏覽器快取分別卡在伺服器組頁、資料庫查詢、訪客裝置三個不同階段,各省略一次請求路徑上的一段工作
快取外掛其實同時在做三件事:頁面快取省下整頁組裝、物件快取省下資料庫查詢、瀏覽器快取省下裝置端重新下載。

裝了一款外掛,不代表三層都自動顧到。外掛本質上只是一張設定介面,背後對應的仍然是這三層機制,不是外掛自己另外發明出來的東西。不先弄懂這三層各自卡在哪一段,設定時很容易漏掉真正需要的那一層,或誤以為裝了外掛就等於三層都到位。

WordPress 官方文件把話說得很直接,快取本身就是提升網站效能最快的一種做法。但這句話的前提,是你先分得清楚快取指的是哪一層。

頁面快取解決的是「整頁重新產生」的問題

同一篇文章,如果每個訪客看到的都是同一份內容,伺服器其實沒有必要每次都重新跑一遍 PHP、重新查一次資料庫。頁面快取(page cache)做的正是這件事,把組好的完整 HTML 存成一份靜態檔案,下一次同樣網址的請求進來,直接把這份現成的成品交出去,完全跳過運算與查詢的過程。

這也是三層快取裡,對「首次造訪的訪客」效果最明顯的一層,對首次載入速度的幫助也最直接。它天生適合開在內容給每個人看都一樣的頁面,例如部落格文章、形象頁、分類與列表頁;但碰到購物車、結帳、會員登入後的頁面,或是「加入購物車」這類會觸發動作的網址,就完全不適用。這些頁面每個人看到的內容不同,不能共用同一份靜態快取,硬是套上頁面快取,反而會讓 A 訪客看到 B 訪客的購物車內容。

頁面快取還有一個常被忽略的設定,就是快取多久要重新產生一次,也就是存活時間(TTL)。TTL 只要設得太短,快取幾乎就沒發揮效果,伺服器負擔跟沒開差不多;設得太長,又會讓訪客在文章更新後,看到的還是舊版內容。這個取捨沒有一體適用的答案,得回頭看網站內容更新的頻率去抓。即使只是很短的快取時間,對流量大的網站來說也能帶來明顯的效能提升,不必為了怕內容過期而完全不設 TTL。

哪些頁面適合開,哪些頁面該排除?

把判準攤開來看,其實就是問一句話,這個頁面在瀏覽器打開後,不同訪客看到的內容會不會一樣。

適合開啟頁面快取的,通常是內容固定、不因人而異的頁面:

  • 部落格文章與新聞頁面
  • 服務介紹、關於我們這類形象頁
  • 商品分類、文章列表這類彙整頁

該排除頁面快取的,則是內容因人而異,或牽涉即時狀態的頁面:

  • 購物車與結帳流程
  • 會員登入後才看得到的頁面
  • 加入購物車、送出表單這類會觸發動作的網址
部落格文章、形象頁、彙整頁這類內容人人相同的頁面適合開頁面快取;購物車、會員登入頁、觸發動作的網址則該排除
頁面快取開不開,就看不同訪客打開後看到的內容一不一樣:一樣就開,因人而異就排除。

物件快取省下的是「資料庫被重複問同一句話」的力氣

線上商店的商品頁,每個訪客可能因為登入狀態、購物車內容、個人化推薦而看到不同版面,整頁快取在這裡幫不上忙。但同一批資料被重複查詢的情況卻很常見,同一份選單、同一批熱門商品,可能在同一天被查詢上千次。物件快取(object cache)解決的正是這個問題,不快取整頁畫面,而是把資料庫查詢跑出來的「結果」存起來,例如文章資料、選單結構、使用者設定,下次遇到同樣的查詢,直接從記憶體拿現成答案,不必再問一次資料庫。

WordPress 官方文件對物件快取的形容很直接,做的事就是把資料從『昂貴又緩慢的存取方式』搬到『便宜又快速的存取方式』。只是 WordPress 內建的物件快取預設是「非持久」的,依官方說明,快取的資料只存在記憶體裡,而且只在單一次請求中有效,這次頁面請求結束,下一個請求進來就重新歸零。要讓它真正發揮效果、跨請求持續有用,得另外接上 Redis 或 Memcached 這類記憶體資料庫,把它做成「持久」快取。

這層快取解決的是資料庫查詢次數,跟頁面快取處理的整頁組裝時間是不同層次的問題。也因此,線上商店、會員平台、線上課程這類會登入互動、內容常常變動的網站,反而最需要它,原因是這些頁面本來就沒辦法整頁做頁面快取,物件快取自然成了省資源的主力。

什麼樣的網站,特別需要接上 Redis 或 Memcached?

判斷方式不難,問自己幾個問題:網站是不是有大量登入後才看得到的個人化內容?商品或課程資料是不是常常被重複查詢?留言、會員互動是不是頻繁?符合的項目越多,物件快取,尤其是接上 Redis 或 Memcached 之後,效果就越明顯。純展示型的形象網站,訪客大多沒有登入行為,這一層通常用不太到。

瀏覽器快取顧的是訪客裝置裡的檔案,不是伺服器

一個訪客這星期已經逛過你的網站,下星期再回訪,如果每一張圖片、每一份 CSS 和 JavaScript 檔案都要重新下載一次,等同於白白浪費了他上次留下的資料。瀏覽器快取(browser cache)顧的就是這件事,把圖片、CSS、JavaScript 這類不常變動的靜態檔案,透過 HTTP 標頭告訴瀏覽器,這份檔案可以先存在訪客自己的裝置裡,下次造訪同一個網站,不必重新下載。

這一層的主導權在瀏覽器端,跟前面兩種發生在伺服器端的快取,完全是不同層次的事。不過設定方式並不複雜,通常是 Cache-Control 與 Expires 這兩種 HTTP 標頭,外掛或伺服器設定檔(如 .htaccess)都能設定。WordPress 官方文件提到,設好正確的檔案標頭之後,伺服器可以用 304 回應取代重新傳送整個檔案,等於用一次簡短的確認,換掉一次完整下載。

也因為主導權在裝置端,瀏覽器快取對「第一次造訪」的訪客完全沒有幫助——他本來就沒有任何檔案可以拿來重複使用,一切都得從頭下載一次。它真正發揮作用的對象,是回訪的訪客。這裡有一個容易被忽略的風險,如果網站更新了 CSS 或 JavaScript,但瀏覽器快取的時間設得太長,訪客瀏覽器裡存的還是舊版檔案,畫面可能因此跑版,甚至功能失效。常見的解法是替檔名加上版本號或雜湊值,檔案內容一變,檔名跟著變,瀏覽器才會判斷這是一個全新的檔案,乖乖重新下載。

靜態資源的快取時間,該設多長?

圖片、字型這類幾乎不會變動的檔案,快取時間可以設得長一點,以年為單位也不誇張。CSS、JS 因為版本更新的頻率通常比較高,快取時間建議設短一些,並且搭配檔名加版本號的做法,讓瀏覽器只有在檔案真的變動時,才重新下載。

網站屬於哪一種情境,該優先顧哪一層快取?

三層快取的定義都拆完了,回頭看自己的網站,可以直接用下面這份檢核清單對照,不必照順序讀完才下結論,三種情境彼此獨立,符合哪一種就優先補哪一層。

內容型網站優先開頁面快取、有會員登入或購物車優先物件快取、訪客常回訪且圖檔多優先瀏覽器快取
WordPress 快取外掛怎麼選,先看網站屬於哪一種情境,就優先補上對應的那一層快取。

內容型網站、部落格、形象官網,先把頁面快取打開就好

這類網站的訪客,很高比例是第一次造訪就離開,而且每個人看到的內容都一樣。頁面快取的效益在這裡最直接,把它打開就能吃到大部分的效能紅利;物件快取與瀏覽器快取,則是錦上添花的加分項。

有會員登入、購物車、線上課程等功能,物件快取不能省

這類網站有大量無法整頁快取的個人化內容,資料庫查詢量本來就偏高。物件快取,尤其是接上 Redis 或 Memcached 之後,能直接減少反覆查詢造成的延遲,是這類網站最該優先顧的一層。

訪客常態回訪、圖片與程式檔案多,瀏覽器快取才看得出效果

常態更新的部落格、作品集網站、圖片量大的網站,回訪率通常偏高。把靜態資源的瀏覽器快取設定好,能明顯降低回訪時的載入時間,也替訪客省下重複下載的流量。

同時裝兩個快取外掛,為什麼常常互相打架?

覺得裝一款快取外掛不夠保險,再多裝一款保底,是很多人會犯的直覺錯誤,結果卻常常適得其反。WordPress 讓頁面快取生效的方式,是靠 wp-config.php 裡的 WP_CACHE 這個常數,去載入 wp-content 目錄下唯一的一支 advanced-cache.php 檔案。如果同時啟用兩款都想做「整頁快取」的外掛,兩者會搶著寫入、搶著讀取同一支檔案。結果可能是其中一款根本沒有真正生效,也可能是兩款清除快取的時機對不上,訪客因此看到舊內容,甚至頁面顯示異常。

兩款外掛都想做整頁快取時會搶著寫入 wp-content 下唯一的 advanced-cache.php,導致其一失效或清快取時機錯亂
同一層只留一款快取外掛負責,才不會兩款搶同一支 advanced-cache.php、害訪客看到舊內容。

瀏覽器快取的規則也可能出現類似的衝突。像 .htaccess 裡設定的到期時間,如果兩款外掛各自寫入一套規則,後寫入的那一套會蓋掉前一套,設定結果就不如預期。

正確的做法其實很單純,同一層,尤其是頁面快取,只留一款外掛負責;其他外掛如果有重疊的功能,像是壓縮、瀏覽器快取規則,記得手動關掉。排查的方式也不複雜,先確認同一層真的只有一款外掛在管,逐一停用測試,才找得出真正生效的是哪一款。

三種快取各自處理請求路徑上不同的一段,沒有誰能取代誰,也沒有一款外掛能自動幫你想清楚該開哪幾層。WordPress 快取外掛怎麼選,關鍵從來不是比較評價星等,而是先想清楚自己的網站卡在流程的哪一段,是每次都要重新組頁面,還是資料庫被同樣的查詢問到喘不過氣,又或者訪客回訪時該省的流量都沒省下來。想清楚之後再決定要補齊哪一層。同一層永遠只留一款負責,快取才不會彼此打架,反而拖慢原本想要加快的網站。

資料來源
  1. Cache – Advanced Administration Handbook — WordPress
  2. WP_Object_Cache Class Reference — WordPress
  3. Time to First Byte (TTFB) — web.dev