@baukit/pwa-web
@baukit/pwa-web 决定PWA服务人员应适用何种缓存策略.
决定是对请求的方法,URL,模式,和目的地的纯函数. 没有
此软件包读取 self, (中文(简体) ), caches, (中文(简体) ), clients,或 location,因此每个分支都可以在
平地节点.
产品拥有缓存名称、预缓存列表、安装和激活处理器以及离线倒置 copy. 这个软件包拥有分类和策略执行, 围绕缓存 产品供应.
请求的保密
import { CACHE_STRATEGIES, decideCacheStrategy } from '@baukit/pwa-web';
decideCacheStrategy(
{ url: '/api/v1/sync/pull?since=12', method: 'GET' },
{ appOrigin: 'https://app.example.com', neverCachedPathPrefixes: ['/api/v1/sync'] },
);
// 'network-only'
规则按此顺序执行:
- 任何路径
neverCachedPathPrefixes条目是network-only列表为空 默认,所以在产品名称之一之前,端点并不特殊. 同步端点属于这里 : 重放被打烂的三角洲会腐蚀本地数据库. - 任何非 GET 方法都是
network-only。 。 。 . - 任何路径
apiPathPrefixes条目(默认)['/api']获得apiStrategy默认值network-first。 。 。 . - 导航( A)
mode === 'navigate'获得defaultStrategy默认值network-first时navigationFallback已经设定,createFetchHandler如果选中的话, 请查看 app- shell 路径 策略失败, 而原始请求没有被缓存 . - 同源请求,其目的地、文件扩展名或路径前缀标记为静态
staticStrategy默认值cache-first。 。 。 . - 其他一切都会得到的
defaultStrategy。 。 。 .
前缀匹配为片段意识 : /api 匹配 /api 财务报告和审定财务报表 /api/v1/me 但没有 /apiary。 。 。 .
扩展匹配只读取最后一个路径段, 所以 /v1.2/plans 不是一个静态资产.
原产资产从未到达 cache-first因为服务员不应该填补它的缓存
和另一个来源的答复.
选项
| 选项 | 默认 | 目的 |
|---|---|---|
appOrigin | 所需经费 | 相对 URL 和同源测试的基础 |
neverCachedPathPrefixes | [] | 必须总是击中网络的路径, 如同步端点 |
apiPathPrefixes | ['/api'] | 作为 API 读取的路径 |
navigationFallback | 未设定 | 离线导航失败后使用的缓存app- shell 路径 |
staticPathPrefixes | [] | 无延伸静态路径, 如 /_expo/static/ |
staticDestinations | 音频、字体、图像、脚本、风格、视频、工人 | Request.destination 表示静态的值 |
staticExtensions | 共同网络资产扩展 | 表示静态的文件扩展名 |
apiStrategy | network-first | API 战略读取 |
staticStrategy | cache-first | 静态资产战略 |
defaultStrategy | network-first | 其他一切的战略 |
createCacheStrategyDecider(options) 绑定选项一次并返回函数
请求,这是安装时间资产扫描所需要的.
navigationFallback 仅适用于同一来源的获取请求 mode: 'navigate'API 路线
和路径 neverCachedPathPrefixes 永远不要用它,即使一个呼叫者供应 mode: 'navigate'。 。 。 .
选中的 defaultStrategy 仍然运行第一。 处理器检查后退路径
此策略无法返回网络响应或请求的 URL 的缓存响应 。 没有
已配置回落, 导航缺失 保留先前的行为, 并拒绝使用网络
错误。 产品必须预先切除后退路径.
执行战略
createFetchHandler 通过产品提供的端口执行选定的策略。 从来没有
构造 a Cache 或呼叫全局 fetch 自己,所以同一个处理器运行在维特下
以平地为对象.
// public/sw.js
import { createFetchHandler } from '/pwa-web.js';
const STATIC_CACHE = 'app-static-v1';
const SHELL_CACHE = 'app-shell-v1';
const handleFetch = createFetchHandler({
appOrigin: self.location.origin,
neverCachedPathPrefixes: ['/api/v1/sync'],
navigationFallback: '/index.html',
staticPathPrefixes: ['/_expo/static/'],
ports: {
fetch: (request, init) => fetch(request, init),
matchCache: (request) => caches.match(request),
putCache: async (strategy, request, response) => {
const name = strategy === 'cache-first' ? STATIC_CACHE : SHELL_CACHE;
const cache = await caches.open(name);
await cache.put(request, response);
},
isCacheable: (response) => response.ok && response.type !== 'error',
cloneResponse: (response) => response.clone(),
},
onRevalidateError: () => {
// A background refresh failure must not surface to the page.
},
});
self.addEventListener('fetch', (event) => {
event.respondWith(handleFetch(event.request));
});
每项战略的行为:
network-only获取方式cache: 'no-store'永远不要写到缓存.cache-first返回命中,否则会获取并存储可缓存的响应.network-first获取并存储可缓存的响应, 当 取出掷出. 如果请求是符合资格的导航,并且没有自己的缓存条目,navigationFallback提供最后的缓存查询。 没有什么缓存 它重新喷出.stale-while-revalidate返回背景中的缓存响应和刷新。 在一个 错过它等待网络。 背景失败到onRevalidateError。 。 。 .
putCache 接收生成响应的策略,这就是上面的片段
引导静态资产和 shell 响应到不同的缓存中.
使用工人的文物
@baukit/pwa-web/worker 解决一个捆绑的经典脚本。 它没有进口,并指定
公开 API 到 globalThis.BaukitPwa。构建脚本可以复制,而不分析或重写
软件包来源 :
import { copyFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
const source = fileURLToPath(import.meta.resolve('@baukit/pwa-web/worker'));
await copyFile(source, 'public/baukit-pwa-worker.js');
在产品工人代码前装入副本 :
// public/sw.js
importScripts('/baukit-pwa-worker.js');
const handleFetch = globalThis.BaukitPwa.createFetchHandler({
// Product cache policy and ports go here.
});
登记册 sw.js 作为普通的经典服务工作者:
if ('serviceWorker' in navigator) {
await navigator.serviceWorker.register('/sw.js');
}
IIFE格式是深思熟虑的. 拷贝它 public/ 输入目录 dist/,而博览会的网页
静态导出时相同。 两条路径都可以为字节复制此文物字节. 没有路径需要
光刻模块导入到浏览器,模块-工人注册,或包的特定捆绑器设置中.
装满了Npm的柏油丸试验 装上没有的文物 window, (中文(简体) ), document,或 self 全球.
移动源重写构建
替换读取的代码 dist/cache-strategy.js,删除导入或导出,并缩写文件
从 @baukit/pwa-web/worker保持产品自主性 sw.js 及其缓存政策.
从 @baukit/pwa-web 和通用JS系统 require('@baukit/pwa-web') 继续支持.
快取清理
产品决定哪些确切的缓存名称属于旧版本或身份. cleanupCaches
提供列表并删除操作和返回计数,而不返回或记录缓存名称.
此激活处理器在保留当前版本的同时删除旧的应用程序缓存版本
和由其它代码拥有的缓存 :
const CURRENT_APP_CACHE = 'notes-app-v4';
self.addEventListener('activate', (event) => {
event.waitUntil(
globalThis.BaukitPwa.cleanupCaches({
ports: {
listCacheNames: () => caches.keys(),
deleteCache: (name) => caches.delete(name),
},
shouldDelete: (name) => name.startsWith('notes-app-') && name !== CURRENT_APP_CACHE,
}),
);
});
私人缓存需要一个产品拥有,不透明的分区密钥. 在身份更改时, 删除精确 在披露新身份数据前的前一个分区。 登录时, 删除所有私密缓存 用于向外分区。 不放置访问令牌、电子邮件地址或原始身份提供者 缓存名称中的主题.
import { cleanupCaches } from '@baukit/pwa-web';
await cleanupCaches({
ports: {
listCacheNames: () => caches.keys(),
deleteCache: (name) => caches.delete(name),
},
shouldDelete: (name) => name === `notes-private-${outgoingPartitionKey}`,
});
cleanupCaches 在开始删除之前选择所有名称,然后一起运行删除。 这算数
缓存仅当 CacheStorage.delete 决定: true2. 清单、上游或删除
失败拒绝操作 。 有些删除可能已经在另一个删除拒绝时完成,
因此在完成登录或身份交换之前重试清理.
此软件包没有做什么
它不注册服务员,预留应用程序外壳,选择缓存名称,定义路径, 创建网络显示或图标, 提示更新, 选择离线路由, 或获取身份 分区键。 这些取决于产品的积分输出,隐私模型和复制. 宝琪的CLI 仍然需要PWA使用的网络能力. 发布此文物不会添加 PWA 生成 到 Expo 网页项目.