Angular Service Worker配置

2022-07-12 11:15 更新

前提條件

對(duì)下列知識(shí)有基本的了解:

配置文件 ?ngsw-config.json? 指定了 Angular Service Worker 應(yīng)該緩存哪些文件和數(shù)據(jù)的 URL,以及如何更新緩存的文件和數(shù)據(jù)。?Angular CLI? 會(huì)在 ?ng build? 期間處理配置文件。如果想手動(dòng)處理,可以用 ?ngsw-config? 工具(這里的 ?<project-name>? 就是要構(gòu)建的項(xiàng)目名):

./node_modules/.bin/ngsw-config ./dist/<project-name> ./ngsw-config.json [/base/href]

該配置文件使用 JSON 格式。所有文件路徑都必須以 ?/? 開頭,也就是相應(yīng)的部署目錄 —— 在 CLI 項(xiàng)目中的它通常是 ?dist/<project-name>?。

除非另有注釋,否則模式使用limited* glob 格式,該格式將在內(nèi)部轉(zhuǎn)換為正則表達(dá)式:

GLOB 格式

詳情

**

匹配 0 個(gè)或多個(gè)路徑段

*

匹配不包括 / 的 0 個(gè)或多個(gè)字符

?

正好匹配不包括 / 的一個(gè)字符

! 前綴

將模式標(biāo)記為負(fù)數(shù),這意味著僅包含與模式不匹配的文件

請(qǐng)注意,在內(nèi)部 glob 到正則表達(dá)式的轉(zhuǎn)換中,正則表達(dá)式中某些具有特殊含義的字符不會(huì)被轉(zhuǎn)義,并且模式不會(huì)用 ?^? / ?$? 包裝。
  • ?$? 是正則表達(dá)式中的一個(gè)特殊字符,它與字符串的結(jié)尾匹配,在將 glob 模式轉(zhuǎn)換為正則表達(dá)式時(shí)不會(huì)自動(dòng)轉(zhuǎn)義。如果你想從字面上匹配 ?$? 字符,則必須自己對(duì)它進(jìn)行轉(zhuǎn)譯(使用 ?\\$?)。
  • 例如,glob 模式 ?/foo/bar/$value? 會(huì)導(dǎo)致出現(xiàn)無(wú)法匹配的表達(dá)式,因?yàn)樽址豢赡茉诮Y(jié)尾后有任何字符。

  • 將模式轉(zhuǎn)換為正則表達(dá)式時(shí),不會(huì)自動(dòng)用 ?^? 和 ?$? 包裝。因此,這些模式將部分匹配請(qǐng)求 URL。如果你希望你的模式匹配 URL 的開頭和/或結(jié)尾,可以自己添加 ?^? / ?$?。
  • 例如,glob 模式 ?/foo/bar/*.js? 將匹配 ?.js? 和 ?.json? 文件。如果你想僅匹配 ?.js? 文件,請(qǐng)使用 ?/foo/bar/*.js$?。

范例模式:

模式

詳情

/**/*.html

指定所有 HTML 文件

/*.html

僅指定根中的 HTML 文件

!/**/*.map

排除所有源映射

下面講講配置文件中的每個(gè)屬性。

appData

本節(jié)允許你傳遞用來(lái)描述這個(gè)特定應(yīng)用版本的任何數(shù)據(jù)。?SwUpdate ?服務(wù)會(huì)在更新通知中包含這些數(shù)據(jù)。許多應(yīng)用會(huì)使用本節(jié)來(lái)提供 UI 彈窗時(shí)要顯示的附加信息,以通知用戶有可用的更新。

index

指定用來(lái)充當(dāng)索引頁(yè)的文件以滿足導(dǎo)航請(qǐng)求。通常是 ?/index.html?。

assetGroups

資產(chǎn)(Assets)是與應(yīng)用一起更新的應(yīng)用版本的一部分。它們可以包含從頁(yè)面的同源地址加載的資源以及從 CDN 和其它外部 URL 加載的第三方資源。由于在構(gòu)建時(shí)可能沒(méi)法提前知道所有這些外部 URL,因此也可以指定 URL 的模式。

