# @12-apps/pwa 中文文档

规范地址：https://npmcn.com/package/%4012-apps/pwa/

版本：2\.6\.2
npm 元数据更新时间：2026-09-05T01:40:39.595Z
中文译文更新时间：2026-11-05T19:59:49.339Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%4012-apps/pwa
原文对照：https://npmcn.com/package/%4012-apps/pwa/?lang=original
项目主页：https://github.com/12-apps/shared-packages#readme
源码仓库：https://github.com/12-apps/shared-packages

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

- 包体积（解压后）：144 kB，31 个文件
- 模块格式：ES Module
- TypeScript 类型：未声明
- Node.js 要求：\>=22\.0\.0
- 运行依赖：1 个
- peer 依赖：@12-apps/wiring \>=1\.9\.0，hono \>=4\.0\.0，react \>=19\.0\.0，react-dom \>=19\.0\.0
- 首次发布：2026-08-07T20:02:13.653Z
- 最新版本发布：2026-09-05T01:40:39.226Z
- 近 30 天下载量：32584（2026-10-04 至 2026-11-02，npm 官方下载统计）
- 已发布版本数：19（近 12 个月 19 个）

## 中文简介

使一个网络应用程序可以安装,并告诉人们: 安装前即时状态机器 + iOS 共享表检测 + 压倒性 pt-BR 复制 (.),安装邀请 (./反应), PER-HOST 显示的端点和被包的网络第一服务wor

## 安装

```sh
npm install @12-apps/pwa
```

也可以使用：`pnpm add @12-apps/pwa`、`yarn add @12-apps/pwa`、`bun add @12-apps/pwa`

## README

# `@12-apps/pwa`

让一个网络应用程序可以安装 并告诉人们它.

捕获 `beforeinstallprompt` 永远不要发射它, 识别iOS 安装为手动共享表动作的浏览器,并发送邀请 这导致的原因 而不是指示。 主机不可知:每个 字符串来自一个压倒性pt-BR消息层.

## 使用量

```tsx
import { InstallInvite } from "@12-apps/pwa/react";
import { reportWarning } from "@12-apps/observability-frontend";

<InstallInvite
  what={store.displayName}
  enabled={isStoreOwnDomain}
  onDiagnostic={reportWarning}
/>
```

| 条目 | 这是什么 |
| --- | --- |
| `@12-apps/pwa` | `useInstallPrompt`, (中文(简体) ), `isIosInstallable`, (中文(简体) ), `isStandalone`, (中文(简体) ), `isHandheld`,信息层, `registerServiceWorker` 编号 : `postToServiceWorker`,则 **重新装入** 一半 - `needsPullToRefresh`, (中文(简体) ), `isInstalledHandheld`, (中文(简体) ), `reloadApp`, (中文(简体) ), `createPullTracker` |
| `@12-apps/pwa/react` | `InstallInvite`, (中文(简体) ), `ShareIcon`, (中文(简体) ), `PullToRefresh` |
| `@12-apps/pwa/server` | `createApiPwa({ resolveApp })` ——每个东道主 **显示终点** 和包装的服务人员 `buildWebAppManifest` 财务报告和审定财务报表 `pwaServiceWorkerSource` |
| `@12-apps/pwa/hono` | `pwaRouter({ resolveApp })`,安装在原生根上. `hono` 是可选对等点 |

根项是无框架的,所以一个只需要“这可以 安装的“不会通过它没有要求的枪管拉入反应.

