阅读(835) (0)

Angular Service Worker配置

2022-07-01 14:18:12 更新

前提条件

对下列知识有基本的了解:

配置文件 ​ngsw-config.json​ 指定了 Angular Service Worker 应该缓存哪些文件和数据的 URL,以及如何更新缓存的文件和数据。​Angular CLI​ 会在 ​ng build​ 期间处理配置文件。如果想手动处理,可以用 ​ngsw-config​ 工具(这里的 ​<project-name>​ 就是要构建的项目名):

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

该配置文件使用 JSON 格式。所有文件路径都必须以 ​/​ 开头,也就是相应的部署目录 —— 在 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

排除所有源映射

下面讲讲配置文件中的每个属性。

appData

本节允许你传递用来描述这个特定应用版本的任何数据。​SwUpdate ​服务会在更新通知中包含这些数据。许多应用会使用本节来提供 UI 弹窗时要显示的附加信息,以通知用户有可用的更新。

index

指定用来充当索引页的文件以满足导航请求。通常是 ​/index.html​。

assetGroups

资产(Assets)是与应用一起更新的应用版本的一部分。它们可以包含从页面的同源地址加载的资源以及从 CDN 和其它外部 URL 加载的第三方资源。由于在构建时可能没法提前知道所有这些外部 URL,因此也可以指定 URL 的模式。

该字段包含一个资产组的数组,每个资产组中会定义一组资产资源和它们的缓存策略。

{
  "assetGroups": [
    {
      …
    },
    {
      …
    }
  ]
}
当 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;
  };
}

name

name ​是强制性的。它用来标识该配置文件版本中这个特定的资产组。

installMode

installMode ​决定了这些资源最初的缓存方式。​installMode ​可以取如下两个值之一:

详情

prefetch

要求 Angular Service Worker 在缓存当前版本的应用时要获取每一个列出的资源。这是个带宽密集型的模式,但可以确保这些资源在请求时可用,即使浏览器正处于离线状态。

lazy

lazy 不会预先缓存任何资源。相反,Angular Service Worker 只会缓存它收到请求的资源。这是一种按需缓存模式。永远不会请求的资源也永远不会被缓存。这对于像为不同分辨率提供的图片之类的资源很有用,那样 Service Worker 就只会为特定的屏幕和设备方向缓存正确的资源。

默认为 ​prefetch​。

updateMode

对于已经存在于缓存中的资源,​updateMode ​会决定在发现了新版本应用后的缓存行为。 自上一版本以来更改过的所有组中资源都会根据 ​updateMode ​进行更新。

详情

prefetch

要求 Service Worker 立即下载并缓存更新过的资源。

lazy

lazy 要求 Service Worker 不要缓存这些资源,而是先把它们看作未被请求的,等到它们再次被请求时才进行更新。lazy 这个 updateMode 只有在 installMode 也同样是 lazy 时才有效。

其默认值为 ​installMode ​的值。

resources

本节描述要缓存的资源,分为如下几组:

资源组

详情

files

files 列出了与 dist 目录中的文件相匹配的模式。它们可以是单个文件也可以是能匹配多个文件的类似 glob 的模式。

urls

包括要在运行时进行匹配的 URL 和 URL 模式。这些资源不是直接获取的,也没有内容散列,但它们会根据 HTTP 标头进行缓存。 这对于像 Google Fonts 服务这样的 CDN 非常有用。
(不支持 glob 的逆模式,? 将会按字面匹配;也就是说它不会匹配除了 ? 之外的任何字符。)

cacheQueryOptions

这些选项用来修改对请求进行匹配的行为。它们会传给浏览器的 ​Cache#match​ 函数。详情参阅 MDN。目前,只支持下列选项:

选项

详情

ignoreSearch

忽略查询参数。默认为 false

dataGroups

与这些资产性(asset)资源不同,数据请求不会随应用一起版本化。它们会根据手动配置的策略进行缓存,这些策略对 API 请求和所依赖的其它数据等情况会更有用。

本字段包含一个数据组的数组,其中的每一个条目都定义了一组数据资源以及对它们的缓存策略。

{
  "dataGroups": [
    {
      …
    },
    {
      …
    }
  ]
}
当 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;
    strategy?: 'freshness' | 'performance';
  };
  cacheQueryOptions?: {
    ignoreSearch?: boolean;
  };
}

name

和 ​assetGroups ​下类似,每个数据组也都有一个 ​name​,用作它的唯一标识。

urls

一个 URL 模式的列表。匹配这些模式的 URL 将会根据该数据组的策略进行缓存。只有非修改型的请求(GET 和 HEAD)才会进行缓存。

  • 不支持 glob 中的否定模式
  • ?​ 只做字面匹配,也就是说,它能匹配 ​?​ 字符。

version

API 有时可能会以不向后兼容的方式更改格式。新版本的应用可能与旧的 API 格式不兼容,因此也就与该 API 中目前已缓存的资源不兼容。

version ​提供了一种机制,用于指出这些被缓存的资源已经通过不向后兼容的方式进行了更新,并且旧的缓存条目(即来自以前版本的缓存条目)应该被丢弃。

version ​是个整型字段,默认为 ​0​。

cacheConfig

本节定义了对匹配上的请求进行缓存时的策略。

maxSize

(必需)缓存的最大条目数或响应数。开放式缓存可以无限增长,并最终超过存储配额,建议适时清理。