該字段包含一個(gè)資產(chǎn)組的數(shù)組,每個(gè)資產(chǎn)組中會(huì)定義一組資產(chǎn)資源和它們的緩存策略。

{
  "assetGroups": [
    {
      …
    },
    {
      …
    }
  ]
}
當(dāng) ServiceWorker 處理請(qǐng)求時(shí),它將按照資源組在 ?ngsw-config.json? 中出現(xiàn)的順序?qū)ζ溥M(jìn)行檢查。與所請(qǐng)求的資源匹配的第一個(gè)資源組將處理該請(qǐng)求。
建議將更具體的資源組放在列表中較高的位置。比如,與 ?/foo.js? 匹配的資源組應(yīng)出現(xiàn)在與 ?*.js? 匹配的資源組之前。

每個(gè)資產(chǎn)組都會(huì)指定一組資源和一個(gè)管理它們的策略。此策略用來(lái)決定何時(shí)獲取資源以及當(dāng)檢測(cè)到更改時(shí)該怎么做。

這些資產(chǎn)組會(huì)遵循下面的 Typescript 接口:

interface AssetGroup {
  name: string;
  installMode?: 'prefetch' | 'lazy';
  updateMode?: 'prefetch' | 'lazy';
  resources: {
    files?: string[];
    urls?: string[];
  };
  cacheQueryOptions?: {
    ignoreSearch?: boolean;
  };
}

name

?name ?是強(qiáng)制性的。它用來(lái)標(biāo)識(shí)該配置文件版本中這個(gè)特定的資產(chǎn)組。

installMode

?installMode ?決定了這些資源最初的緩存方式。?installMode ?可以取如下兩個(gè)值之一:

詳情

prefetch

要求 Angular Service Worker 在緩存當(dāng)前版本的應(yīng)用時(shí)要獲取每一個(gè)列出的資源。這是個(gè)帶寬密集型的模式,但可以確保這些資源在請(qǐng)求時(shí)可用,即使瀏覽器正處于離線狀態(tài)。

lazy

lazy 不會(huì)預(yù)先緩存任何資源。相反,Angular Service Worker 只會(huì)緩存它收到請(qǐng)求的資源。這是一種按需緩存模式。永遠(yuǎn)不會(huì)請(qǐng)求的資源也永遠(yuǎn)不會(huì)被緩存。這對(duì)于像為不同分辨率提供的圖片之類的資源很有用,那樣 Service Worker 就只會(huì)為特定的屏幕和設(shè)備方向緩存正確的資源。

默認(rèn)為 ?prefetch?。

updateMode

對(duì)于已經(jīng)存在于緩存中的資源,?updateMode ?會(huì)決定在發(fā)現(xiàn)了新版本應(yīng)用后的緩存行為。 自上一版本以來(lái)更改過(guò)的所有組中資源都會(huì)根據(jù) ?updateMode ?進(jìn)行更新。

詳情

prefetch

要求 Service Worker 立即下載并緩存更新過(guò)的資源。

lazy

lazy 要求 Service Worker 不要緩存這些資源,而是先把它們看作未被請(qǐng)求的,等到它們?cè)俅伪徽?qǐng)求時(shí)才進(jìn)行更新。lazy 這個(gè) updateMode 只有在 installMode 也同樣是 lazy 時(shí)才有效。

其默認(rèn)值為 ?installMode ?的值。

resources

本節(jié)描述要緩存的資源,分為如下幾組:

資源組

詳情

files

files 列出了與 dist 目錄中的文件相匹配的模式。它們可以是單個(gè)文件也可以是能匹配多個(gè)文件的類似 glob 的模式。

urls

包括要在運(yùn)行時(shí)進(jìn)行匹配的 URL 和 URL 模式。這些資源不是直接獲取的,也沒(méi)有內(nèi)容散列,但它們會(huì)根據(jù) HTTP 標(biāo)頭進(jìn)行緩存。 這對(duì)于像 Google Fonts 服務(wù)這樣的 CDN 非常有用。
(不支持 glob 的逆模式,? 將會(huì)按字面匹配;也就是說(shuō)它不會(huì)匹配除了 ? 之外的任何字符。)

