Django 靜態檔案部署爆版問題排查與解法

部署 Django 專案時,常見「靜態檔案爆版」問題:明明已經更新了 CSS/JS,使用者卻還是看到舊版畫面。這篇文章將帶你找出問題核心,並給出最佳解法。


問題現象

  • 前端樣式或 JS 更新後,使用者端仍然載入舊檔案
  • 清除瀏覽器快取後才會看到新內容
  • CDN 或 Nginx 設定了長時間快取

問題核心

Django 預設的 collectstatic 只會把檔案複製到 STATIC_ROOT,檔名不變。如果 Nginx 或 CDN 設定了 cache-control/expires,檔案內容變了但檔名沒變,使用者端就會一直拿到舊檔案。

關鍵:
只要檔名沒變,快取就不會重新抓新檔案。


解決方法

1. 啟用 ManifestStaticFilesStorage

Django 內建的 ManifestStaticFilesStorage 會在檔名自動加上 hash,只要內容有變,檔名就會變,快取自然失效。

設定方式

settings.py 加入:

STATICFILES_STORAGE = "django.contrib.staticfiles.storage.ManifestStaticFilesStorage"

2. 正確執行 collectstatic

每次部署靜態檔案有變動時,務必執行:

python manage.py collectstatic

這會自動產生帶 hash 的檔案,例如:

style.1a2b3c4d.css

3. 模板引用方式

確保模板都用 {% static 'path/to/file.css' %},Django 會自動引用帶 hash 的檔名。

4. Nginx / CDN 快取設定

可以放心設定長快取,例如:

location /static/ {
    alias /staticfiles/;
    expires 7d;
    add_header Cache-Control "public";
}

因為檔名有 hash,內容變了檔名也會變,快取不會爆版。


排查流程

  1. 確認 collectstatic 是否有執行
  2. 檢查 staticfiles 目錄下檔名是否有 hash
  3. 檢查模板是否正確用 static 標籤
  4. 檢查 Nginx/CDN 是否有快取設定
  5. 檢查瀏覽器載入的檔案路徑是否為新檔名

結論

只要啟用 ManifestStaticFilesStorage 並正確部署,Django 靜態檔案快取問題就能徹底解決。
這是現代 Django 專案部署的最佳實踐!