maxAge

(必需)​maxAge ​参数表示在响应因失效而要清除之前允许在缓存中留存的时间。​maxAge ​是一个表示持续时间的字符串,可使用以下单位作为后缀:

后缀

详情

d

h

小时

m

分钟

s

u

毫秒

比如,字符串 ​3d12h​ 规定此内容最多缓存三天半。

timeout

这个表示持续时间的字符串用于指定网络超时时间。 如果配置了网络超时时间,Angular Service Worker 就会先等待这么长时间再使用缓存。​timeout ​是一个表示持续时间的字符串,使用下列后缀单位:

后缀

详情

d

h

小时

m

分钟

s

u

毫秒

比如,字符串 ​5s30u​ 将会被翻译成 5 秒零 30 毫秒的网络超时。

strategy

Angular Service Worker 可以使用两种缓存策略之一来获取数据资源。

缓存策略

详情

performance

performance,默认值,为尽快给出响应而优化。如果缓存中存在某个资源,则使用这个缓存版本,而不再发起网络请求。它允许资源有一定的陈旧性(取决于 maxAge)以换取更好的性能。适用于那些不经常改变的资源,比如用户头像。

freshness

freshness 为数据的即时性而优化,优先从网络获取请求的数据。只有当网络超时时,请求才会根据 timeout 的设置回退到缓存中。这对于那些频繁变化的资源很有用,比如账户余额。

你还可以模拟第三种策略 staleWhileRevalidate,它会返回缓存的数据(如果可用),但是也会在后台从网络上获取新数据,以供下次使用。要使用本策略,请在 ​cacheConfig ​中把 ​strategy ​设置为 ​freshness​,并且把 ​timeout ​设置为 ​0u​。
本质上说,它会做如下工作:
  1. 首先尝试从网络上获取。
  2. 如果网络请求没有在 0ms 内(也就是立刻)完成,就用缓存做为后备(忽略缓存有效期)。
  3. 一旦网络请求完成,就更新缓存,以供将来的请求使用。
  4. 如果指定的资源在缓存中不存在,总是等待网络请求。

cacheOpaqueResponses

Angular 服务工作者是否应该缓存不透明的响应。

如果未指定,则默认值取决于数据组的配置策略:

STRATEGIES

详情

使用 freshness 策略的组

默认值为 true(缓存不透明响应)。这些组每次都会重新请求数据,只有在脱机或在慢速网络上时才会回到缓存响应。因此,服务工作者是否缓存错误响应是无关紧要的。

具有 performance 策略的组

默认值为 false(不缓存不透明响应)。这些组将继续返回缓存响应,直到 maxAge 过期,即使错误是由于临时网络或服务器问题造成的。因此,服务工作者缓存错误响应将是有问题的。

评论不透明的响应
如果你不熟悉,不透明响应是请求不同来源的不返回 CORS 标头的资源时返回的一种特殊类型的响应。不透明响应的特性之一是不允许服务工作者读取其状态,这意味着它无法检查请求是否成功。有关更多详细信息,请参阅fetch()介绍。
如果你无法实现 CORS(例如,如果你不控制来源),更愿意对会导致不透明响应的资源使用 freshness 策略。

navigationUrls

这个可选节让你可以指定一个自定义的 URL 列表,它们都会被重定向到索引文件。

处理导航请求

对于没有匹配上任何 ​asset ​或 ​data ​组的导航请求,ServiceWorker 会把它们重定向到指定的索引文件。下列请求将会视为导航请求:

  • 它的模式是 ​navigation
  • 它接受 ​text/html​ 响应(根据 ​Accept​ 头的值决定)
  • 它的 URL 符合特定的条件

默认情况下,这些条件是:

  • URL 的最后一段路径中不能包含文件扩展名(比如 ​.​)
  • URL 中不能包含 ​__

匹配导航请求的 URL

虽然这些默认条件在大多数情况下都挺好用,不过有时还是要配置一些不同的规则。比如,你可能希望忽略一些特定的路由(它们可能不是 Angular 应用的一部分),而是把它们透传给服务器。

该字段包含一个将要在运行期间匹配的 URL 和 类似 glob 的 URL 模式。 它既可以包含正向模式也可以包含反向模式(比如用 ​!​ 开头的模式)。

只有那些能匹配任意正向 URL 或 URL 模式并且不匹配任何一个反向模式的 URL 才会视为导航请求。当匹配时,这些 URL 查询将会被忽略。

如果省略了该字段,它的默认值是:

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

navigationRequestStrategy

通过此可选属性,你可以配置服务工作者如何处理导航请求:

{
  "navigationRequestStrategy": "freshness"
}

可能的值

详情

'performance'

默认设置。提供指定的索引文件,它通常会被缓存。

'freshness'

将请求透传到网络,并在脱机时回退到 performance 模式。当服务器在用 HTTP 重定向(3xx 状态代码)将导航请求重定向到其他位置时,此值很有用。使用此值的原因包括:

  • 当应用尚未处理身份验证时,重定向到身份验证网站。
  • 重定向特定的 URL,以免在网站重新设计后破坏现有的链接/书签。
  • 当页面暂时关闭时,重定向到其他网站,比如服务器状态页。

freshness ​策略通常会导致向服务器发送更多请求,这可能会增加响应延迟。建议你尽可能使用默认的性能策略。