你把新文章部署上去,自己看得到最新版,讀者卻還在看昨天的內容?先別急著重跑 11ty,也別一杯接一杯咖啡地清快取。很多時候,問題不是建置失敗,而是瀏覽器、Hostinger、CDN 或 HTTP headers 還在提供舊檔案。
這篇會用一套實際設定,帶你分開處理 HTML、CSS、JavaScript、圖片、字型和 Pagefind 搜尋索引,最後用 curl 驗收更新是否真的生效。
目錄
先記住這個快取原則
不要把所有檔案都快取一年。比較穩定的分法是:
- HTML:短時間快取,或要求瀏覽器重新驗證,因為文章和首頁會更新。
- CSS、JavaScript、圖片、字型:如果檔名包含版本號或內容指紋,可以長效快取。
- Pagefind 搜尋資產:搜尋索引會隨文章更新,通常要比一般靜態資產更快失效。
簡單說,內容頁要容易更新;URL 已經跟著內容改變的資產,才適合快取久一點。
11ty 與 Hostinger 各自負責什麼?
11ty 負責把 Markdown、模板和資產建置成 _site 裡的靜態檔案。它不會替你決定訪客的瀏覽器或 Hostinger CDN 要快取多久。
上線後的快取主要分成三層:
| 快取層級 | 作用 | 更新不生效時先檢查什麼 |
|---|---|---|
| 瀏覽器 | 減少訪客重複下載檔案 | 用無痕視窗測試 |
| Hostinger | 減少來源站重複處理請求 | hPanel 的 Cache Manager |
| CDN | 讓訪客從較近的節點取得檔案 | Flush/Purge CDN 快取 |
所以,重新執行 11ty 只會更新輸出檔案,不能保證所有快取層立刻換成新版本。
部署前先確認 _site
在專案根目錄執行:
npx @11ty/eleventy接著確認 _site 裡有:
_site/index.html- 最新文章的 HTML
- CSS 和 JavaScript
- 圖片與字型
- Pagefind 搜尋索引(如果網站有使用 Pagefind)
上傳時,要把 _site 裡面的內容放到 Hostinger 的網站根目錄,常見位置是 public_html。不要把整個專案原始碼上傳到公開目錄,也不要多包一層 _site 資料夾。
在 public/.htaccess 設定快取
目前網站使用 public/.htaccess 管理 Apache 的過期時間與 response headers。實際設定分成 mod_expires、mod_headers 和 mod_setenvif 幾個區塊。注意:不是所有圖片和字型都會拿到一年快取,真正的範圍由 <FilesMatch> 的副檔名規則決定。
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 2 days"
ExpiresByType text/html "access plus 1 day"
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 "\.(?: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 "public, max-age=86400" env=pagefind_asset
</IfModule>這些設定分別做什麼?
ExpiresActive On:啟用 Apache 的過期時間設定。ExpiresDefault "access plus 2 days":沒有特別指定類型的檔案,預設快取兩天。ExpiresByType text/html "access plus 1 day":HTML 快取一天,讓文章與首頁不會長時間卡在舊版本。- CSS、JavaScript、圖片和字型的
ExpiresByType:先設定為快取一個月。 Cache-Control: public, max-age=31536000, immutable:把符合檔名規則的 CSS、JavaScript、部分圖片、圖示與 woff 字型實際設定為快取一年。SetEnvIfNoCase Request_URI "^/pagefind/" pagefind_asset:找出/pagefind/開頭的檔案。Header set Cache-Control "public, max-age=86400" 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: public, max-age=86400這個例外很重要:一般資產可以快取一年,但搜尋索引不應該跟著使用同樣長的 TTL。
Header需要 Apachemod_headers,ExpiresByType需要mod_expires,Pagefind 的環境變數需要mod_setenvif。如果修改.htaccess後出現 500 錯誤,先還原修改,再逐段確認 Hostinger 是否支援相關模組與語法。
除了快取,.htaccess 還能負責哪些事情?
.htaccess 不只是快取設定檔,也可以集中管理 Apache 網站常見的伺服器規則。以下功能不一定全部都要啟用,應依網站需求和主機支援的 Apache 模組決定:
- 靜態網站路由:使用
mod_rewrite將找不到實體檔案或目錄的請求導向入口頁,例如/index.html。如果網站使用 11ty 產生檔案式路由,才需要採用符合專案結構的 rewrite 規則。 - 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。
- 如果只有單一頁面或 URL 過期,到 Advanced → Cache Manager 清除指定 URL。
- 如果網站啟用了 Hostinger CDN,進入 CDN 設定執行 Flush/Purge。
- 用無痕視窗重新開啟首頁和剛更新的文章。
不要一開始只清除自己的瀏覽器快取。如果所有訪客都看到舊版本,問題更可能在 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。
首頁應該看到短 TTL 或要求重新驗證的設定;版本化 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 一天;其他資產依版本策略 | 避免搜尋結果長時間不完整 |
| CDN 剛啟用或剛清除 | 短 TTL | 依 CDN 規則 | 等待節點更新,再用不同網路測試 |
這張表主要根據兩個問題決定快取時間:檔案多久會更新,以及檔案的 URL 是否會隨內容改變。
- HTML 通常使用短 TTL:首頁和文章內容可能經常更新,因此使用
no-cache或短時間快取,讓瀏覽器重新向伺服器確認。no-cache不是完全不儲存檔案,而是使用快取前必須重新驗證。 - 有內容指紋的靜態資產可以快取一年:例如
app.8f31c.css。CSS 或 JavaScript 更新後,檔名也會改變,瀏覽器會把它視為全新的檔案,因此適合搭配immutable使用一年 TTL。 - 固定檔名的資產應使用短 TTL:例如
style.css或app.js。如果內容更新但 URL 不變,長效快取可能讓訪客持續取得舊檔案;在尚未完成版本化時,可先使用 5–30 分鐘。 - Pagefind 使用一天 TTL:搜尋索引會隨文章更新,但 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 是否真的使用一天 TTL,最後清除 Hostinger 或 CDN 快取。
改 .htaccess 後網站出現 500 怎麼辦?
先還原最後一次修改,確認 Hostinger 支援 mod_headers、mod_expires 和相關語法,再逐段加入設定。不要在未驗證前,直接把同一份 .htaccess 複製到其他網站。
推薦工具/資源
- Hostinger hPanel:適合已經把 11ty 靜態站部署到 Hostinger,需要管理 Cache Manager、CDN 或網站根目錄的站長。若你正在選擇支援靜態網站部署與 hPanel 的主機,可參考 Hostinger 主機服務 →。
curl:免費且適合直接查看公開網站的 response headers,先用它確認伺服器實際回傳什麼,再判斷是不是瀏覽器問題。- Chrome DevTools Network:適合查看
Age、ETag、Cache-Control和 response body,確認不同資產是否使用了預期的 TTL。
結語:先分層,再決定 TTL
11ty 快取問題的重點不是把數字設得越大越好,而是讓不同檔案採用適合自己的更新策略:
- HTML 保持容易重新驗證。
- 版本化 CSS、JavaScript、圖片和字型使用長效快取。
- Pagefind 搜尋資產縮短到一天,避免索引更新被卡住。
- 每次部署後用 hPanel、
curl和無痕視窗驗收。
完成設定後,下一步是到 Hostinger hPanel 清除快取,再用 curl -I 確認公開網站真的回傳預期的 headers:先到 Hostinger 管理你的靜態網站與快取 →。

