
訪客第一次打開你的網站時,瀏覽器會下載網頁用到的所有檔案:圖片、CSS、JavaScript、字型。瀏覽器快取就是讓瀏覽器把這些檔案存起來,下次再來、或點到第二頁時直接拿出來用,不用再跟主機要一次。
如果主機沒有告訴瀏覽器「這個檔案可以用多久」,瀏覽器常常得先問主機「檔案有沒有變」,就算答案是沒變,一來一回也要花時間。設定了有效期限之後,期限內瀏覽器連問都不用問,頁面自然就快了。
這篇把設定方法、推薦的有效期限,以及最常遇到的「改了 CSS 訪客卻看到舊版」問題整理在一起。(原本另一篇〈通過設置.htaccess給WordPress站點Leverage browser caching〉的內容已經整合到這裡。)
瀏覽器快取和快取外掛有什麼不同?
- 快取外掛(伺服器端快取):WP Rocket、LiteSpeed Cache 這類外掛,是把整頁網頁先產生好存在主機上,省掉每次執行 PHP 與查詢資料庫的時間,對每一位訪客都有幫助。
- 瀏覽器快取:檔案存在訪客的電腦或手機上,對回訪的訪客、以及同一次造訪中點開的第二、第三頁有幫助。Logo、CSS、JavaScript 每一頁都一樣,只要下載一次就好。
兩者是互相搭配,不是二選一。
Expires 與 Cache-Control 是什麼?
主機是用回應標頭(HTTP header)告訴瀏覽器檔案可以快取多久,常見的有兩個:
Expires:寫一個固定的到期時間,在這之前都有效。Cache-Control: max-age=秒數:寫「從現在起幾秒內有效」,例如max-age=31536000是一年。這是比較新的寫法,兩個同時存在時,瀏覽器以Cache-Control為準。
Cache-Control 還有幾個常見的值:
no-cache:可以存,但每次使用前都要先問主機有沒有更新。no-store:完全不要存,通常用在含有個人資料的頁面。public、private:能不能讓 CDN 等中間的快取伺服器也存一份。
Apache 的 mod_expires 模組會同時送出 Expires 與 Cache-Control: max-age,一般網站用它設定就夠了。
設定之前:先看網站現在的狀況
有些主機、快取外掛或 CDN 已經幫你設定好了,先檢查可以避免重複設定:
- 用 Chrome 打開網站,按 F12 切到「Network(網路)」分頁,確認上方的「Disable cache(停用快取)」沒有勾選。
- 重新整理頁面,點一個
.css檔或圖片。 - 在「Response Headers(回應標頭)」裡,看有沒有
cache-control的max-age,或是expires。 - 再重新整理一次,如果「Size(大小)」欄位顯示 memory cache 或 disk cache,代表這個檔案是直接從瀏覽器快取拿出來的。
Apache:用 mod_expires 設定(推薦寫法)
Apache 與 LiteSpeed 主機,在網站根目錄的 .htaccess 最上面(# BEGIN WordPress 那一行的上面)加入下面這段。改之前記得先備份原本的檔案:
<IfModule mod_expires.c>
ExpiresActive On
# 網頁與資料:每次都向主機確認有沒有新版本
ExpiresByType text/html "access plus 0 seconds"
ExpiresByType application/json "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType text/xml "access plus 0 seconds"
# RSS 訂閱
ExpiresByType application/rss+xml "access plus 1 hour"
ExpiresByType application/atom+xml "access plus 1 hour"
# CSS 與 JavaScript (網址有版本號,可以放很久)
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType text/javascript "access plus 1 year"
# 字型
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/ttf "access plus 1 year"
ExpiresByType font/otf "access plus 1 year"
# 圖片
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/webp "access plus 1 month"
ExpiresByType image/avif "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 week"
ExpiresByType image/vnd.microsoft.icon "access plus 1 week"
# 影音
ExpiresByType video/mp4 "access plus 1 month"
ExpiresByType video/webm "access plus 1 month"
ExpiresByType audio/mpeg "access plus 1 month"
</IfModule>這樣設定的理由:
- HTML、JSON、XML 設 0 秒:網頁內容隨時會更新,每次都要向主機確認,訪客才會看到最新的文章。WordPress 登入後的後台頁面會自己送出「不要快取」的標頭,這段設定不會去改動它們。
- CSS、JavaScript、字型設一年:WordPress 載入這些檔案時,網址後面會加上
?ver=版本號,主題或外掛更新時網址就會改變,瀏覽器會當成新檔案重新下載,所以可以放心設很久(自己改檔案時要注意,下面會說明)。 - 圖片設一個月:WordPress 上傳的圖片很少會用同一個檔名覆蓋,如果你確定不會這樣做,也可以延長到一年。
- RSS 設一小時、網站小圖示(favicon)設一週:兼顧更新速度與效能。
- 沒列出的檔案類型(例如 PDF)維持主機原本的行為。PDF 型錄、價目表常常用同一個檔名更新,不適合設長期快取。
外面的 IfModule 代表主機有 mod_expires 模組才會執行,萬一沒有也不會讓網站出錯。
檔案改了,訪客看到的還是舊的?用版本號解決
快取設得越久,越要注意這個問題:瀏覽器在期限內不會再問主機,你改了 CSS,訪客的瀏覽器還是拿舊檔案來用。
解決的原理很簡單:檔案內容變了,就讓網址也跟著變。瀏覽器看到新網址,會當成新檔案重新下載。
WordPress:用 ver 參數
WordPress 用 wp_enqueue_style()、wp_enqueue_script() 載入檔案時,第四個參數就是版本號,會變成網址後面的 ?ver=...。自己在子主題加的 CSS,可以用檔案的修改時間當版本號,每次存檔就會自動換成新網址。把下面這段加到子主題的 functions.php:
add_action( 'wp_enqueue_scripts', function () {
$file = get_stylesheet_directory() . '/css/custom.css';
if ( ! file_exists( $file ) ) {
return;
}
wp_enqueue_style(
'my-custom-style',
get_stylesheet_directory_uri() . '/css/custom.css',
array(),
(string) filemtime( $file )
);
} );css/custom.css 換成你實際的檔案位置。JavaScript 改用 wp_enqueue_script(),寫法相同。
其他常見情況
- 版型裡直接寫死
<link>的網站(非 WordPress、或自己寫的版型):在網址後面手動加上版本號,例如style.css?v=2,每次更新檔案就把數字加一。 - 用同一個檔名覆蓋圖片:訪客可能在快取期限內都看到舊圖。建議上傳新圖片(新檔名),再把文章裡的圖片換掉。
- 後台「外觀 → 自訂 → 附加的 CSS」:這裡的 CSS 是直接寫在網頁裡,不受瀏覽器快取影響;但如果有快取外掛,存檔後要記得清除外掛的快取。
- 自己檢查修改結果:用 Ctrl + Shift + R(Mac 是 Cmd + Shift + R)強制重新整理,瀏覽器會重新下載所有檔案。
舊版寫法為什麼要換掉
這篇文章舊版與合併進來的另一篇,程式碼都有需要修正的地方:
- 搬家時格式跑掉:原本的
IfModule、FilesMatch標籤被吃掉了,照著貼上會讓網站出現 500 錯誤。 - 過時的檔案類型:
text/x-component(只有舊版 IE 使用)、text/cache-manifest(瀏覽器已經移除的離線快取功能),以及application/font-woff2這類舊的字型類型名稱,現在都用不到或已經改名。 - 期限設反了:CSS、JavaScript 有版本號,可以放很久,舊寫法卻只設兩小時;PDF 這類常用同一個檔名更新的文件,反而設了將近一年,更新後訪客可能一直下載到舊版。
- 把所有 PHP 檔案設成
no-store:WordPress 的每一頁都是透過index.php產生,這等於整個網站的網頁都禁止快取,瀏覽器按「上一頁」時也可能無法直接使用暫存的頁面。WordPress 真正需要禁止快取的頁面(例如登入後的後台)本來就會自己處理。 Pragma: no-cache:這是 HTTP/1.0 時代的寫法,現在用Cache-Control就好。
Nginx 主機
Nginx 不讀 .htaccess,對應的寫法是:
location ~* \.(?:css|js|woff2?|ttf|otf)$ {
expires 1y;
}
location ~* \.(?:jpe?g|png|gif|webp|avif|svg|ico|mp4|webm)$ {
expires 1M;
}expires 會同時送出 Expires 與 Cache-Control: max-age,1y 是一年、1M 是一個月。Nginx 設定通常要請主機商處理;如果主機已經有處理靜態檔案的 location 設定,自己再加可能會互相衝突,出現錯誤時請主機商協助。
用 PageSpeed Insights 檢查
- 打開 PageSpeed Insights,輸入網址進行分析。
- 在診斷結果裡,找跟快取有關的項目(英文介面叫 Use efficient cache lifetimes,較早的版本叫 Serve static assets with an efficient cache policy)。
- 展開後會列出快取時間太短的檔案,以及它們目前的快取期限。
清單裡常會出現 Google Analytics、廣告、YouTube、Facebook 這類外部網站的檔案,它們的快取時間由對方決定,你沒辦法修改;只要確認自己網站的檔案沒有被列出就好。
常見問題
用了快取外掛或 Cloudflare,還需要自己設定嗎?
先用前面的方法檢查。有些快取外掛(例如 LiteSpeed Cache)有瀏覽器快取的選項,開啟後就會送出這些標頭,已經有了就不要重複設定。Cloudflare 的「瀏覽器快取 TTL」設定也可能改變最後送出的期限,兩邊的設定要一致。
網站改版之後,有訪客反映版面怪怪的?
多半是舊的 CSS 還在他的瀏覽器裡。確認新的 CSS 網址有換版本號,並清除快取外掛與 CDN 的快取;請訪客強制重新整理一次,也能馬上解決。
快取期限設多久才好?
上面推薦的期限適合大多數網站。原則是:網址會跟著內容改變的檔案(有版本號的 CSS、JavaScript),期限越長越好;網址不變、內容卻可能更新的檔案(網頁本身、PDF),不要設長期快取。
延伸閱讀
- 網站 GZIP、Brotli 壓縮總整理:Apache、Nginx、Plesk、cPanel 開啟與檢查方法
- WordPress 網站加速完整攻略:測速、主機、快取、圖片、外掛與資料庫清理
- .htaccess 用法大全:轉址、HTTPS、安全防護、壓縮與快取常用設定(WordPress 適用)
網站速度是很多小設定累積出來的,正威網路行銷是 25 年經驗的基隆網頁設計工作室,提供客製化網頁設計與網站維護託管,也服務台北與全台客戶,歡迎來聊聊。







發表留言
還沒有人留言,歡迎第一個分享你的想法或問題。留言經審核後才會顯示,Email 不會公開。