@broberg/pwa (英语)
舰队的 PWA 原始语言今天它把四号重装手卷 独立—— "有新版本可用,可以重新装入" 生命周期 - 作为一个小的、框架的和捆绑的不可知性包,而不是第五份.
npm i @broberg/pwa
0.9.0 — 一个已过时的页面重新装入自己新鲜的,一次: staleShellGuardScript() (F021.13) (法语)
部署后,一个已安装的应用程序可以在存储的页面副本上启动. 那个复制点在 /assets/ 保存已删除的部署, 404 个, 窗口将保留 白色。一个简单的重新装入可以让存储的页面返回。 该警卫为服务台(F047.5/F047.6,生产中),端口为:
import { staleShellGuardScript } from "@broberg/pwa/manifest";
// Vite: first thing in <head>, before your app script
transformIndexHtml: () => [{ tag: "script", children: staleShellGuardScript(), injectTo: "head-prepend" }],
// Next: <Script id="stale-shell" strategy="beforeInteractive">{staleShellGuardScript()}</Script>
当其中一页的 OWN 同源 /assets/ 脚本或样式表无法加载, 它导航到相同的 URL ?_v=<time> (浏览器商店从未见过的地址),最多每30 s一次,并删除 _v 从新页面上的地址栏。 图像、外国脚本和文件 /assets/ 从来没有触发它. staleShellGuardScript({ storageKey }) 设置自己的会话Storage密钥.
在飞行现场, @broberg/deploy-core ^ 0.8.2还服务于所保持部署(F033.20)的旧散货资产,因此,404型最初不会发生。 这个警卫掩护着其他的主人.
0.8.0 — 同一SVG(F021.12)的本地图标集
对于 Capacitor(iOS/Android)和Tauri apps,所以它们都没有保留自己的图标脚本:
pwa-icons --svg assets/icon.svg --native native-icons --background "#0B7A57"
写入
| 路径 | 什麽 |
|---|---|
ios/AppIcon.appiconset/AppIcon-1024.png + 键 Contents.json | Xcode 14+ 单尺寸的应用程序图标. 无 Alpha 频道 ——App Store拒绝一个具有一个的图标,因此PNG被重新编码为RGB,而不只是做不透明. |
android/mipmap-anydpi-v26/ic_launcher.xml, (中文(简体) ), ic_launcher_round.xml | 适应性图标 @color/ic_launcher_background + 键 @mipmap/ic_launcher_foreground |
android/mipmap-<dpi>/ic_launcher_foreground.png | 每个密度108dp画布(108–432 px) 内部 66dp,每个发射器面具唯一保留的部分 |
android/mipmap-<dpi>/ic_launcher.png, (中文(简体) ), ic_launcher_round.png | 遗留发射器图标, 48–192 px |
android/values/ic_launcher_background.xml | 背景颜色 |
desktop/icon.ico, (中文(简体) ), desktop/icon.icns | Windows / macOS (PNG 有效载荷) |
--background 实值 所需经费: 透明画布上的白色符号会变成空图标。 将文件夹复制到您的 Xcode/ Gradle 项目中 —— 软件包不会编辑您的本地项目 。 程序设置 : nativeIconSet(svg, { background, platforms? }) 从 @broberg/pwa/raster。网络产出(rasterizeIconSet, (中文(简体) ), pwa-icons 无 --native) 不变.
0.7.0 — 舰队报告的四个修补(F021.11)
- 初访无相旗. 一个全新的工人是短暂的
registration.waiting每安装一次( spec's 因此第一次访问显示“Ny版本 klar” (vn-leker) (英语). 最新消息现在需要一名ACTIVE工人来替换. 真正的更新总是有一个, 也在页面上与 没有控制器,所以没有真正的横幅丢失. - 默认情况下没有英国人的身体行.
labels.body除非您设置它, 否则是空的; 标题会说它 。 (横幅有: 翻译标题/按钮用来显示“重新装入以获得最新版本” - IPhone家用屏幕图标.
rasterizeIconSet()现在也返回rootFiles:180名巴布亚新几内亚人/apple-touch-icon.png财务报告和审定财务报表/apple-touch-icon-precomposed.pngiOS要求网络ROOT自行提供这些; 没有他们,它又回到了一封信。 把它们写入您的网络根( Q)pwa-iconsbin does, into the parent of 中, 输入到--out或者说--root) (中文(简体) ).pwaMetaTags现在放sizes="180x180"在苹果-touch链接. - 名单里只有PNG. 打开
rasterizeIconSet().icons——而别无他法——在表上icons[]。 。 。 . SVG 设定从buildIconSet()是发光器的源材料; SVG 条目在icons[]给了一封信 iOS 26 (jam),而每个工作的机队应用只有PNG. 过rasterizeIconSet().appleTouchIcon改为pwaMetaTags({ appleTouchIcon })。 。 。 . - 使用
pwaMetaTags头部,不仅您框架的元数据:它写着apple-mobile-web-app-capable, (中文(简体) ), 下个16'sappleWebApp.capable没有( 它写mobile-web-app-capable页:1.
0.6.0 — 一个典型的服务工作者也可以使用: pwa-sw.global.js (F021.10) (法语)
服务员 public/ 是静态文件,不能 import 这样啊
@broberg/pwa/sw (一个ES模块)是无法到达的。 现在:
cp node_modules/@broberg/pwa/dist/pwa-sw.global.js public/ # e.g. in "prebuild"
// public/sw.js
importScripts('/sw.global.js'); // @broberg/webpush, if you use it
importScripts('/pwa-sw.global.js'); // «Opdatér nu» works — the listener is attached for you
不要打电话 listenForSkipWaiting 在那个工人中.
self.BrobergPwa = { listenForSkipWaiting, SKIP_WAITING } 如果你需要的话
常数 文件名为 pwa-sw.global.js 这样它就可以坐在旁边
网络推力 sw.global.js 而不覆盖它。 导出为
@broberg/pwa/sw.global添加——没有其他变化.
0.5.0 — PNG 图标, 因此iPhone上的“ 添加到家用屏幕” 显示标志( F021. 9)
新设 pwa-icons 宾+ @broberg/pwa/raster - 见下文“PNG图标”。 添加内容 :
无已更改的输出, 核心条目仍然没有依赖性 .
0.4.1 - “最新消息”现在总是更新(F054.9)
如果您显示更新按钮, 请使用 0.4.1 . 在0.4.0的媒体 无法做任何事情, 永远:在没有现职服务人员的情况下打开一页(轮班,或 登记后的第一页),当一名新工人等待时,警卫 阻止第一个安装 重新装入新的访客 也吞下 接管媒体造成的。 没有重装,以后的媒体都找工人 这已经是活动。 店主在服务台按了30次后报道.
现在: applyUpdate() 下一次收购总是重新装入
工人已直接激活再装入;和 无 SW clientsClaim
工人到达后重新加载 activated一次重装 两次.
reloadOnControllerChange: false 仍然意味着你重新装填自己。 无 API
更改; 第一个安装仍然从未单独重新装入 .
0.4.0 — READ, 不记得了(F054. 8)
带0.4.0. 在此之前, updateReady 只能离开 上来,并且仅来自
事件: registration.waiting 附加,加 updatefound编辑
调用间隔和焦点检查 registration.update() 从不看
registration.waiting 一点也不 因此,旗帜得到了 只有一次机会
看见了 - 放弃一次,或者错过 秒是它起来,没有在
软件包可以再次为那个分页提高。 客户就坐在老包上
无限.
它在令人安心的方向失败了:在新建筑上部署绿色的服务器, 特征活泼——任何人唯一的症状是一个人说 特性缺失。 这张卡片就是这么找到的 模式.
您有什么变化 :
| 0.3.x (单位:千美元) | 0.4.0 (中文(简体) ) | |
|---|---|---|
updateReady | 升起一次,永远 | 从 registration.waiting 每个间隔/ 焦点/ 可见度勾选 |
subscribe() | 最多发射量 一次 | 当答案移动时,即发出, 双向 |
| "待会" | 你的问题 | snooze() - 30分钟默认,持续,然后它回来 |
updateReady 现在可以走了. 如果你的代码假设它只会上升..
useState 你永远不要重置,一个你手举起的横幅
升级。 其他的都是添加剂.
const { updateReady, applyUpdate, snooze } = usePwaUpdate();
// "Update" → applyUpdate() "Later" → snooze(), NOT a local setState(false)
在您的代码中查找的模式,在读取时由卡片命名 报告反对通过这些建议,这不是假设性的,而是 消费者写道:
// ⚠️ the 0.3.x shape: a local mirror, reset only on dismiss
const [needRefresh, setNeedRefresh] = useState(false);
useEffect(() => { if (updateReady) setNeedRefresh(true); }, [updateReady]);
const onDismiss = () => setNeedRefresh(false); // ← the only way down
那面镜子不会掉下来的 updateReady 做,而弃绝是永久的
——这是最初的缺陷,向上复制了一层. 放下镜子
从 updateReady 直接; 接线“ 稍后” 至 snooze()。 。 。 .
所以这里的升级是很小的 移徙,而不是免费的版本起伏。 这是 一个地方0.4.0 问你什么.
如果你被开除了 升职不能自己解决
fd-sundhed通过读取他们自己安装的代码而不是这个找到这个 报告,是其中一半将产生绿色索赔和 用户不变。 他们的旗子上挂着第二次辞退:
const [dismissed] = useState(() => sessionStorage.getItem(KEY) === "1");
if (!updateReady || dismissed) return null; // "Later" hides it for the whole tab
缺点是 双倍 ——我们的钩子上,他们的部分上——并且只有
我们的去与一个 pnpm up升级,报告固定,这个人仍然
再也见不到旗帜了.
所以在升级之前,用另一种方式 给自己的部件加固
隐藏(单位:千美元) sessionStorage编号 :localStorage 旗帜, a dismissed 状态, a
useRef 那节子 不管它被压住,它必须成为snooze,或
斯诺兹是装饰性的.
如果你需要30分钟以上的东西
snoozeMs 是一个普通的数字,所以一个大的数字是可用的,这个软件包将会
别阻止你 因此,诚实的说法比"哑巴是
不可能":没有名为"哑"的OPTION,默认会回来.
如果你真正想要的政策是 "剩下的钱都用完了"表达
作为范围而不是期限 -- -- snoozeStorage: sessionStorage 长的
snoozeMs而不是假装永久的 所以
关闭和重新打开应用程序的人又被问到,没有人需要解释
大约2255年的一个时间戳.
snooze() 故意的不是哑巴,没有办法让它变成哑巴:
上面的缺陷,是官方的。 这个
鼻涕虫一直存在(localStorage 默认, snoozeStorage: null 页:1
重新装入横幅是 请求 不能打败它.
@broberg/pwa—— 说createPwaUpdater(),用于 服务-工人更新生命周期(与Serwist、工作箱或手工滚动的SW合作).@broberg/pwa/react—— 说usePwaUpdate()钩子 + a 未设置<PwaUpdateBanner>骨架(用你自己的标志来设计).@broberg/pwa/sw—— 说listenForSkipWaiting()握手的侍从.
网页 推动 通知是一个单独关注的问题——使用
@broberg/webpush这个包裹从不触及推.
更新生命周期
找到新版本的服务员安装后 等待时间 这么说吧
无法从用户的下面删除页面. @broberg/pwa 检测到
等待工人,让用户选择何时取取,然后在活动后重新装入:
new deploy → SW installs → SW waiting → banner → user taps Update
→ applyUpdate() posts SKIP_WAITING → SW skipWaiting() → controllerchange → reload
反应使用
"use client";
import { usePwaUpdate, PwaUpdateBanner } from "@broberg/pwa/react";
export function PwaUpdater() {
// Guards are YOUR policy — pass `disabled` for native shells / dev.
const isNative = document.documentElement.classList.contains("native");
const { updateReady, applyUpdate } = usePwaUpdate({
disabled: isNative || process.env.NODE_ENV !== "production",
});
return (
<PwaUpdateBanner
updateReady={updateReady}
onUpdate={applyUpdate}
onDismiss={() => {/* hide for this session; it returns on next load */}}
className="my-banner" // ← you own the styling
labels={{ title: "Ny version klar", update: "Opdatér", dismiss: "Senere" }}
/>
);
}
更喜欢自己造UI? 单用钩子.. usePwaUpdate() 给你
{ updateReady, applyUpdate } 没有别的了。 旗帜只是方便
骨架: 它使 role="status" + 键 aria-live="polite",搭载马厩
睾丸 pwa-update-confirm 编号 : pwa-update-dismiss 编号 : pwa-update-close,以及
船舶 没有 颜色或设计系统类.
预用
与 Stack B (Bun / Hono / Preact) 应用程序的 API 相同 —— /preact 子路径
(单位:千美元)preact 是可选对等点,而不是 react:
import { usePwaUpdate, PwaUpdateBanner } from "@broberg/pwa/preact";
export function PwaUpdater() {
const { updateReady, applyUpdate } = usePwaUpdate({ disabled: isNative || isDev });
return <PwaUpdateBanner updateReady={updateReady} onUpdate={applyUpdate} className="my-banner" />;
}
usePwaUpdate() 财务报告和审定财务报表 <PwaUpdateBanner> 表现得和他们的反应一样
对口单位.
框架不可知核心
没有反应? 直接驱动控制器( Preact, Svelte, 香草) :
import { createPwaUpdater } from "@broberg/pwa";
const updater = createPwaUpdater({ swUrl: "/sw.js", disabled: isNative });
updater.subscribe(({ updateReady }) => renderBanner(updateReady));
// on the user's "Update" click:
updater.applyUpdate();
// later: updater.destroy();
createPwaUpdater(options)
| 选项 | 默认 | 含义 |
|---|---|---|
swUrl | /sw.js | 要注册的服务- 工作脚本 |
pollIntervalMs | 3_600_000 | * 检查新战略的频率; 0 禁用 |
reloadOnControllerChange | true | 新 SW 控制后重新加载页面 |
disabled | false | 惰性无-op——通过自己的后卫(内壳,dev) |
回返 { subscribe, getState, applyUpdate, destroy }没有服务员
支助(或 disabled),是一种永不放弃的惰性无能.
服务-工人方面
在您的服务人员中回答客户的激活请求:
// sw.ts
import { listenForSkipWaiting } from "@broberg/pwa/sw";
listenForSkipWaiting(); // defaults to the worker's own global scope
与 巫师编号 :工作框,继续激活用户提示 :
new Serwist({ /* … */, skipWaiting: false, clientsClaim: true });
安装设置 — 显示、 图标、 元( M)@broberg/pwa/manifest页:1
这个 其他项目 半个PWA: manifest.webmanifest,图标集,和
苹果点触 <meta> 标记——全部为 纯, 零点 工厂让你停下来
手工滚动 app/manifest.ts页:1 gen-pwa-icons.cjs 脚本和墙壁
<meta> 标签。 图标作为自成一体的发布 特别工作组对巴布亚新几内亚人来说
iPhone需要,见下文“PNG图标”(0.5.0).
import { defineManifest, serializeManifest, buildIconSet, pwaMetaTags } from "@broberg/pwa/manifest";
// 1. Icons from a monogram (or pass `svg: "<svg…>"` for real artwork).
const { files, icons } = buildIconSet({ monogram: "AK", background: "#141969", color: "#fff" });
// files → [{ path:"/icons/icon-180.svg", content:"<svg…>", … }, …] (write to public/)
// icons → manifest icons[] incl. a padded maskable-512
// 2. Manifest — required members defaulted; `extra` merges last.
const manifest = defineManifest({ name: "Aalborg Klinik", shortName: "AK", themeColor: "#141969", icons });
writeFile("public/manifest.webmanifest", serializeManifest(manifest));
// 3. Head tags — typed descriptors you render in Next metadata / a Hono head / plain HTML.
pwaMetaTags({ themeColor: "#141969", title: "AK" });
// → [{tag:"link",attrs:{rel:"manifest",href:"/manifest.webmanifest"}}, {tag:"meta",attrs:{name:"theme-color",…}}, …]
buildIconSet发放苹果(180分)、192分、512分+可伪装-512分(10%的安全区) 默认( inset) ; 覆盖sizes, (中文(简体) ),basePath, (中文(简体) ),maskable。 。 。 .180进入 苹果点触<link>,不显示icons[]。 。 。 .- 一切都是纯粹的回报价值 - 你拥有文件系统写作和头 调制。 运行在构建脚本,路由处理器或浏览器中.
- iOS需要PNG (英语). Safari 不使用 SVG 软件
apple-touch-icon: 仅使用 SVG 在 iPhone 上显示页面截图 标志。 (这个README说到0.5.0之前是相反的——这是错的
PNG图标—— pwa-icons 财务报告和审定财务报表 @broberg/pwa/raster (0.5.0,F021.9) (中文(简体) )
一个命令, 在构建时间运行; 每个应用程序没有尖锐的脚本 :
npm i -D @resvg/resvg-js # the renderer — an optional peer, prebuilt binaries
npx pwa-icons --svg logo.svg --background "#141969" --out public/icons
# or: --monogram AK --color "#fff" (also --base-path /icons)
写着 icon-180/192/512.{svg,png} + 键 icon-maskable-512.{svg,png} 和指纹
显示 icons[] (巴布亚新几内亚)和 appleTouchIcon。将头牌指向PNG:
pwaMetaTags({ themeColor: "#141969", appleTouchIcon: "/icons/icon-180.png" });
或用代码 :
import { buildIconSet } from "@broberg/pwa/manifest";
import { rasterizeIconSet } from "@broberg/pwa/raster";
const { files, icons, appleTouchIcon } = await rasterizeIconSet(buildIconSet({ svg, background: "#141969" }));
// files → [{ path: "/icons/icon-180.png", content: Uint8Array, … }] — you write them
@broberg/pwa 财务报告和审定财务报表 /manifest 保持无依赖关系 /raster 图标
需求 @resvg/resvg-js,没有它,安装命令就失效.
抓到他们了(放进这个包里 这样你就不会重新发现他们)
- 第一个安装被压制. 一个工人到达
installed没有 控制器为 第一个 安装——没有任何更新,所以没有横幅. - 没有重新装入.
controllerchange重装一次. - Serwist + Next.js 需要网页包构建器 —— 说
next build与 涡轮包装 打破农奴制的SW建设. 使用next build(网络包装). - 警卫属于你. 这个包裹不闻
NODE_ENV或一个.native班级——通过disabled因此,政策 住在一个地方 在你的应用.
许可证
麻省理工学院的一部分 @broberg/* 共享库存.