本主題說明 Service Worker 設定檔的各項屬性。
修改設定
ngsw-config.json 這個 JSON 設定檔,指定 Angular Service Worker 應該快取哪些檔案與資料 URL,以及應該如何更新已快取的檔案與資料。
Angular CLI 會在 ng build 期間處理這個設定檔。
所有檔案路徑都必須以 / 開頭,這對應到部署目錄——在 CLI 專案中通常是 dist/<project-name>。
除非另有註解,否則模式使用一種 limited* glob 格式,在內部會轉換成正規表示式:
| Glob 格式 | 詳細說明 |
|---|---|
** |
符合 0 個或多個路徑區段 |
* |
符合 0 個或多個字元(不含 /) |
? |
恰好符合一個字元(不含 /) |
! 前綴 |
把模式標示為否定,意思是只包含不符合該模式的檔案 |
特殊字元需要跳脫
請注意,在正規表示式中具有特殊意義的某些字元不會被跳脫,而且在內部的 glob 轉正規表示式過程中,模式也不會被包在 ^/$ 中。
$ 是正規表示式中的特殊字元,符合字串的結尾,在把 glob 模式轉換成正規表示式時不會自動跳脫。
如果你想逐字符合 $ 字元,你必須自行跳脫它(使用 \\$)。例如,glob 模式 /foo/bar/$value 會產生一個無法符合的表示式,因為一個字串在結束之後不可能再有任何字元。
在轉換成正規表示式時,模式不會自動被包在 ^ 與 $ 中。因此,這些模式只會部分符合請求的 URL。
如果你想讓模式符合 URL 的開頭與/或結尾,你可以自行加入 ^/$。例如,glob 模式 /foo/bar/*.js 會同時符合 .js 與 .json 檔案。如果你只想符合 .js 檔案,請使用 /foo/bar/*.js$。
模式範例:
| 模式 | 詳細說明 |
|---|---|
/**/*.html |
指定所有 HTML 檔案 |
/*.html |
只指定根目錄中的 HTML 檔案 |
!/**/*.map |
排除所有 sourcemap |
Service Worker 設定屬性
以下各節說明設定檔的每一項屬性。
appData
這一節讓你可以傳入任何想傳的資料,用來描述應用程式的這個特定版本。
SwUpdate 服務會把該資料包含在更新通知中。
許多應用程式使用這一節提供額外資訊,用來顯示 UI 彈出視窗,通知使用者有可用更新。
index
指定作為索引頁面來滿足導覽請求的檔案。
通常是 /index.html。
assetGroups
_資產_是應用程式版本的一部分、會隨應用程式一起更新的資源。 它們可以包括從頁面來源載入的資源,以及從 CDN 與其他外部 URL 載入的第三方資源。 由於並非所有這類外部 URL 在建置時都已知,因此可以使用 URL 模式來進行符合比對。
HELPFUL: 若要讓 Service Worker 處理從不同來源載入的資源,請確定每個來源的伺服器都已正確設定 CORS。
這個欄位包含一個資產群組陣列,每個群組都定義一組資產資源,以及快取它們所依據的政策。
{
"assetGroups": [
{
…
},
{
…
}
]
}
HELPFUL: 當 ServiceWorker 處理一個請求時,它會依資產群組在 ngsw-config.json 中出現的順序來檢查。
第一個符合所請求資源的資產群組會處理該請求。
建議把較具體的資產群組放在清單較前面的位置。
例如,符合 /foo.js 的資產群組,應該出現在符合 *.js 的群組之前。
每個資產群組都同時指定一組資源,以及管理這些資源的政策。 這個政策決定資源何時被擷取,以及偵測到變更時會發生什麼事。
資產群組遵循這裡所示的 TypeScript 介面:
interface AssetGroup {
name: string;
installMode?: 'prefetch' | 'lazy';
updateMode?: 'prefetch' | 'lazy';
resources: {
files?: string[];
urls?: string[];
};
cacheQueryOptions?: {
ignoreSearch?: boolean;
};
}
每個 AssetGroup 由以下資產群組屬性定義。
name
name 是必填的。
它在設定的各版本之間識別這個特定的資產群組。
installMode
installMode 決定這些資源最初如何被快取。
installMode 可以是兩個值之一:
| 值 | 詳細說明 |
|---|---|
prefetch |
告訴 Angular Service Worker,在它快取應用程式目前版本的同時,擷取每一個列出的資源。這會大量消耗頻寬,但能確保資源在被請求時隨時可用,即使瀏覽器目前離線也一樣。 |
lazy |
不預先快取任何資源。Angular Service Worker 只會快取它收到請求的資源。這是一種隨選快取模式。從未被請求的資源不會被快取。這適用於不同解析度的圖片這類情境,讓 Service Worker 只快取符合特定螢幕與方向的正確資產。 |
預設值為 prefetch。
updateMode
對於已經在快取中的資源,updateMode 決定在發現應用程式新版本時的快取行為。
群組中自前一版本以來已變更的任何資源,都會依 updateMode 來更新。
| 值 | 詳細說明 |
|---|---|
prefetch |
告訴 Service Worker 立即下載並快取已變更的資源。 |
lazy |
告訴 Service Worker 不要快取這些資源。它會把它們視為未被請求,並等到它們再次被請求時才更新。updateMode 為 lazy 只有在 installMode 也是 lazy 時才有效。 |
預設值為 installMode 所設定的值。
resources
這一節說明要快取的資源,細分如下列群組:
| 資源群組 | 詳細說明 |
|---|---|
files |
列出符合發行目錄中檔案的模式。這些可以是單一檔案,或是符合多個檔案的類 glob 模式。 |
urls |
包括在執行階段進行比對的 URL 與 URL 模式。這些資源不會被直接擷取,也沒有內容雜湊,而是依其 HTTP 標頭來快取。這對 Google Fonts 服務這類 CDN 最有用。 (不支援否定 glob 模式,且 ? 會逐字比對;也就是說,它不會符合 ? 以外的任何字元。) |
cacheQueryOptions
這些選項用來修改請求的比對行為。
它們會傳給瀏覽器的 Cache#match 函式。
詳情請參閱 MDN。
目前只支援以下選項:
| 選項 | 詳細說明 |
|---|---|
ignoreSearch |
忽略查詢參數。預設值為 false。 |
dataGroups
與資產資源不同,資料請求不會隨應用程式一起版控。 它們會依手動設定的政策來快取,這類政策對 API 請求與其他資料相依性等情境更有用。
這個欄位包含一個資料群組陣列,每個群組都定義一組資料資源,以及快取它們所依據的政策。
{
"dataGroups": [
{
…
},
{
…
}
]
}
HELPFUL: 當 ServiceWorker 處理一個請求時,它會依資料群組在 ngsw-config.json 中出現的順序來檢查。
第一個符合所請求資源的資料群組會處理該請求。
建議把較具體的資料群組放在清單較前面的位置。
例如,符合 /api/foo.json 的資料群組,應該出現在符合 /api/*.json 的群組之前。
資料群組遵循這個 TypeScript 介面:
export interface DataGroup {
name: string;
urls: string[];
version?: number;
cacheConfig: {
maxSize: number;
maxAge: string;
timeout?: string;
refreshAhead?: string;
strategy?: 'freshness' | 'performance';
};
cacheQueryOptions?: {
ignoreSearch?: boolean;
};
}
每個 DataGroup 由以下資料群組屬性定義。
name
與 assetGroups 類似,每個資料群組都有一個 name,用來唯一識別它。
urls
URL 模式的清單。 符合這些模式的 URL 會依這個資料群組的政策來快取。 只有非變更型的請求(GET 與 HEAD)會被快取。
- 不支援否定 glob 模式
?會逐字比對;也就是說,它_只_符合?字元
version
API 有時會以不向後相容的方式變更格式。 應用程式的新版本可能與舊的 API 格式不相容,因此也可能與來自該 API 的既有快取資源不相容。
version 提供一種機制,指出正在快取的資源已以不向後相容的方式更新,而舊的快取項目——也就是來自先前版本的項目——應該被捨棄。
version 是一個整數欄位,預設值為 1。
cacheConfig
以下屬性定義符合的請求被快取所依據的政策。
maxSize
快取中項目或回應的最大數量。
CRITICAL: 無上限的快取可能以無限制的方式增長,最終超過儲存配額,導致快取被清除。
maxAge
maxAge 參數指出回應在被視為無效並清除之前,可以在快取中保留多久。maxAge 是一個持續時間字串,使用以下單位後綴:
| 後綴 | 詳細說明 |
|---|---|
d |
天 |
h |
小時 |
m |
分鐘 |
s |
秒 |
u |
毫秒 |
例如,字串 3d12h 表示把內容快取最多三天半。
timeout
這個持續時間字串指定網路逾時。
網路逾時是指在設定如此做的情況下,Angular Service Worker 在改用已快取回應之前,等待網路回應的時間。
timeout 是一個持續時間字串,使用以下單位後綴:
| 後綴 | 詳細說明 |
|---|---|
d |
天 |
h |
小時 |
m |
分鐘 |
s |
秒 |
u |
毫秒 |
例如,字串 5s30u 相當於五秒又 30 毫秒的網路逾時。
refreshAhead
這個持續時間字串指定在已快取資源到期之前的多久,Angular Service Worker 應該主動嘗試從網路重新整理該資源。
refreshAhead 持續時間是一個可選設定,決定 Service Worker 應該在已快取回應到期前多久,從網路發起請求來重新整理該資源。
| 後綴 | 詳細說明 |
|---|---|
d |
天 |
h |
小時 |
m |
分鐘 |
s |
秒 |
u |
毫秒 |
例如,字串 1h30m 相當於到期時間前一小時又 30 分鐘。
strategy
Angular Service Worker 對資料資源可以使用兩種快取策略之一。
| 快取策略 | 詳細說明 |
|---|---|
performance |
預設策略,針對儘可能快的回應進行最佳化。如果資源存在於快取中,就使用已快取的版本,不發出網路請求。這會以更好的效能換取一定程度的過時(視 maxAge 而定)。這適用於不常變更的資源;例如,使用者頭像圖片。 |
freshness |
針對資料的即時性進行最佳化,優先從網路擷取所請求的資料。只有在網路逾時(依 timeout 而定)時,請求才會退回使用快取。這適用於經常變更的資源;例如,帳戶餘額。 |
HELPFUL: 你也可以模擬第三種策略,staleWhileRevalidate,它會在已有快取資料時回傳快取資料,但同時在背景從網路擷取新資料,供下次使用。
若要使用這個策略,請在 cacheConfig 中把 strategy 設為 freshness,把 timeout 設為 0u。
這基本上會執行以下動作:
- 先嘗試從網路擷取。
- 如果網路請求沒有立即完成,也就是在 0 ms 的逾時之後,忽略快取年齡並退回使用已快取的值。
- 網路請求完成後,更新快取供未來請求使用。
- 如果資源不存在於快取中,無論如何都等待網路請求。
cacheOpaqueResponses
Angular Service Worker 是否應該快取不透明回應。
如果未指定,預設值取決於資料群組所設定的策略:
| 策略 | 詳細說明 |
|---|---|
使用 freshness 策略的群組 |
預設值為 true,Service Worker 會快取不透明回應。這些群組每次都會請求資料,只有在離線或網路緩慢時才退回使用已快取的回應。因此,Service Worker 是否快取了一個錯誤回應並不重要。 |
使用 performance 策略的群組 |
預設值為 false,Service Worker 不會快取不透明回應。這些群組會持續回傳已快取的回應,直到 maxAge 到期為止,即使錯誤是因為暫時的網路或伺服器問題也一樣。因此,Service Worker 若快取了錯誤回應,就會造成問題。 |
關於不透明回應的說明
如果你不熟悉,不透明回應是一種特殊類型的回應,在請求位於不同來源、且該來源不回傳 CORS 標頭的資源時回傳。
不透明回應的特性之一是,Service Worker 不被允許讀取它的狀態,意思是它無法檢查請求是否成功。
更多詳細資訊,請參閱 fetch() 簡介。
如果你無法實作 CORS——例如,你無法控制該來源——對於會產生不透明回應的資源,請優先使用 freshness 策略。
cacheQueryOptions
詳情請參閱 assetGroups。
navigationUrls
這個可選的區段讓你可以指定一份自訂的 URL 清單,這些 URL 會重新導向到索引檔案。
處理導覽請求
ServiceWorker 會把不符合任何 asset 或 data 群組的導覽請求,重新導向到指定的索引檔案。
符合以下條件的請求會被視為導覽請求:
- 它的方法是
GET - 它的模式是
navigate - 依
Accept標頭的值判斷,它接受text/html回應 - 它的 URL 符合以下條件:
- URL 的最後一個路徑區段不能包含副檔名(也就是
.) - URL 不能包含
__
- URL 的最後一個路徑區段不能包含副檔名(也就是
HELPFUL: 若要設定導覽請求是否要送往網路,請參閱 navigationRequestStrategy 一節與 applicationMaxAge 一節。
比對導覽請求 URL
雖然這些預設條件在大多數情況下都適用,但有時你會想設定不同的規則。 例如,你可能會想忽略特定的路由,例如不屬於 Angular 應用程式的路由,並把它們傳給伺服器。
這個欄位包含一個 URL 陣列,以及在執行階段比對的類 glob URL 模式。
它可以同時包含否定模式(也就是以 ! 開頭的模式)與非否定模式和 URL。
只有 URL 符合_任何_非否定 URL/模式、且_不_符合任何否定模式的請求,才會被視為導覽請求。 比對時會忽略 URL 查詢。
如果省略這個欄位,它的預設值為:
[
'/**', // Include all URLs.
'!/**/*.*', // Exclude URLs to files (containing a file extension in the last segment).
'!/**/*__*', // Exclude URLs containing `__` in the last segment.
'!/**/*__*/**', // Exclude URLs containing `__` in any other segment.
];
navigationRequestStrategy
這個可選屬性讓你可以設定 Service Worker 如何處理導覽請求:
{
"navigationRequestStrategy": "freshness"
}
| 可能的值 | 詳細說明 |
|---|---|
'performance' |
預設設定。提供指定的索引檔案,該檔案通常已快取。 |
'freshness' |
把請求傳給網路,在離線時退回 performance 行為。這個值在伺服器使用 3xx HTTP 重新導向狀態碼把導覽請求導向別處時很有用。使用這個值的原因包括:
|
IMPORTANT: freshness 策略通常會導致更多請求送往伺服器,這可能會增加回應延遲。建議只要有可能,就使用預設的效能策略。
applicationMaxAge
這個可選屬性讓你可以設定 Service Worker 從快取提供某個應用程式版本多久。這個期限是從你建置應用程式的時間起算,而不是從檔案快取到裝置上的時間起算。
在 applicationMaxAge 之內,Service Worker 會從快取提供檔案。超過之後,Service Worker 會把所有請求都送往網路,包括資產與資料請求,即使沒有較新的版本也一樣。在部署新版建置、且裝置已取得它之前,應用程式無法離線運作。
若你省略 applicationMaxAge,就沒有限期上限,Service Worker 會提供快取的版本,不論它們有多舊。