# @broberg/pwa 中文文档

规范地址：https://npmcn.com/package/%40broberg/pwa/

版本：0\.9\.0
npm 元数据更新时间：2026-10-26T19:15:18.252Z
中文译文更新时间：2026-11-08T16:04:13.073Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40broberg/pwa
原文对照：https://npmcn.com/package/%40broberg/pwa/?lang=original
项目主页：https://github.com/broberg-ai/components#readme
源码仓库：https://github.com/broberg-ai/components

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：505 kB，52 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：0 个
- peer 依赖：react \>=18\.0\.0，preact \>=10\.0\.0，@resvg/resvg-js \>=2\.6\.0
- 首次发布：2026-07-06T13:41:27.913Z
- 最新版本发布：2026-10-26T19:15:17.670Z
- 近 30 天下载量：3729（2026-10-09 至 2026-11-07，npm 官方下载统计）
- 已发布版本数：13（近 12 个月 13 个）

## 中文简介

Fleet PWA 原始:一个框架-不可知的服务-工人更新-检测控制器(新版-可用生命周期)+一个反应钩和无样式的横幅骨架+一个服务-工人跳等帮助. 零跑道口; 船-暗道口.

## 安装

```sh
npm install @broberg/pwa
```

也可以使用：`pnpm add @broberg/pwa`、`yarn add @broberg/pwa`、`bun add @broberg/pwa`

## README

# @broberg/pwa (英语)

舰队的 **PWA 原始语言**今天它把四号重装手卷 独立—— _"有新版本可用,可以重新装入"_ 生命周期 - 作为一个小的、框架的和捆绑的不可知性包,而不是第五份.

```bash
npm i @broberg/pwa
```

## 0.9.0 — 一个已过时的页面重新装入自己新鲜的,一次: `staleShellGuardScript()` (F021.13) (法语)

部署后,一个已安装的应用程序可以在存储的页面副本上启动. 那个复制点在 `/assets/` 保存已删除的部署, 404 个, 窗口将保留 **白色**。一个简单的重新装入可以让存储的页面返回。 该警卫为服务台(F047.5/F047.6,生产中),端口为:

```ts
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,所以它们都没有保留自己的图标脚本:

```bash
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.png`iOS要求网络ROOT自行提供这些; 没有他们,它又回到了一封信。 把它们写入您的网络根( Q) `pwa-icons` bin 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's `appleWebApp.capable` 没有( 它写 `mobile-web-app-capable` 页:1.

## 0.6.0 — 一个典型的服务工作者也可以使用: `pwa-sw.global.js` (F021.10) (法语)

服务员 `public/` 是静态文件,不能 `import` 这样啊 `@broberg/pwa/sw` (一个ES模块)是无法到达的。 现在:

```sh
cp node_modules/@broberg/pwa/dist/pwa-sw.global.js public/   # e.g. in "prebuild"
```

```js
// 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` 你永远不要重置,一个你手举起的横幅 升级。 其他的都是添加剂.

```ts
const { updateReady, applyUpdate, snooze } = usePwaUpdate();
// "Update" → applyUpdate()     "Later" → snooze(), NOT a local setState(false)
```

**在您的代码中查找的模式**,在读取时由卡片命名 报告反对通过这些建议,这不是假设性的,而是 消费者写道:

```ts
// ⚠️ 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通过读取他们自己安装的代码而不是这个找到这个 报告,是其中一半将产生绿色索赔和 用户不变。 他们的旗子上挂着第二次辞退:

```ts
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`](https://discovery.broberg.ai/)这个包裹从不触及推.

## 更新生命周期

找到新版本的服务员安装后 **等待时间** 这么说吧 无法从用户的下面删除页面. `@broberg/pwa` 检测到 等待工人,让用户选择何时取取,然后在活动后重新装入:

```
new deploy → SW installs → SW waiting → banner → user taps Update
  → applyUpdate() posts SKIP_WAITING → SW skipWaiting() → controllerchange → reload
```

## 反应使用

```tsx
"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`:

```tsx
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, 香草) :

```ts
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`),是一种永不放弃的惰性无能.

## 服务-工人方面

在您的服务人员中回答客户的激活请求:

```ts
// sw.ts
import { listenForSkipWaiting } from "@broberg/pwa/sw";
listenForSkipWaiting(); // defaults to the worker's own global scope
```

与 **巫师**编号 :**工作框**,继续激活用户提示 :

```ts
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).

```ts
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) (中文(简体) )

一个命令, 在构建时间运行; 每个应用程序没有尖锐的脚本 :

```sh
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:

```ts
pwaMetaTags({ themeColor: "#141969", appleTouchIcon: "/icons/icon-180.png" });
```

或用代码 :

```ts
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/*`](https://discovery.broberg.ai/) 共享库存.

## 常见问题

### @broberg/pwa 是什么？

Fleet PWA 原始:一个框架-不可知的服务-工人更新-检测控制器\(新版-可用生命周期\)\+一个反应钩和无样式的横幅骨架\+一个服务-工人跳等帮助\. 零跑道口; 船-暗道口\.

### 如何安装 @broberg/pwa？

在项目目录运行 npm install @broberg/pwa，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 pwa-icons，可以用 npx pwa-icons 直接运行。

### @broberg/pwa 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @broberg/pwa 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @broberg/pwa 可以商用吗？

@broberg/pwa 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @broberg/pwa 的下载量有多少？

根据 npm 官方下载统计，@broberg/pwa 在 2026/10/09 – 2026/11/07 这 30 天内被下载 3,729 次，日均约 124 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @broberg/pwa 还在维护吗？

最新版本 0\.9\.0 发布于 2026/10/27（12 天前）；至今共发布 13 个版本，其中过去 12 个月发布了 13 个；首次发布于 2026/07/06。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

