你把新文章部署上去,自己看得到最新版,讀者卻還在看昨天的內容?先別急著重跑 11ty,也別一杯接一杯咖啡地清快取。很多時候,問題不是建置失敗,而是瀏覽器、Hostinger、CDN 或 HTTP headers 還在提供舊檔案。
這篇會帶你用 11ty 建置 _site,再依檔案類型安排 HTML、CSS、JavaScript、圖片、字型和 Pagefind 搜尋資產的快取策略。你也會看到如何在 Hostinger hPanel 清除快取,以及用 curl 檢查公開網站實際回傳的 headers。快取不是壞掉的記憶體,只是它記得比你久了一點。
目錄
先記住快取原則
不要把所有檔案都快取一年。比較穩定的分法是:
- HTML:短時間快取,或要求瀏覽器重新驗證,因為文章和首頁會更新。
- CSS、JavaScript、圖片、字型:如果檔名包含版本號或內容指紋,可以長效快取。
- Pagefind 搜尋資產:搜尋索引會隨文章更新,不能直接套用一般靜態資產的一年 TTL。
簡單說,內容頁要容易更新;URL 已經跟著內容改變的資產,才適合快取久一點。
11ty 與 Hostinger 各自負責什麼?
11ty 負責把 Markdown、模板和資產建置成 _site 裡的靜態檔案。它不會替你決定訪客的瀏覽器或 Hostinger CDN 要快取多久。
上線後的快取主要分成三層:
| 快取層級 | 作用 | 更新不生效時先檢查什麼 |
|---|---|---|
| 瀏覽器 | 減少訪客重複下載檔案 | 用無痕視窗測試 |
| Hostinger 快取 | 減少來源站重複處理請求 | hPanel 的 Clear cache 或 Cache Manager |
| CDN | 讓訪客從較近的節點取得檔案 | 依 CDN 介面執行 Purge/Flush |
所以,重新執行 11ty 只會更新輸出檔案,不能保證所有快取層立刻換成新版本。
部署前先確認 _site
在專案根目錄執行:
npx @11ty/eleventy本專案的 pnpm run build 還會在 Eleventy 完成後執行 Pagefind,並寫入 _site/pagefind/。如果只是先檢查 Eleventy 輸出,可以執行上面的指令;正式部署則建議直接執行:
pnpm run build接著確認 _site 裡有:
_site/index.html- 最新文章的 HTML
- CSS 和 JavaScript
- 圖片與字型
pagefind/搜尋資產(如果網站有使用 Pagefind)
上傳時,要把 _site 裡面的內容放到 Hostinger 的網站根目錄,常見位置是 public_html。不要把整個專案原始碼上傳到公開目錄,也不要多包一層 _site 資料夾。
依專案設定 public/.htaccess
本專案的 public/.htaccess 使用 Apache 的 mod_expires、mod_headers 和 mod_setenvif 管理快取與 response headers。下面是與目前設定相同的重點片段;完整檔案還包含重新導向、安全標頭、Gzip 和目錄列表設定。
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 5 minutes"
ExpiresByType text/html "access plus 3 minutes"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType application/x-javascript "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/webp "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType font/ttf "access plus 1 month"
ExpiresByType font/otf "access plus 1 month"
ExpiresByType font/woff "access plus 1 month"
ExpiresByType font/woff2 "access plus 1 month"
</IfModule>
<IfModule mod_headers.c>
<FilesMatch "\.(?:html?)$">
Header set Cache-Control "public, max-age=180"
</FilesMatch>
<FilesMatch "\.(?:css|js|gif|jpe?g|png|webp|svg|ico|woff2?)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>
<IfModule mod_setenvif.c>
SetEnvIfNoCase Request_URI "^/pagefind/" pagefind_asset
</IfModule>
<IfModule mod_headers.c>
Header set Cache-Control "no-cache, must-revalidate" env=pagefind_asset
</IfModule>這些設定分別做什麼?
ExpiresActive On:啟用 Apache 的過期時間設定。ExpiresDefault "access plus 5 minutes":沒有特別指定類型的檔案,預設快取五分鐘。ExpiresByType text/html "access plus 3 minutes":HTML 的Expires基準為三分鐘。- CSS、JavaScript、圖片和字型的
ExpiresByType:先設定為快取一個月,之後資產規則會再設定明確的Cache-Control。 Cache-Control: public, max-age=31536000, immutable:把符合檔名規則的 CSS、JavaScript、部分圖片、圖示與 woff 字型實際設定為快取一年。SetEnvIfNoCase Request_URI "^/pagefind/" pagefind_asset:找出/pagefind/開頭的檔案。Header set Cache-Control "no-cache, must-revalidate" env=pagefind_asset:讓 Pagefind 更新後立即重新驗證。Strict-Transport-Security:不是檔案快取,而是告訴瀏覽器未來一年都使用 HTTPS;目前也包含includeSubDomains。
一年快取有一個容易忽略的風險
目前的 <FilesMatch> 是按照副檔名套用一年快取,並沒有檢查檔名是否真的含有內容雜湊。因此沒有版本號的 style.css 或 app.js 也會進入一年快取。如果這些檔案在原 URL 直接更新,訪客可能長時間拿到舊版本。
另一方面,mjs、avif、ttf 和 otf 雖然有一個月的 ExpiresByType,卻不符合目前的 <FilesMatch>,不會拿到一年期的 Cache-Control。要維持一年 TTL,部署流程就必須確保資產 URL 會隨內容改變,或另外為未版本化資產加上較短的規則。
為什麼 Pagefind 需要單獨設定?
Pagefind 的檔案可能同時符合一般 JavaScript 或資產檔案規則,因此先拿到一年的長效快取。接著,env=pagefind_asset 條件會再套用重新驗證的 Cache-Control:
Cache-Control: no-cache, must-revalidate這個例外很重要:一般資產可以快取一年,但搜尋索引不應該跟著使用同樣長的 TTL。
Header需要 Apachemod_headers,ExpiresByType需要mod_expires,Pagefind 的環境變數需要mod_setenvif。如果修改.htaccess後出現 500 錯誤,先還原修改,再逐段確認 Hostinger 是否支援相關模組與語法。
除了快取,.htaccess 還能負責哪些事情?
.htaccess 不只是快取設定檔,也可以集中管理 Apache 網站常見的伺服器規則。以下功能不一定全部都要啟用,應依網站需求和主機支援的 Apache 模組決定:
- 靜態網站路由:使用
mod_rewrite管理重新導向或找不到頁面的處理方式。11ty 已經產生檔案式路由時,不要直接套用 SPA 的「全部導向/index.html」規則,否則原本的 404 和文章路徑可能一起被煮成一鍋。 - 301 重新導向:將舊網址導向新網址,適合網站改版、文章改名或網址結構變更時使用。大量重定向最好由腳本產生,避免手動維護時遺漏或重複。
- 安全標頭:可設定
X-Frame-Options、X-Content-Type-Options等 response headers,降低點擊劫持和 MIME 類型嗅探等風險。新增標頭前,應先確認不會影響網站嵌入或第三方服務。 - Gzip 壓縮:使用
mod_deflate壓縮 HTML、CSS、JavaScript 和 XML 等文字檔,減少傳輸量。JPEG、PNG、WebP 等通常已經壓縮,不需要再次壓縮。 - 目錄保護:
Options -Indexes可避免訪客直接看到沒有首頁檔案的資料夾列表。 - HTTP 導向 HTTPS:使用
mod_rewrite將 HTTP 請求重新導向 HTTPS。啟用前要先確認 SSL 憑證正常;HSTS 只會要求瀏覽器後續使用 HTTPS,不會代替 HTTP → HTTPS 的重新導向。
修改 .htaccess 前,先確認 Hostinger 支援所需的 Apache 模組與語法。建議一次只加入一個功能,修改後用 curl -I 和瀏覽器測試;若出現 500 錯誤,先還原最近一次修改,再逐段排查。
HSTS 不是檔案快取
這一行:
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"意思是瀏覽器在接下來一年內,連線到這個網站時優先使用 HTTPS。它不會決定 HTML、CSS 或圖片要存多久,因此不要把 HSTS 和 Cache-Control 當成同一種設定。
只有在 HTTPS 已經完全正常,而且所有會使用到的子網域也都能使用 HTTPS 時,才適合啟用較長的 HSTS 期限。
部署後到 hPanel 清除快取
每次部署後,依序做以下檢查:
- 進入 Hostinger hPanel 的網站 Dashboard,執行 Clear cache。不同方案或 hPanel 版本的選單名稱可能略有不同。
- 如果只想處理單一頁面,到 Advanced → Cache Manager 輸入 URL 後執行 Purge。
- 如果網站啟用了 Hostinger CDN,到 Performance → CDN 檢查 CDN 狀態,並依介面提供的選項清除快取。
- 用無痕視窗重新開啟首頁和剛更新的文章。
不要一開始只清除自己的瀏覽器快取。如果所有訪客都看到舊版本,問題更可能在 Hostinger 快取、CDN 或部署檔案,而不是單一瀏覽器。
用 curl 驗收 response headers
檢查首頁:
curl -I https://example.com/檢查一個版本化資產:
curl -I https://example.com/assets/app.8f31c.css你可以觀察 Cache-Control、Expires、ETag、Last-Modified、Age 和 Content-Type。
依本專案目前設定,首頁通常會看到三分鐘的 max-age;符合資產副檔名規則的 CSS 則可能看到一年的 max-age。Pagefind URL 則應該要求重新驗證:
curl -I https://example.com/pagefind/pagefind.js如果重新請求時內容沒有改變,伺服器可能回傳 304 Not Modified,代表條件式快取正常運作。若 curl 已經拿到新內容,但瀏覽器仍是舊內容,再用無痕視窗、另一個網路和 DevTools Network 交叉確認。
快取設定決策表
| 你的情況 | HTML | CSS/JS/圖片/字型 | 建議 |
|---|---|---|---|
| 文章常更新,檔名沒有版本號 | no-cache 或短 TTL | 短 TTL,例如 5–30 分鐘 | 先確保更新穩定,再逐步延長 |
| CSS/JS 有內容指紋 | no-cache 或一天 | 一年+immutable | 適合穩定的 production 靜態站 |
| 正在除錯快取問題 | no-cache | no-cache 或短 TTL | 驗收完成後再恢復長效快取 |
| Pagefind 搜尋索引會更新 | 短 TTL | Pagefind 使用 no-cache;其他資產依版本策略 | 避免搜尋索引長時間未更新 |
| CDN 剛啟用或剛清除 | 短 TTL | 依 CDN 規則 | 等待節點更新,再用不同網路測試 |
這張表主要根據兩個問題決定快取時間:檔案多久會更新,以及檔案的 URL 是否會隨內容改變。
- HTML 通常使用短 TTL:首頁和文章內容可能經常更新,因此使用短時間快取,讓瀏覽器較快向伺服器確認。本專案目前設定為三分鐘;
no-cache則是另一種要求使用前重新驗證的策略。 - 有內容指紋的靜態資產可以快取一年:例如
app.8f31c.css。CSS 或 JavaScript 更新後,檔名也會改變,瀏覽器會把它視為全新的檔案,因此適合搭配immutable使用一年 TTL。 - 固定檔名的資產應使用短 TTL:例如
style.css或app.js。如果內容更新但 URL 不變,長效快取可能讓訪客持續取得舊檔案;在尚未完成版本化時,可先使用 5–30 分鐘。 - Pagefind 使用
no-cache:搜尋索引會隨文章更新,但 URL 通常不一定包含內容指紋,因此每次使用前都應重新驗證。 - 正在除錯時全部縮短 TTL:先讓 HTML、CSS 和 JavaScript 使用
no-cache或短 TTL,確認部署與 response headers 正常後,再恢復長效快取。
要注意的是,這張表是判斷原則,不代表目前 .htaccess 已經自動檢查檔名是否含有內容指紋。目前的 <FilesMatch> 是按照副檔名設定一年快取,所以固定名稱的 style.css 或 app.js 也可能被快取一年。只有在部署流程確實會讓資產 URL 隨內容改變時,才適合使用一年 TTL 和 immutable。
常見問題
重新建置後,網站為什麼還是舊頁面?
先確認 _site 裡真的有新內容,再確認上傳的是 _site 內容,而不是原始 Markdown。接著依序檢查 Hostinger 快取、CDN 和瀏覽器,不要只重跑 11ty。
可以把所有檔案都設定成快取一年嗎?
不建議。沒有版本化的 HTML、style.css 或 app.js 可能長時間讓訪客拿到舊內容。只有 URL 會隨內容改變的資產,才適合搭配 immutable 使用一年 TTL。
為什麼 Pagefind 搜尋不到剛發布的文章?
可能是 Pagefind 索引本身沒有重新建置,也可能是 /pagefind/ 資產仍被舊快取提供。先確認部署輸出有最新索引,再用 curl -I 檢查 Pagefind URL 是否真的要求重新驗證,最後清除 Hostinger 或 CDN 快取。
改 .htaccess 後網站出現 500 怎麼辦?
先還原最後一次修改,確認 Hostinger 支援 mod_headers、mod_expires 和相關語法,再逐段加入設定。不要在未驗證前,直接把同一份 .htaccess 複製到其他網站。
部署驗收工具
- Hostinger hPanel:用來清除網站快取、管理 Cache Manager,以及依方案管理 CDN。
curl:直接查看公開網站的 response headers,先確認伺服器實際回傳什麼,再判斷是不是瀏覽器問題。- Chrome DevTools Network:查看
Age、ETag、Cache-Control和 response body,交叉確認不同資產是否使用預期的 TTL。
結語:先分層,再決定 TTL
11ty 快取問題的重點不是把數字設得越大越好,而是讓不同檔案採用適合自己的更新策略:
- HTML 使用短 TTL,保持容易更新。
- 版本化 CSS、JavaScript、圖片和字型使用長效快取。
- Pagefind 搜尋資產使用
no-cache,避免索引更新被卡住。 - 每次部署後用 hPanel、
curl和無痕視窗驗收。
完成設定後,下一步是到 Hostinger hPanel 清除快取,再用 curl -I 確認公開網站真的回傳預期的 headers。快取驗收完,再來一杯咖啡;這次咖啡和 HTML 都應該是熱的。
參考資料
- Apache
mod_expires官方文件:說明ExpiresActive、ExpiresDefault和ExpiresByType如何產生快取標頭。 - Apache
mod_headers官方文件:查閱.htaccess中設定與修改 response headers 的Header指令。 - Pagefind Running Pagefind:說明在靜態網站建置後產生
pagefind/搜尋資產的流程。 - Hostinger:Website caching explained:說明 hPanel Cache Manager、瀏覽器快取、伺服器快取與 CDN 的差異。

