簡單的方式避免瀏覽器 cache

瀏覽器為了效能,會對 HTML、JavaScript 與 CSS 做 cache,其本意是好的,但對於 developer 來說,卻擔心更新到 production server 後,user 仍然是執行到被瀏覽器 cache 的 HTML、JavaScript 與 CSS,Angular 該如何解決這個問題呢 ?

Version


Angular 5.1

HTML


在經過 Angular CLI 的 ng build --prod 之後,會在 dist 目錄下產生整個 Angular 專案唯一的 index.html,擔心的是 user 執行到被瀏覽器 cache 的 index.html

新增 HTML Meta

src/index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>NG5HttpClient</title>
<meta http-equiv="Cache-Control" content="no-cache, no-store, max-age=0, must-revalidate">
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="expires" content="0" />
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>

第 6 行

1
2
3
<meta http-equiv="Cache-Control" content="no-cache, no-store, max-age=0, must-revalidate">
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="expires" content="0" />

新增這 3 行 <meta>

在 HTTP 1.1 規格中,有 Cache-Control 可設定瀏覽器的 cache。

在 HTTP 1.0 規格中,有 Pragma 可設定瀏覽器的 cache。

而 HTTP 1.0 與 1.1 都有 Expires 設定 cache 內容的有效期限,但在 1.1 的規格中,Cache-Control 的優先權是大於 Expires,因此可以規劃出以上通用設定,就可避免 index.html 被瀏覽器 cache。

cache000

  1. 開啟 src 目錄下的 index.html
  2. 加入 3 行 <meta>

編譯 Angular

1
~/MyProject $ ng build --prod

要放進 production server 的 code,最後會加上 --prod

cache001

編譯後的 index.html

經過 ng build --prod 之後的 HTML、JavaScript 與 CSS 都會放在 dist 目錄下。

cache002

  1. 選擇 dist 目錄
  2. 選擇 index.html,這是最後會上 production server 的 index.html
  3. 我們剛剛加入的 3 個 <meta> 都還留著,因此不用每次編譯就修改 index.html

只要改一次 src/index.html<meta>,之後就不用擔心 HTML 被瀏覽器 cache 的問題

JavaScript


JavaScript 若檔名相同,瀏覽器會優先選擇使用本地的 cache 增加效能,Angular CLI 在每次 ng build --prod 之後,會重新以亂數命名 JavaScript 檔案,因此瀏覽器只能重新對 server 抓 *.js,而不會採用瀏覽器的 cache。

cache003

所有經過 ng build --prod 所 bundle 的 JavaScript 都經過亂數改掉檔名,因此瀏覽器一定會再跟 server 要新的 JavaScript。

cache005

Angular CLI 會幫我們將所引用的 JavaScript 一併改名。

CSS


CSS 若檔名相同,瀏覽器會優先選擇使用本地的 cache 增加效能,Angular CLI 在每次 ng build --prod 之後,會重新以亂數命名 CSS 檔案,因此瀏覽器只能重新對 server 抓 *.css,而不會採用瀏覽器的 cache。

cache004

所有經過 ng build --prod 所 bundle 的 CSS 都經過亂數改掉檔名,因此瀏覽器一定會再跟 server 要新的 CSS。

cache006

Angular CLI 會幫我們將所引用的 CSS 一併改名。

Conclusion


  • 在開發階段時,完全不用擔心 HTML、JavaScript 與 CSS 被瀏覽器 cache 問題,Angular CLI 內建的 web server 已經幫我們處理
  • 由於 JavaScript 並沒有提供 <meta> 機制,因此若將 JavaScript 獨立於 HTML,就必須面臨 JavaScript 可能被瀏覽器 cache 的問題,Angular CLI 已經幫我們處理了 JavaScript 與 CSS,我們唯一需要處理的只剩下 HTML 部分,所幸 HTML 部分可簡單的用 <meta> 處理即可

Reference


Poy Chang, 在 Angular 網站中取消瀏覽器快取功能

2018-02-17