渐进式 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 | string 或 string[] |
是 | 一个 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 状态代码或标头来确定响应是否可以缓存。此对象有两个可选属性:statuses 和 headers 。statuses 是应该被视为缓存有效的 HTTP 状态代码数组。headers 是 HTTP 标头和值对的对象;至少有一个标头必须匹配,响应才被视为有效。当 strategy 为 'cacheFirst' 时,默认为 { statuses: [ 200 ] } ,当 strategy 为 networkFirst 或 staleWhileRevalidate 时,默认为 { statuses: [0, 200] } 。 |
expiration | object |
是 | 控制缓存如何失效。此对象有两个可选属性。maxEntries 是可以缓存的响应数量。一旦超过此最大值,最旧的条目将被删除。maxAgeSeconds 是缓存响应在被删除之前可以存在的最长时间(以秒为单位)。 |
networkTimeoutSeconds | number |
是 | 与 networkFirst 策略一起使用,以指定在回退到缓存之前等待资源加载的最长时间(以秒为单位)。 |
目前支持四种路由策略
networkFirst
尝试通过网络加载资源,如果请求失败或超时,则回退到缓存。这对于经常更改或可能经常更改(即未版本化)的资产来说是一种有用的策略。cacheFirst
从缓存中加载资源,除非资源不存在,在这种情况下,它将通过网络获取。这最适合很少更改或可以缓存很长时间(例如,版本化资产)的资源。networkOnly
强制资源始终通过网络检索,对于没有离线等效请求来说非常有用。staleWhileRevalidate
同时从缓存和网络请求资源。缓存会随着每个成功的网络响应而更新。此策略最适合不需要持续更新的资源,例如用户头像。但是,当获取不发送 CORS 标头的第三方资源时,无法读取响应的内容或验证状态代码。因此,可能会缓存错误的响应。在这种情况下,networkFirst
策略可能更适合。