**[采用.md](https://npmcn.com/package/%4012-apps/pwa/ADOPTING.md) 收养合同** - 配置表和 5个线圈规则 咬.

## 是什么使得一个应用程序可以安装(12-23)

以上邀请 _询问_有两个东西必须先存在 这里的两艘船:

1.  **一份清单,作为一份ENPOINT——从来不是静态文件.** 一个PWA的身份是它的 原产地,而捆绑则有一个 `index.html` 以它所服务的每个佃户发誓, 如此静态 `manifest.webmanifest` 无法改变的商店 访问者是 看着. `resolveApp` 返回时 `null` 是一个404,404是整个 可安装门.
2.  **每一次访问都会有一位重新配置的服务员.** `registerServiceWorker()` 属于 app 启动时, 而不是设置屏幕后: 源主机注册了它 仅来自 `enableWebPush()`,所以一个访客 谁从来没有打开通知 偏好没有工人——浏览器从未提出安装商店.

```ts
const pwa = pwaRouter({ resolveApp: ({ host }) => appForHost(host) });
app.route('/', pwa.router);           // the manifest, at the ORIGIN ROOT
registerServiceWorker();              // in the SPA's entry, once
```

**包装工人是网络第一的文档,这不是 优先选择.** 在捆绑的SPA中,每个散列文件名都会随着部署而死 产生了它,一个历史倒转 回答一个消失的块 `index.html` —— 说 在 MIME 类型上失败的, 到达 `React.lazy`,使页面变为空白。 A 类 天真的缓存第一工人把旧的外壳钉住,使空白页变得一成不变; 在已安装的应用程序上,“force-refresh”是用户无法遵循的建议.

## 重新装入

安装应用程序将地址栏取出,再装入按钮—— 在应用程序被焊接时,它就很好:一个旧的外壳 部署、 未注意到页面已过期的会话、 屏幕 获取失败 。 这套文件已经说明了成本,第5条 [采用.md](https://npmcn.com/package/%4012-apps/pwa/ADOPTING.md)数字 : _在安装的应用程序上,“force-refresh”是建议 用户无法跟踪 ._ 工人修补了可以修补的那一半,没有 用户. `PullToRefresh` 这是另一半.

```tsx
import { PullToRefresh } from "@12-apps/pwa/react";
import { PULL_TO_REFRESH_MESSAGES } from "@12-apps/pwa";

<PullToRefresh messages={PULL_TO_REFRESH_MESSAGES["pt-BR"]} onDiagnostic={reportWarning}>
  <App />
</PullToRefresh>
```

**把整个应用包起来 不需要花多少钱**因为那里 它什么也没有. `needsPullToRefresh()` 门是真实的 完全一个组合:

| 地点 | 有重装吗? | 为什么 |
| --- | --- | --- |
| 任何浏览器标签 | 对 | 地址栏,加上浏览器本身的超滚动刷新 |
| 独立铬(Android) | 对 | **安装时保持了过度滚动的新鲜度** 除非应用程序本身选择退出 `overscroll-behavior-y: contain | none` |
| 桌面独立 | 对 | 没有地址栏,但是 `Ctrl+R` 和上下文菜单 |
| **iOS 主屏幕** | **没有** | 没有铬,在Safari中重新装入的拉动手势不会重新装入一个独立的网络应用程序. 野外的劳动是 _删除图标并再次添加_ |

因此,在默认情况下,手势船 iOS 和其他地方 为: _不安全_ 但因为一个已经起作用的平台姿态 原生的感觉和杂乱无章,不能被 JavaScript 失败所丢失 .

**也用在Android上,通过 `platform={isInstalledHandheld}`。 。 。 .** 这是 支持选择,而不是绕行,移交是干净的而不是 倍数: 正在安装的套件 `overscroll-behavior-y: contain`,而这正是 将Chromium的过度卷轴刷新。 一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一 这是你的——两个平台上相同的指标和门槛. 它在安全方向上也失败了: 如果捆绑从未运行, 财产就是 从来没有设定,克洛米姆的姿态仍然在那里.

当你想用一个手势来设计和支持每一个电话时, 或用于Android浏览器,其已安装的应用程序确实 _没有_ 留着那个本地的. 注意你放弃了什么 在Android上 你正在替换一个手势 保持一个你维护.

`isInstalledHandheld` 故意排除已安装的 DESKTOP 应用程序—— 无地址 栏,但 `Ctrl+R`,一个上下文菜单,没有触摸屏可以拉起。 端对端 测试驱动桌面浏览器通过 `() => true`。 。 。 .

### 从自己的路径,而不是从枪管中导入手势

主机挂载 `PullToRefresh` 所以无论进口到哪里 它正走着关键的道路. `@12-apps/pwa/react` 再出口 `InstallInvite`,以及 `@12-apps/pwa` 重新导出邀请信件包和 `beforeinstallprompt` 状态机器,所以从其中之一导入手势 桶将邀请函放入条目的模块图中,然后由捆绑器折叠 进来吧.

这是衡量,而不是理论。 {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}在一个能摆出姿态的东道主 根,安装邀请器从懒惰的块中移出 **输入条目块**数字 : +9.3 KiB 生 / + 2.4 KiB brotli 首绘代码,只运行于一个上 离职确认屏幕 .

```ts
// on the critical path — reaches the gesture and nothing else
import { PullToRefresh } from "@12-apps/pwa/react/pull-to-refresh";
import { PULL_TO_REFRESH_MESSAGES } from "@12-apps/pwa/pull-to-refresh-locales";
import { isInstalledHandheld } from "@12-apps/pwa/reload";
```

进口邀请的机主机还是正确的,或者说一个 门没有捆绑大小。 三分两分就能走窄路 他们中没有人会改名: `platform.ts` 持有三个上游 没有反应, `pull-to-refresh.{pt-BR,en-US}.ts` 拿着手势的复制件 从邀请, 和每一个原 模块再出口什么移动.

### `reloadApp()` 还不完全一样 `location.reload()`

打开的文档由加载时活跃的工人控制, 而浏览器本身的更新检查比对导航 因此,一旦部署的土地仍能由 即将离任的工人,把用户试图逃跑的外壳还给我. `reloadApp()` 首先要求更新并等待, 以 2 为边框 (缺省),因为刚刚拉倒的人通常是其 网络今天很不顺 每个失败路径仍然重新装入: 重新装入用户 要求的绝不是应用程序拒绝做的事情.

### 手势不会这样

3件事情是不能打破的 每件事情都是建筑所阻止的 检查一下有没有人记得:

-   **卷行相传.** 头12px旅行是 _观看和不消耗_ —— 说 `preventDefault()` 只有追踪者要求手势时才叫它 这对手指向上移动或侧向移动来说 从来都不是.
-   **任何在门户.** 听者在组件自己的树下, 所以一个MUI `Drawer` 或者说 `Dialog` - 变成 `document.body`,一个兄弟 内部的一切——无法到达它们.
-   **内作卷轴.** 已经向下滚动的列表保持自己的拉力 。 A 类 在标记中 `data-pull-refresh="off"`。 。 。 .

包装是 `display: contents`,所以它不会改变布局:孩子会留下来 父公司自己的弹性或网格项目. `offsetTop` 财务报告和审定财务报表 `zIndex` 设置指标 在主机固定的铬上方——曝光而不是硬码,因为应用 使用安装邀请器的 _联合国_ 固定放置方式 `!important`。 。 。 .

## 两个没有分享的平台

**铬** 火灾 `beforeinstallprompt`,它被俘获和 **举行** 从来没有 自动发射。 一个浏览器让一个页面询问一次,第一个询问一次 访问,在访客知道应用程序是什么之前, 花一个机会在一个 近乎肯定的"否",浏览器随后会长期记忆. 按钮是 访客的.

注意点火 **桌面** 就像在Android上一样 复制品由 `(pointer: coarse)` 而不是假设一个电话.

**iOS 完全没有 API**在任意浏览器中。 非暂时性:没有 `beforeinstallprompt` 在Safari 26.0-26.6或27β, MDN的相容数据记录 `safari: false` 与 `safari_ios` 财务报告和审定财务报表 `webview_ios` 反映——和 `webview_ios` 每个iOS浏览器是什么, Chrome 包含 —— WebKit 的 在网络安装 API 上的标准位置(`navigator.install`)为 **反对**。 。 。 . 共享工作表的设计.

`isIosInstallable()` 故意不检查 _哪个_ 浏览器. 不包括 `CriOS`编号 :`FxiOS`编号 :`EdgiOS` 2023年3月之前就已经是了 并且从iOS 16.4开始就有了错误 将“ 添加到家屏幕” 打开至任何带有此功能的浏览器 `com.apple.developer.web-browser` 权利,所以排除 他们告诉大 iPhone的用户份额完全没有.

## IOS 指令是设计工作所在

单塔按钮自行转换. 书面指示必须生存 阅读,理解,然后采取行动 违反控制的人从来没有 刻意地看着——在两秒钟里,他们用闪闪发光的旗帜. 接下来是三件事,每件事物的替换 显而易见的版本出了问题:

1.  **其由由相导.** 第一个版本以“ 添加到您的家” 打开 屏幕,并将报酬降为灰色字幕文本. 没有人增加一个网站 因为他们想在家庭屏幕上添加一个网站。 打开 iOS 支付额也是被封门的 —— 网络推力不存在于一个外部 已安装的应用软件——所以“准备好就被告知”是 _无_ 直到他们知道 这个 这是头条.
2.  **取出格来,不是字来.** "Tap Share"要求从一个单词翻译 到一个形状. `ShareIcon` 和浏览器中的染色体相同 所以 没有什么可翻译的。 画入: SF 符号是 Apple 的,并且是 an 图标字体将是一个网络回合,其全部工作是 立即被理解.
3.  **它指出来.** Safari的股权控制在 **下边** 栏和横幅 在页面的顶端 一点也没有. `placement="anchored"` (单位:千美元) 默认)将卡片修正到控制上方,并瞄准它. `placement="inline"` 当主机已经放低时选择退出 .

**老实说天花板.** 这些都没有使iOS安装 _不错_ 苹果公司 不需要API, 转基因在任何地方都很差。 这是一个发现支付, 不是漏斗,值得衡量 而不是假设.

## 诊断

拒绝出现的邀请失败 **安静**: 没有扔,所以 破碎的一页看起来很健康. `onDiagnostic` 被告诉一次每 载荷,载荷为决定表:

| 字段 | 什麽 `false` 表示 |
| --- | --- |
| `earlyScriptPresent` | 文档先于内置抓取——部署 |
| `earlyEventHeld` | 浏览器从未判断可安装的页面 |
| `earlyEventFiredAt` 设定但 `hasDeferred` 虚假 | 藏品未被采纳 |
| `installed` 编号 : `dismissed` 真实 | 工作如设计,不是错 |

## 测试

```bash
pnpm --filter @12-apps/pwa test
```

## 常见问题

### @12-apps/pwa 是什么？

使一个网络应用程序可以安装,并告诉人们: 安装前即时状态机器 \+ iOS 共享表检测 \+ 压倒性 pt-BR 复制 \(\.\),安装邀请 \(\./反应\), PER-HOST 显示的端点和被包的网络第一服务wor

### 如何安装 @12-apps/pwa？

在项目目录运行 npm install @12-apps/pwa，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：react（\>=19\.0\.0）、react-dom（\>=19\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @12-apps/pwa 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/12-apps\_\_pwa 是否存在。

### @12-apps/pwa 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @12-apps/pwa 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=22\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @12-apps/pwa 可以商用吗？

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

### @12-apps/pwa 的下载量有多少？

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

### @12-apps/pwa 还在维护吗？

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