cacheQueryOptions

這些選項(xiàng)用來(lái)修改對(duì)請(qǐng)求進(jìn)行匹配的行為。它們會(huì)傳給瀏覽器的 ?Cache#match? 函數(shù)。詳情參閱 MDN。目前,只支持下列選項(xiàng):

選項(xiàng)

詳情

ignoreSearch

忽略查詢參數(shù)。默認(rèn)為 false。

dataGroups

與這些資產(chǎn)性(asset)資源不同,數(shù)據(jù)請(qǐng)求不會(huì)隨應(yīng)用一起版本化。它們會(huì)根據(jù)手動(dòng)配置的策略進(jìn)行緩存,這些策略對(duì) API 請(qǐng)求和所依賴的其它數(shù)據(jù)等情況會(huì)更有用。

本字段包含一個(gè)數(shù)據(jù)組的數(shù)組,其中的每一個(gè)條目都定義了一組數(shù)據(jù)資源以及對(duì)它們的緩存策略。

{
  "dataGroups": [
    {
      …
    },
    {
      …
    }
  ]
}
當(dāng) ServiceWorker 處理請(qǐng)求時(shí),它將按照數(shù)據(jù)組在 ?ngsw-config.json? 中出現(xiàn)的順序?qū)ζ溥M(jìn)行檢查。與所請(qǐng)求的資源匹配的第一個(gè)數(shù)據(jù)組將處理該請(qǐng)求。
建議將更具體的數(shù)據(jù)組放在列表中較高的位置。比如,與 ?/api/foo.json? 匹配的數(shù)據(jù)組應(yīng)出現(xiàn)在與 ?/api/*.json? 匹配的數(shù)據(jù)組之前。

數(shù)據(jù)組遵循下列 TypeScript 接口:

export interface DataGroup {
  name: string;
  urls: string[];
  version?: number;
  cacheConfig: {
    maxSize: number;
    maxAge: string;
    timeout?: string;
    strategy?: 'freshness' | 'performance';
  };
  cacheQueryOptions?: {
    ignoreSearch?: boolean;
  };
}

name

和 ?assetGroups ?下類似,每個(gè)數(shù)據(jù)組也都有一個(gè) ?name?,用作它的唯一標(biāo)識(shí)。

urls

一個(gè) URL 模式的列表。匹配這些模式的 URL 將會(huì)根據(jù)該數(shù)據(jù)組的策略進(jìn)行緩存。只有非修改型的請(qǐng)求(GET 和 HEAD)才會(huì)進(jìn)行緩存。

  • 不支持 glob 中的否定模式
  • ??? 只做字面匹配,也就是說(shuō),它能匹配 ??? 字符。

version

API 有時(shí)可能會(huì)以不向后兼容的方式更改格式。新版本的應(yīng)用可能與舊的 API 格式不兼容,因此也就與該 API 中目前已緩存的資源不兼容。

?version ?提供了一種機(jī)制,用于指出這些被緩存的資源已經(jīng)通過(guò)不向后兼容的方式進(jìn)行了更新,并且舊的緩存條目(即來(lái)自以前版本的緩存條目)應(yīng)該被丟棄。

?version ?是個(gè)整型字段,默認(rèn)為 ?0?。

cacheConfig

本節(jié)定義了對(duì)匹配上的請(qǐng)求進(jìn)行緩存時(shí)的策略。

maxSize

(必需)緩存的最大條目數(shù)或響應(yīng)數(shù)。開放式緩存可以無(wú)限增長(zhǎng),并最終超過(guò)存儲(chǔ)配額,建議適時(shí)清理。

maxAge

(必需)?maxAge ?參數(shù)表示在響應(yīng)因失效而要清除之前允許在緩存中留存的時(shí)間。?maxAge ?是一個(gè)表示持續(xù)時(shí)間的字符串,可使用以下單位作為后綴:

后綴

詳情

d

h

小時(shí)

m

分鐘

s

u

毫秒

比如,字符串 ?3d12h? 規(guī)定此內(nèi)容最多緩存三天半。

timeout

這個(gè)表示持續(xù)時(shí)間的字符串用于指定網(wǎng)絡(luò)超時(shí)時(shí)間。 如果配置了網(wǎng)絡(luò)超時(shí)時(shí)間,Angular Service Worker 就會(huì)先等待這么長(zhǎng)時(shí)間再使用緩存。?timeout ?是一個(gè)表示持續(xù)時(shí)間的字符串,使用下列后綴單位:

后綴

詳情

d

h

小時(shí)

m

分鐘

s

u

毫秒

比如,字符串 ?5s30u? 將會(huì)被翻譯成 5 秒零 30 毫秒的網(wǎng)絡(luò)超時(shí)。

strategy

Angular Service Worker 可以使用兩種緩存策略之一來(lái)獲取數(shù)據(jù)資源。

緩存策略

詳情

performance

performance,默認(rèn)值,為盡快給出響應(yīng)而優(yōu)化。如果緩存中存在某個(gè)資源,則使用這個(gè)緩存版本,而不再發(fā)起網(wǎng)絡(luò)請(qǐng)求。它允許資源有一定的陳舊性(取決于 maxAge)以換取更好的性能。適用于那些不經(jīng)常改變的資源,比如用戶頭像。

freshness

freshness 為數(shù)據(jù)的即時(shí)性而優(yōu)化,優(yōu)先從網(wǎng)絡(luò)獲取請(qǐng)求的數(shù)據(jù)。只有當(dāng)網(wǎng)絡(luò)超時(shí)時(shí),請(qǐng)求才會(huì)根據(jù) timeout 的設(shè)置回退到緩存中。這對(duì)于那些頻繁變化的資源很有用,比如賬戶余額。

你還可以模擬第三種策略 staleWhileRevalidate,它會(huì)返回緩存的數(shù)據(jù)(如果可用),但是也會(huì)在后臺(tái)從網(wǎng)絡(luò)上獲取新數(shù)據(jù),以供下次使用。要使用本策略,請(qǐng)?jiān)?nbsp;?cacheConfig ?中把 ?strategy ?設(shè)置為 ?freshness?,并且把 ?timeout ?設(shè)置為 ?0u?。
本質(zhì)上說(shuō),它會(huì)做如下工作:
  1. 首先嘗試從網(wǎng)絡(luò)上獲取。
  2. 如果網(wǎng)絡(luò)請(qǐng)求沒(méi)有在 0ms 內(nèi)(也就是立刻)完成,就用緩存做為后備(忽略緩存有效期)。
  3. 一旦網(wǎng)絡(luò)請(qǐng)求完成,就更新緩存,以供將來(lái)的請(qǐng)求使用。
  4. 如果指定的資源在緩存中不存在,總是等待網(wǎng)絡(luò)請(qǐng)求。

cacheOpaqueResponses

Angular 服務(wù)工作者是否應(yīng)該緩存不透明的響應(yīng)。

如果未指定,則默認(rèn)值取決于數(shù)據(jù)組的配置策略:

STRATEGIES

詳情

使用 freshness 策略的組

默認(rèn)值為 true(緩存不透明響應(yīng))。這些組每次都會(huì)重新請(qǐng)求數(shù)據(jù),只有在脫機(jī)或在慢速網(wǎng)絡(luò)上時(shí)才會(huì)回到緩存響應(yīng)。因此,服務(wù)工作者是否緩存錯(cuò)誤響應(yīng)是無(wú)關(guān)緊要的。

具有 performance 策略的組

默認(rèn)值為 false(不緩存不透明響應(yīng))。這些組將繼續(xù)返回緩存響應(yīng),直到 maxAge 過(guò)期,即使錯(cuò)誤是由于臨時(shí)網(wǎng)絡(luò)或服務(wù)器問(wèn)題造成的。因此,服務(wù)工作者緩存錯(cuò)誤響應(yīng)將是有問(wèn)題的。

評(píng)論不透明的響應(yīng)
如果你不熟悉,不透明響應(yīng)是請(qǐng)求不同來(lái)源的不返回 CORS 標(biāo)頭的資源時(shí)返回的一種特殊類型的響應(yīng)。不透明響應(yīng)的特性之一是不允許服務(wù)工作者讀取其狀態(tài),這意味著它無(wú)法檢查請(qǐng)求是否成功。有關(guān)更多詳細(xì)信息,請(qǐng)參閱fetch()介紹。
如果你無(wú)法實(shí)現(xiàn) CORS(例如,如果你不控制來(lái)源),更愿意對(duì)會(huì)導(dǎo)致不透明響應(yīng)的資源使用 freshness 策略。

navigationUrls

這個(gè)可選節(jié)讓你可以指定一個(gè)自定義的 URL 列表,它們都會(huì)被重定向到索引文件。

處理導(dǎo)航請(qǐng)求

對(duì)于沒(méi)有匹配上任何 ?asset ?或 ?data ?組的導(dǎo)航請(qǐng)求,ServiceWorker 會(huì)把它們重定向到指定的索引文件。下列請(qǐng)求將會(huì)視為導(dǎo)航請(qǐng)求:

  • 它的模式是 ?navigation ?
  • 它接受 ?text/html? 響應(yīng)(根據(jù) ?Accept? 頭的值決定)
  • 它的 URL 符合特定的條件

默認(rèn)情況下,這些條件是:

  • URL 的最后一段路徑中不能包含文件擴(kuò)展名(比如 ?.?)
  • URL 中不能包含 ?__?

匹配導(dǎo)航請(qǐng)求的 URL

雖然這些默認(rèn)條件在大多數(shù)情況下都挺好用,不過(guò)有時(shí)還是要配置一些不同的規(guī)則。比如,你可能希望忽略一些特定的路由(它們可能不是 Angular 應(yīng)用的一部分),而是把它們透?jìng)鹘o服務(wù)器。

該字段包含一個(gè)將要在運(yùn)行期間匹配的 URL 和 類似 glob 的 URL 模式。 它既可以包含正向模式也可以包含反向模式(比如用 ?!? 開頭的模式)。

只有那些能匹配任意正向 URL 或 URL 模式并且不匹配任何一個(gè)反向模式的 URL 才會(huì)視為導(dǎo)航請(qǐng)求。當(dāng)匹配時(shí),這些 URL 查詢將會(huì)被忽略。

如果省略了該字段,它的默認(rèn)值是:

[
  '/**',           // Include all URLs.
  '!/**/*.*',      // Exclude URLs to files.
  '!/**/*__*',     // Exclude URLs containing `__` in the last segment.
  '!/**/*__*/**',  // Exclude URLs containing `__` in any other segment.
]

