@absourutejs/pwa (英语)
将任何应用程序变成可安装软件的 框架不可知性原始, 离线能力、推力能力 网络应用程序显示, (中文(简体) ), 有限背景 同步,则 推动服务人员页:1 VAPID 网络推送器 旗帜死了 终点,和 浏览器胶水 服务-工人登记+订阅.
其直接原始物仍为存储和框架不可知. 绝对 JS 构建
添加推荐路径: Auth 拥有注册,调度拥有生命周期
扇出, 页面代码只使用 @absolutejs/devices。 。 。 .
bun add @absolutejs/pwa
服务器
import {
createWebAppManifest,
pushServiceWorker,
createWebPush,
} from "@absolutejs/pwa";
const ICON = "/icons/app-512.png";
// Serve as application/manifest+json at /manifest.webmanifest
export const manifest = createWebAppManifest({
name: "My App",
shortName: "MyApp",
themeColor: "#6366f1",
icons: [
{ src: ICON, sizes: "192x192", type: "image/png", purpose: "any" },
{ src: ICON, sizes: "512x512", type: "image/png", purpose: "any" },
],
});
// Serve as text/javascript at /sw.js with header `Service-Worker-Allowed: /`.
// Pass `offline` to also precache an app shell + serve a fallback page when a
// navigation fails offline, and cache same-origin assets cache-first.
export const sw = pushServiceWorker({
icon: ICON,
offline: { fallback: "/offline.html", assetPrefix: "/assets/" },
sync: true,
});
// VAPID sender — pass empty/unset keys and it no-ops (isConfigured() === false),
// so push degrades gracefully to your email/in-app fallback.
const push = createWebPush({
publicKey: process.env.VAPID_PUBLIC_KEY,
privateKey: process.env.VAPID_PRIVATE_KEY,
subject: "mailto:[email protected]",
});
// Fan out to a user's devices; prune whatever it reports gone.
const { gone } = await push.sendMany(subscriptions, {
title: "New match",
body: "Acme Co. just replied.",
url: "/inbox",
});
await pruneEndpoints(gone); // your storage
骑马是你的。 与爱丽西亚:
new Elysia()
.get("/manifest.webmanifest", ({ set }) => {
set.headers["content-type"] = "application/manifest+json";
return manifest;
})
.get("/sw.js", ({ set }) => {
set.headers["content-type"] = "text/javascript";
set.headers["service-worker-allowed"] = "/";
return sw;
});
在绝对JS中可移植推
在绝对JS应用程序中,导入 pushNotifications 和启用 pwa
自动生成浏览器适配器和订阅旋转工人.
设置公众 VAPID_PUBLIC_KEY 在建筑环境中; 保持
VAPID_PRIVATE_KEY 仅在可信任的交付过程中。 配置 Auth 一次
发送寿命周期 auth({ push: ... })。浏览器只能提交
其供应商的证书和不透明安装 ID - Auth获得用户,租户,
和服务器上的主题.
import { pushNotifications } from "@absolutejs/devices";
await pushNotifications.requestPermission();
await pushNotifications.enable();
同一页面代码在Capacitor shell中使用APNs/FCM,在浏览器中使用Web Push.
对于直接的PWA整合,通过 push 改为 registerServiceWorker() 或打电话
configurePwaPush() 当然 安装身份与
indexedDB 中的服务工人,所以浏览器订阅旋转更新相同
即使在没有打开页面时信任的服务器记录 .
调度用户可以导入 createWebPushDispatchAdapter 从
@absolutejs/pwa/dispatch; 它将提供者中性消息映射到 Web Push
发件人和分类 生命周期退休的去/可复验结果.
客户端
import {
registerServiceWorker,
getPushStatus,
subscribeToPush,
unsubscribeFromPush,
} from "@absolutejs/pwa/client";
// At boot. By default this waits for page load, then retries transient
// browser/network failures up to three total attempts.
await registerServiceWorker(); // defaults to "/sw.js"
// Toggle on: returns the subscription JSON — send it through your typed API.
const subscription = await subscribeToPush(vapidPublicKey);
await api.push.subscriptions.post(subscription);
// Toggle off: returns the endpoint to drop server-side.
const endpoint = await unsubscribeFromPush();
await api.push.subscriptions.delete({ endpoint });
const status = await getPushStatus(); // { supported, permission, subscribed }
离线同步
@absolutejs/pwa 可提供 @absolutejs/sync 自动
认证的浏览器应用程序 。 产生工人 sync: true,然后启用
注册时的客户端桥:
await registerServiceWorker("/sw.js", { sync: {} });
Sync 浏览器运行时间仅在启用此桥时懒散地加载, 所以 express-, s安装-和push-lease 应用程序不支付客户端成本.
绝对JS用品 storageSchema 自动编译应用程序计划
包含来自已安装同步包的宣告元数据。 同样的JSON安全计划是
由前景客户端和服务工作者使用,因此索引DB在前作升级
运行时间读取缓存行或冲出耐用发件箱。 直接PWA( PWA)
集成可能通过组件捆绑 sync.storageSchema。 。 。 .
该捆绑还载有当地数据的敏感性、保留和配额规则.
浏览器不会收到由存储在
密码文本:除非直接的PWA,否则加密所需的记录会失效
提供经审计的同步保护供应商。 便携式包可以
改为声明 onProtectionUnavailable: "memory-only"; 特性保留其
不写入敏感行的活浏览器状态和仅在线突变或
参数到 IndexedDB,而同一捆绑则被永久加密
本地密钥链/ Keystore 后置适配器 .
配额压力驱出 完整的缓存预测, 从来没有耐用发货箱.
与 @absolutejs/auth 财务报告和审定财务报表 syncSocket() 挂载,没有页面级符号或
需要收集列表。 客户端执行严格的同源 JSON POST
改为 /__absolute/sync/principal 使用 HTTP 唯一的会话 cookie。 这个
响应中只包含一个不透明的账户命名空间。 前景同步客户端和
工人共用一个名称空间索引数据库;工人发现的情况持续存在
id- 键入收藏描述符,冲出耐用外框,拉出有限度
更新通过 /__absolute/sync/background。 。 。 .
背景同步是最佳的,因为浏览器支持和排程不同. 在线、焦点和可见页面活动也重新连接和冲出活跃客户端, 因此,前景/恢复仍然是正确的路径。 本地应用程序继续使用 他们以Auth为基地的运输 而不是这个饼干桥.
高级端点、限制和共享数据库名称可配置 :
await registerServiceWorker("/sw.js", {
sync: {
endpoint: "/__absolute/sync/background",
principalEndpoint: "/__absolute/sync/principal",
databaseName: "absolutejs-sync-v1",
maxMutations: 50,
maxPulls: 50,
},
});
两个端点必须解决页面的确切出处,重定向是
拒绝。 饼干、无记名标记、变异参数和应用程序行
从不嵌入工人的脚本 或服务-工人信息。 如果会议
工人配置被清除。 在焦点,在线,可见
页面过渡,桥在同步前再次解决主机。 一个
账户更改中止旧运行、清除运行时间并安装新
任何新工作开始前的不透明命名空间 . configurePwaSync() 也为
用于单独登记工人的宿主.
在不向绝对JS发送应用数据的情况下, 观察静态运行结果 :
import { getLastPwaSyncResult, onPwaSyncResult } from "@absolutejs/pwa/client";
const unsubscribe = onPwaSyncResult((result) => {
// { ok, durationMs, trigger, acknowledged?, pulled?, ... }
console.log(result);
});
const latest = getLastPwaSyncResult();
同样的汇总结果发出于 window 作为
absolute:pwa-sync-result 自定义事件。 它的合同只允许地位,
持续时间、触发点和总数; 命名空间、终点、证书、,
变异参数,和行被丢弃在页面边界上. 这个
应用程序可观测信号,而不是内置分析器或电话家庭频道.
安装快速
抓取浏览器安装的信号并按自己的按钮驱动:
import {
initInstallPrompt,
onInstallable,
promptInstall,
canInstall,
} from "@absolutejs/pwa/client";
initInstallPrompt(); // once at boot
// React to availability (show/hide your install button):
const off = onInstallable((installable) => setShowInstall(installable));
// From a click handler (must be a user gesture):
const accepted = await promptInstall();
嵌入式浏览器和能力 UX
在提供依赖浏览器的动作之前先进行特性检测,然后使用嵌入式- 浏览器身份只用来解释无法使用的能力 :
import {
detectEmbeddedBrowser,
getBrowserCapabilities,
} from "@absolutejs/pwa/client";
const capabilities = getBrowserCapabilities();
if (!capabilities.pushNotifications && capabilities.embeddedBrowser) {
showOpenInBrowserHelp(capabilities.embeddedBrowser.app);
}
// Pure user-agent classification is also available for SSR/tests.
detectEmbeddedBrowser(request.headers.get("user-agent") ?? "");
侦测是故意保守的:Facebook、Instagram和Messet
仅从其明确的主机应用程序标记中识别。 未知的 Web 视图返回
null;能力检查仍然具有权威性.
App 更新提示
一个有缝隙的更新流柄 既包括等待服务工人 也包括释放探测器. 检测从不重新装入页面;只有用户的更新动作才有:
import {
announceUpdateAvailable,
applyUpdate,
checkForUpdate,
onUpdateAvailable,
} from "@absolutejs/pwa/client";
// Render your framework's branded prompt. A signal received before this
// subscription is retained and delivered immediately.
const off = onUpdateAvailable(() => showUpdatePrompt());
// Bridge any release detector, including @absolutejs/beacon's releaseProbe:
const onStale = (release: { currentRelease: string; newestRelease: string }) =>
announceUpdateAvailable({ ...release, source: "release-probe" });
// Safe to call on focus, visibility change, or an interval.
await checkForUpdate();
// Call only from the prompt's button. This activates a waiting worker when one
// exists, then performs exactly one bounded reload.
await applyUpdate();
服务员必须没有 skipWaiting 所以它等待着
明确征得用户同意。 重复的放行- 探测和服务- 工作信号
合并到一个提示, 而不是创建相竞的重装路径 .
每个客户端功能都具有特性安全性( API 缺失时或 API 期间没有操作)
战略秘书处. subscribeToPush 掷出 Error("notification-permission-denied") 在困难中
允许拒绝,所以您可以发送它.
许可证
麻省理工学院
长寿标签更新
订阅 onUpdateAvailable 打电话前 startAppUpdateChecks({ currentRelease, endpoint: "/version" }) 从 @absolutejs/pwa/client服务 a
无 { release } 或者说 { commit } 并嵌入同样的释放
每一页都提供了。 包裹立即检查,一次一分钟的可见,
并关注焦点、能见度和重联。 退取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取出取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取出取取出取取取取取取取取取出. 探测器
即使没有服务人员,工作也会忽略离线/不良反应
永不自动重装。 启动您的应用程序的持久更新现在按钮和
调用 applyUpdate() 只从用户动作。 等待者首先激活;
否则它执行一次重载。 启动失败的检查可以重试 .
自动更新
startAutoUpdate() 自动应用已发现的更新,此时
无法丢失工作: 立即在隐藏标签中, 或之后 idleMs (违约15s)
在可见的指针、键、轮子、触摸或滚动输入中,没有指针。 从来没有
在 a 时重新装入 dialog[open], (中文(简体) ), [role="dialog"] 或者说 [aria-modal="true"]
元素存在,而文本字段有焦点,或者您 isBusy()
返回真( 将检查数丢出为繁忙); 它重新检查每个 retryMs。 。 。 .
import {
onUpdateAvailable,
startAppUpdateChecks,
startAutoUpdate,
} from "@absolutejs/pwa/client";
const offPrompt = onUpdateAvailable(() => showUpdateBanner()); // fallback while busy
const stopChecks = startAppUpdateChecks({
currentRelease,
endpoint: "/version",
});
const stopAuto = startAutoUpdate({ isBusy: () => hasUnsavedDrafts() });
该页面在当前 URL 中重新加载 。 为繁忙的案件保留一个更新横幅 .
恢复资产负载而不丢失当前页面
startAppUpdateChecks() 还监视同源脚本、样式表和模块预装失败。 它从不自动重新装入. 订阅 onAssetLoadFailure 并行 onUpdateAvailable 显示一个重试/更新动作。 在 UI 订阅前捕获的失败会被重播到该订阅者. 原始错误仍然可供错误跟踪使用.
将处理过的路由器错误输入 reportAssetLoadFailure(error, destination)返回时返回 false 用于不相关的错误或外部目的地。 导航成功后,打电话 clearAssetLoadFailure()。在用户的明确重试时,拨打 applyUpdate({ targetUrl: failure?.targetUrl }):这在必要时激活了等待工,并替换了一次失败的目的地. 离线或失败的激活尝试仍然可以重试;没有这个明确动作,计时器就无法重装页面.