dojo dragon main logo

渐进式 Web 应用程序

渐进式 Web 应用程序 (PWA) 由一系列技术和模式组成,这些技术和模式可以改善用户体验,并有助于创建更可靠、更易用的应用程序。移动用户尤其会发现应用程序与他们设备的集成度更高,类似于已安装的应用程序。

渐进式 Web 应用程序的核心由两种技术组成:服务工作者和清单。Dojo 的构建命令通过 .dojorc 中的 pwa 对象支持这两种技术。

清单

清单 在一个 JSON 文件中描述了一个应用程序,并提供了一些详细信息,以便可以直接从 Web 上将应用程序安装到设备的主屏幕上。

.dojorc

{
	"build-app": {
		"pwa": {
			"manifest": {
				"name": "Todo MVC",
				"description": "A simple to-do application created with Dojo",
				"icons": [
					{ "src": "./favicon-16x16.png", "sizes": "16x16", "type": "image/png" },
					{ "src": "./favicon-32x32.png", "sizes": "32x32", "type": "image/png" },
					{ "src": "./favicon-48x48.png", "sizes": "48x48", "type": "image/png" },
					{ "src": "./favicon-256x256.png", "sizes": "256x256", "type": "image/png" }
				]
			}
		}
	}
}

当提供清单时,dojo build 将在应用程序的 index.html 中注入必要的 <meta> 标签。

  • mobile-web-app-capable="yes":指示 Android 上的 Chrome 应用程序可以添加到用户的 home screen。
  • apple-mobile-web-app-capable="yes":指示 iOS 设备应用程序可以添加到用户的 home screen。
  • apple-mobile-web-app-status-bar-style="default":指示 iOS 设备状态栏应使用默认外观。
  • apple-touch-icon="{{icon}}":等效于清单的图标,因为 iOS 目前不从清单中读取图标。每个图标数组条目都会注入一个单独的元标签。

服务工作者

服务工作者是一种 Web 工作者,它能够拦截网络请求、缓存和提供资源。Dojo 的构建命令可以自动构建功能齐全的服务工作者,该服务工作者在启动时被激活,并包含预缓存和来自配置文件的自定义路由处理。

例如,我们可以编写一个配置来创建一个简单的服务工作者,该服务工作者缓存所有应用程序捆绑包(除管理员捆绑包外),并缓存最近的应用程序图像和文章。

.dojorc

{
	"build-app": {
		"pwa": {
			"serviceWorker": {
				"cachePrefix": "my-app",
				"excludeBundles": ["admin"],
				"routes": [
					{
						"urlPattern": ".*\\.(png|jpg|gif|svg)",
						"strategy": "cacheFirst",
						"cacheName": "my-app-images",
						"expiration": { "maxEntries": 10, "maxAgeSeconds": 604800 }
					},
					{
						"urlPattern": "http://my-app-url.com/api/articles",
						"strategy": "cacheFirst",
						"expiration": { "maxEntries": 25, "maxAgeSeconds": 86400 }
					}
				]
			}
		}
	}
}

ServiceWorker 配置

在幕后,@dojo/webpack-contrib 中的 ServicerWorkerPlugin 用于生成服务工作者,其所有选项都是有效的 pwa.serviceWorker 属性。

属性 类型 可选 描述
bundles string[] 要包含在预缓存中的捆绑包数组。默认为所有捆绑包。
cachePrefix string 用于运行时预缓存缓存的前缀。
clientsClaim boolean 服务工作者是否应该在激活时开始控制客户端。默认为 false
excludeBundles string[] 要包含在预缓存中的捆绑包数组。默认为 []
importScripts string[] 应该在服务工作者中加载的脚本路径数组
precache object 预缓存配置选项的对象(见下文)
routes object[] 运行时缓存配置对象的数组(见下文)
skipWaiting boolean 服务工作者是否应该跳过等待生命周期

预缓存

precache 选项可以接受以下选项来控制预缓存行为

属性 类型 可选 描述
baseDir string include 匹配的基本目录。
ignore string[] 一个 glob 模式字符串数组,匹配在生成预缓存时应该忽略的文件。默认为 [ 'node_modules/**/*' ]
include stringstring[] 一个 glob 模式字符串或 glob 模式字符串数组,匹配应该包含在预缓存中的文件。默认为构建管道中的所有文件。
index string 如果对以 / 结尾的 URL 的请求失败,则应检查的索引文件名。默认为 'index.html'
maxCacheSize number 文件要添加到预缓存中,其大小(以字节为单位)不得超过的最大值。默认为 2097152(2 MB)。
strict boolean 如果为 true,则如果 include 模式匹配不存在的目录,则构建将失败。默认为 true
symlinks boolean 在生成预缓存时是否遵循符号链接。默认为 true

运行时缓存

除了预缓存外,还可以为特定路由提供策略,以确定是否以及如何缓存它们。此 routes 选项是一个对象数组,具有以下属性

属性 类型 可选 描述
urlPattern string 一个模式字符串(将被转换为正则表达式),匹配特定路由。
strategy string 缓存策略(见下文)。
options object 其他选项的对象,每个选项的详细信息见下文。
cacheName string 用于路由的缓存名称。请注意,cachePrefix 不会 添加到缓存名称之前。默认为主运行时缓存(${cachePrefix}-runtime-${domain})。
cacheableResponse object 使用 HTTP 状态代码或标头来确定响应是否可以缓存。此对象有两个可选属性:statusesheadersstatuses 是应该被视为缓存有效的 HTTP 状态代码数组。headers 是 HTTP 标头和值对的对象;至少有一个标头必须匹配,响应才被视为有效。当 strategy'cacheFirst' 时,默认为 { statuses: [ 200 ] },当 strategynetworkFirststaleWhileRevalidate 时,默认为 { statuses: [0, 200] }
expiration object 控制缓存如何失效。此对象有两个可选属性。maxEntries 是可以缓存的响应数量。一旦超过此最大值,最旧的条目将被删除。maxAgeSeconds 是缓存响应在被删除之前可以存在的最长时间(以秒为单位)。
networkTimeoutSeconds number networkFirst 策略一起使用,以指定在回退到缓存之前等待资源加载的最长时间(以秒为单位)。

目前支持四种路由策略

  • networkFirst 尝试通过网络加载资源,如果请求失败或超时,则回退到缓存。这对于经常更改或可能经常更改(即未版本化)的资产来说是一种有用的策略。
  • cacheFirst 从缓存中加载资源,除非资源不存在,在这种情况下,它将通过网络获取。这最适合很少更改或可以缓存很长时间(例如,版本化资产)的资源。
  • networkOnly 强制资源始终通过网络检索,对于没有离线等效请求来说非常有用。
  • staleWhileRevalidate 同时从缓存和网络请求资源。缓存会随着每个成功的网络响应而更新。此策略最适合不需要持续更新的资源,例如用户头像。但是,当获取不发送 CORS 标头的第三方资源时,无法读取响应的内容或验证状态代码。因此,可能会缓存错误的响应。在这种情况下,networkFirst 策略可能更适合。