navigationRequestStrategy

通過(guò)此可選屬性,你可以配置服務(wù)工作者如何處理導(dǎo)航請(qǐng)求:

{
  "navigationRequestStrategy": "freshness"
}

可能的值

詳情

'performance'

默認(rèn)設(shè)置。提供指定的索引文件,它通常會(huì)被緩存。

'freshness'

將請(qǐng)求透?jìng)鞯骄W(wǎng)絡(luò),并在脫機(jī)時(shí)回退到 performance 模式。當(dāng)服務(wù)器在用 HTTP 重定向(3xx 狀態(tài)代碼)將導(dǎo)航請(qǐng)求重定向到其他位置時(shí),此值很有用。使用此值的原因包括:

  • 當(dāng)應(yīng)用尚未處理身份驗(yàn)證時(shí),重定向到身份驗(yàn)證網(wǎng)站。
  • 重定向特定的 URL,以免在網(wǎng)站重新設(shè)計(jì)后破壞現(xiàn)有的鏈接/書簽。
  • 當(dāng)頁(yè)面暫時(shí)關(guān)閉時(shí),重定向到其他網(wǎng)站,比如服務(wù)器狀態(tài)頁(yè)。

?freshness ?策略通常會(huì)導(dǎo)致向服務(wù)器發(fā)送更多請(qǐng)求,這可能會(huì)增加響應(yīng)延遲。建議你盡可能使用默認(rèn)的性能策略。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)