# @devopsplaybook\.io/common-web 中文文档

规范地址：https://npmcn.com/package/%40devopsplaybook.io/common-web/

版本：0\.12\.1
npm 元数据更新时间：2026-11-05T21:35:37.841Z
中文译文更新时间：2026-11-12T03:53:33.329Z
软件包许可：ISC

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

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

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

- 包体积（解压后）：90.3 kB，26 个文件
- 模块格式：ES Module
- TypeScript 类型：未声明
- Node.js 要求：\>=22
- 运行依赖：3 个
- peer 依赖：vue ^3\.5\.0，nuxt ^4\.0\.0，pinia ^2\.0\.0 \|\| ^3\.0\.0 \|\| ^4\.0\.0
- 首次发布：2026-09-27T14:02:30.967Z
- 最新版本发布：2026-11-05T21:35:37.598Z
- 近 30 天下载量：3827（2026-10-12 至 2026-11-10，npm 官方下载统计）
- 已发布版本数：29（近 12 个月 29 个）

## 中文简介

DevOpsPlaybook 网络应用程序共享 Nuxt 层

## 安装

```sh
npm install @devopsplaybook.io/common-web
```

也可以使用：`pnpm add @devopsplaybook.io/common-web`、`yarn add @devopsplaybook.io/common-web`、`bun add @devopsplaybook.io/common-web`

## README

# @devopsplaybook.io/common-web (英语)

一个小的,不建 Nuxt 4层 包含共享设计符牌,UI组件, devOpsPlaybook 网页应用程序的可编译和浏览器服务.

## 快开始

```sh
npm install @devopsplaybook.io/common-web
```

从您的 Nuxt 配置中扩展层 :

```ts
export default defineNuxtConfig({
  extends: ["@devopsplaybook.io/common-web"],
});
```

层组件和可堆积由Nuxt自动导入. 货船 原始 Vue 和 TypeScript 源; 您的应用程序的 Nuxt 构建汇编它们 。 纳克特4是 所需经费。 这个 `playground/` 目录显示一个消耗性应用.

## 构成部分

| 构成部分 | 目的 |
| --- | --- |
| `<Loading size="small" />` | 可用的装载指标; `size` 实值 `small` 或者说 `large`。动画在 `prefers-reduced-motion: reduce`。 。 。 . |
| `<AlertMessages />` | 可访问的现场区域,显示发布的信息 `EventBus`,每个带每个消息 **开除** 按钮. |
| `<AppNavigation :links="links" :link-component="NuxtLink" label="Primary" />` | 带有名称的导航外壳 `brand` 插槽,可配置链接(`label`, (中文(简体) ), `to`选项 `icon` 财务报告和审定财务报表 `active`)和可选择的可访问性 `label`。 。 。 . |
| `<OfflineBanner message="You are offline." />` | 宣布下线状态,并通过默认槽接受替换内容. |

`AlertMessages` 监听 `EventTypes.ALERT_MESSAGE` 事件。 它的有效载荷是: `{ text, type?, durationMs? }` 与 `type` 限于 `info`, (中文(简体) ), `success`, (中文(简体) ), `warning` 或者说 `error`。默认显示时间为5秒; `durationMs: 0` 保存信件直到用户激活 **开除** 按钮。 负持续时间被夹到 `0`他们将永居其中; 非无限值`NaN`, (中文(简体) ), `Infinity`)使用五秒默认值. 错误渲染 充满自信 `role="alert"` 以礼相待的方式 `role="status"` 区域。 这两个地区是兄弟姐妹,总是挂起,所以 每条消息都公布一次。 解除管制是本地人 `<button type="button">` 带有无障碍名称 `Dismiss` 和明显的焦点 铃声。 同名词 `type` + 键 `text` 双对被复制,队列不变 大部分5条留言, 放弃最古老的第一。 提醒样式使用前缀 `.alert-message*` 分类,所以消费者样式表不受 层的全局样式. `handleError(error, { debug = false } = {})` 日志 a 静态摘要(消息、状态、方法、没有查询字符串的路径) 带有证书被编辑)并发出相应的出错提示. `debug: true` 日志原始错误对象,其中可能包含证书,并且是 仅供发展之用.

`AppNavigation` 简单化 `<a href>` 默认链接, 保留 非纳克特深层进口和原材料使用有效。 Nuxt 应用程序应当 通过它们的链接组件来保持SPA状态的导航:

```vue
<script setup lang="ts">
import { resolveComponent } from "vue";

const NuxtLink = resolveComponent("NuxtLink");
</script>

<template>
  <AppNavigation :links="links" :link-component="NuxtLink" />
</template>
```

这个 `label` 道具设置可访问导航的名称和默认值 `Main navigation`。在页面上给每个导航一个不同的标签,这样屏幕 读者用户可以分辨:

```vue
<AppNavigation :links="primaryLinks" label="Primary" />
<AppNavigation :links="secondaryLinks" label="Secondary" />
```

链接按目标和位置键,所以重复 `to` 目标仍在实现; 在开发中,组件在检测到重复时记录警告.

`OfflineBanner` 保留它 `role="status"` 随时挂起的活区 屏幕阅读器宣布过渡; 而在线区域为视觉 藏起来 横幅会隐藏在服务器 HTML 中并反映真实 水合后连接 默认副本为中性 `You are offline.`; 替换为 `message` 道具或默认槽.

## B. 可构成物和服务

-   `useTheme()` 持续 `light`编号 :`dark` 首选项 `localStorage` 并适用 `data-theme` 转到文档根。 状态是一个全单元的单子: `useTheme()` 调用相同 `preference` 财务报告和审定财务报表 `isDark` 裁判,请稍等 电话里没看到一份烂拷贝 窗口 `storage` 听者保持分页同步 . `isDark` 反映有效主题:默认 `system` 偏好 如下 `prefers-color-scheme`,包括实时操作系统变化,以及 `toggleTheme()` 与有效值脱节。 使用 `setTheme("system")` 返回到操作系统的偏好。 何时 `localStorage` 缺少 (SSR)或被屏蔽(sandboxed iframe,隐私模式),主题仍然适用 只有坚韧性被跳过. 该图层还注入了小的预绘 `<head>` 应用的脚本 `data-theme` 从 `localStorage` 财务报告和审定财务报表 `prefers-color-scheme` 开始之前 涂料,所以存储的黑暗偏好不再闪出光主题 装入。 具有严格CSP的应用程序必须允许此内置脚本(nonce 或 `unsafe-inline`没有它 `prefers-color-scheme` CSS 路径仍然 应用,主题在水合后解决. 设定 `COMMON_WEB_THEME_SCRIPT_NONCE` 构建时的环境变量 在被注入的标签上添加一个非ce( 读取时间为 `nuxt.config.ts` 实值 (评价) 共享层不支持每个请求的非ce: 构建 与导出项相连接的头条目 `themeInitScriptEntry(nonce)` 助手从 `@devopsplaybook.io/common-web/composables/theme` 并覆盖 `app.head.script` 在消耗性应用.
-   `useAppHeight()` 更新 `--app-height` 从 `visualViewport` 可用时 并清理卸载上的听众大小。 调整更新大小与 `requestAnimationFrame`,因此重复调整事件大小和多个组件 实例每个框架最多写出一次自定义属性。 待决框架 只在最后一次卸载时才取消, 所以卸载一个组件永远不会取消另一个组件的更新.
-   `useOfflineStatus()` 返回反应 `isOnline` 参考: 开始是 `true` 因此,服务器 HTML 和第一个客户端渲染协议,然后读取 `navigator.onLine` 在挂起并跟随 `online`编号 :`offline` 事件,所以 已装入下线的页面显示在水合后右侧的下线横幅 水分不匹配.
-   例如,通过包深进口提供各种服务 `@devopsplaybook.io/common-web/services/AuthService`。 。 。 . `AuthService`, (中文(简体) ), `PreferencesService` 财务报告和审定财务报表 `RefreshIntervalService` 守护每个 `localStorage` 通过内部 `BrowserStorage` 帮助者,所以在SSR或与 被屏蔽的存储读取返回他们的已记录倒计时, 而写作是无操作的 .
-   `createAuthenticationStore()` 返回 Pinia 存储定义; `Pinia` 必须在消费应用程序中提供.

犬类认证存储密钥是 `auth_token`在此兼容期间 释放, `AUTH_TOKEN` 财务报告和审定财务报表 `AUTH_TOKEN_KEY` 读取并迁移到 警犬钥匙 托肯斯留在这 `localStorage`,匹配现有应用程序. 当一个经认证的标志 进入其寿命的最后20%, `AuthService` 通过更新 `POST /api/users/session/refresh` 输入 背景情况. `getToken()` 财务报告和审定财务报表 `getAuthHeader()` 返回仍然有效的当前 信号符立即发出,下一个呼叫会看到更新的信号符,所以缓慢地刷新 终点从来不会拖住打电话者.

`getToken()` 绝不因存储或更新的符号而拒绝:

-   腐败或不可解密的令牌被视为已签名 : 每个认证密钥是 已删除, `AUTH_UPDATED` 已排放,并且 `null` 已返回。 过期代币为 删除并返回 `null`。礼物 `exp` 或者说 `iat` 索赔必须是有限的 数字;带有字符串或有其他错误的债权的符号是腐败的.
-   A 类 `401` 或者说 `403` 从刷新端点表示会话被取消: 届会被清除, `AUTH_UPDATED` 已排放,并且 `null` 已返回.
-   超时和无效的续作回复执行单一请求. 网络 错误和 `5xx` 回复在500米后重试一次.
-   当续签仍然失败时, 返回仍然有效的当前符号 进一步更新该标志的尝试暂停30秒。 更新 在背景中运行,所以最糟糕的情况是 大约6.5秒的背景 工作(2个3s的尝试加上500ms的后退),从不挡住呼叫器. 如果在尝试中该符号过期,会话将被清除并稍后结束 调用返回 `null`。 。 。 .
-   3秒后续约请求超时, 同时通话共享一个单次 请求。 在飞行中保存的标志胜过更新 数值.
-   重新发行的代币被验证(可解码、非空地、未来) `exp`,以及 `exp > iat` 何时 `iat` 在那之前.
-   `AUTH_RENEWAL_FAILED` 以 `{ reason }`时 `reason` 这是其中之一 `timeout`, (中文(简体) ), `5xx`, (中文(简体) ), `network` 或者说 `invalid-response`。它没有符号、 URL 或 PII;消费者可以使用自己的遥测仪. 此软件包添加无 OpenTeleometry 度量衡或依赖性.

`removeToken()` 清除每个存储的认证密钥. `removeToken(token)` 是一个 比较和移动操作: 它只在存储的符号时清除会话 仍然相等 `token`,因此,僵化的反应不能丢弃更新的会话.

## 认证状态和 HTTP 集成

`AuthService.saveToken()` 财务报告和审定财务报表 `removeToken()` 发射 `EventTypes.AUTH_UPDATED` 编辑 `EventBus` 当存储的符号实际 更改; 延长和到期通过这些方法。 皮尼亚店订货 到事件和刷新 `isAuthenticated`,所以更新,登录在另一个 选项卡或过期的符号不再离开 UI stale。 给添加剂打电话 `refreshAuthentication()` 操作手动刷新; `ensureAuthenticated()` 仍然装入初始状态。 商店还监听浏览器 `storage` ,使符号在标签中同步更改.

Bearer-token 附加是选入的: 分层船只有注册帮助器 而不注册插件,所以已有应用程序保持当前 行为。 默认时在耗用应用程序中添加客户端插件 Axios 实例应认证请求,并清除会议 `401`数字 :

```ts
// plugins/auth.client.ts
import { registerAxiosAuthInterceptors } from "@devopsplaybook.io/common-web/services/AxiosAuthInterceptor";

export default defineNuxtPlugin(() => {
  registerAxiosAuthInterceptors();
});
```

`registerAxiosAuthInterceptors(instance = axios, { allowedOrigins = [], loginPaths = ["/users/session"] } = {})` 附加 `Authorization: Bearer <token>` 只有在请求不明确时 `Authorization` 页眉和 允许有效目标:

-   相对 URL 、 页面来源、 绝对源 `Config.SERVER_URL` 和清单所列任何来源 `allowedOrigins` 即接受迹象;
-   向任何其他来源提出的跨原产地请求没有收到任何征兆,不触发 符号更新, 当绝对 URL 无法解析时, 失败关闭 ;
-   `allowedOrigins` 条目已恢复正常化为来源和无效条目 掷出 `TypeError`· ;
-   登记为每Axios实例的同位素并返回 `false` 何时 已经注册; 选项仅适用于第一次注册.

A 类 `401` 仅在失败的请求使用当前时清除存储的符号 存储的代号(所附代号记录在请求上或从 发送 `Authorization` 头曰. 烂透了 `401` 被忽略,a `401` 从a 请求没有寄出任何指示牌,则无法澄清任何问题。 登录路径可配置通过 `loginPaths`: 有效路径名上的后缀匹配, 默认 `["/users/session"]`,在配置时替换,而忽略了空条目. `loginPaths: []` 豁免任何路径.

### 服务器 URL 配置

`Config.get()` 返回时 `{ SERVER_URL: "/api" }` 默认。 输入不同的 基础 URL, 例如来自 Nuxt 客户端插件, 并重置用于测试 :

```ts
import Config from "@devopsplaybook.io/common-web/services/Config";

Config.set({ SERVER_URL: "https://api.example.com" });
await Config.get(); // { SERVER_URL: "https://api.example.com" }
Config.reset(); // back to "/api"
```

`Config.set()` 修剪白相间并去除后遗症,所以 `"https://api.example.com///"` 财务报告和审定财务报表 `"/api/"` 变成 `"https://api.example.com"` 财务报告和审定财务报表 `"/api"`在开发中,它警告URL使用时 `http:` 而不是一个 循环主机( r)`localhost`, (中文(简体) ), `127.0.0.1`, (中文(简体) ), `[::1]`) (中文(简体) ). 一个非同源 `SERVER_URL` 必须使用HTTPS,并允许通过CORS生成应用程序源; 跨原产地请求只有在来源是 配置 `SERVER_URL` 原产地或列于 `allowedOrigins`。 。 。 .

### 服务退后

`UserService.isInitialized({ timeoutMs = 5000, signal, cacheTtlMs = 0 } = {})` 决定 `false` 网络或 HTTP 错误而不是拒绝, 因此设置代码 可以安全地打开门 每项请求都以下列条件为准: `timeoutMs` (默认为5 s) 并接受可选 `AbortSignal`与 `cacheTtlMs > 0` 一个成功的 `true` 在此期间对结果进行再利用(按URL键); `false` 永远 缓存和 `cacheTtlMs: 0` 禁用缓存。 失败将警告记录为 `reason` (单位:千美元)`timeout`, (中文(简体) ), `aborted`, (中文(简体) ), `http-<status>` 或者说 `network`)和没有 URL, 符号 或反应机构. `RefreshIntervalService.get()` 倒计时 `"10000"` 当存储值是 失踪或畸形; `set()` 正常化有效的非负整数字符串 (例如 `"05000"` 变成 `"5000"`)并投掷 `TypeError` 否则. `"0"` 有效,并禁止投票。 两者 `PreferencesService` 财务报告和审定财务报表 `RefreshIntervalService` 容忍丢失或被封存: 读取返回 `null` 编号 : `"10000"` 写作被跳过,故他们在安全无虞 无效 `set()` 值仍然丢出 `TypeError`。 。 。 .

## SSR和仅限客户使用

该图层具有SSR兼容性:组件在服务器上渲染 堆肥者守护他们的浏览器只访问.

-   `useTheme()` 保持模块级别状态,但触摸 `document`, (中文(简体) ), `window` 财务报告和审定财务报表 `localStorage` 仅在 `onMounted` (在安全部门改革期间从未运行)和通过 守护者 `BrowserStorage` 帮助; 服务器总是使默认值 `system` 优先选择.
-   `useOfflineStatus()` 备忘 `isOnline` 改为 `true`因此,服务器和 第一客户端达成一致意见; 真实值读取于 `onMounted`,所以一个 离线页面显示水合后而非服务器上的横幅 HTML (英语).
-   `useAppHeight()` 触摸 `window` 仅在内部 `onMounted`。 。 。 .
-   `AuthService`, (中文(简体) ), `PreferencesService` 财务报告和审定财务报表 `RefreshIntervalService` 守护每个 `localStorage` 访问:在安全部门改革期间,读取返回记录的倒计时 写作是没有的.

托肯存储, 会话更新, `AUTH_UPDATED` 跨塔布传播 同步和选入 Axios 集成是只浏览器: 注册 Axios 来自 a 的助手 `.client.ts` 如上所示的插件,并期望 认证状态只有在水合后才有意义 .

`tests/ssr.spec.ts` 使运出组件与 `createSSRApp` 财务报告和审定财务报表 `renderToString` 在一个节点环境中,所以这个服务器发送合同是 执行人 `npm test` 和通过CI工作流程.

## 脚本和app-shell 样式

层负载 `assets/css/tokens.css` 财务报告和审定财务报表 `assets/css/app-shell.css`。 。 。 . 键包括 `--color-*` (包括每个状态前景符号) `--color-on-success`, (中文(简体) ), `--color-on-error` 财务报告和审定财务报表 `--color-on-warning` 用过的 `--color-success`, (中文(简体) ), `--color-error` 财务报告和审定财务报表 `--color-warning`, (中文(简体) ), `--space-*`, (中文(简体) ), `--text-*`, (中文(简体) ), `--radius-*`, (中文(简体) ), `--shadow-*`, (中文(简体) ), `--header-height`,以及 `--app-height`。可以选择暗模式 `data-theme="dark"` 或来 从 `prefers-color-scheme` 当没有设定明确的光线偏好时。 状态 颜色与WCAG AA相对 `--color-on-*` 两者的前景标志 主题. `--color-primary` 财务报告和审定财务报表 `--color-primary-hover` 两者的定义 主题和在运出时遇到 AA(4.5:1) `--color-surface` 财务报告和审定财务报表 `--color-surface-raised` 学来. `tests/contrast.spec.ts` 门文本, 变音的文字,主,主盘旋 和状态颜色对在光和 两个黑暗的街区。 这个 `dpb-fade-in` 财务报告和审定财务报表 `dpb-blink` 帮助类已禁用 下级 `prefers-reduced-motion: reduce`。 。 。 .

在图层后装入特定应用的 CSS , 只重新定义您需要的值 :

```css
:root {
  --color-primary: #145da0;
  --header-height: 4.5rem;
}
```

### 苹果壳钩

用于页面框架和 浮动提醒容器 :

```vue
<div class="page-layout">
  <AppNavigation :links="links" />
  <main>
    <NuxtPage />
    <AlertMessages class="page-alert-messages" />
  </main>
</div>
```

`#page-layout` 财务报告和审定财务报表 `#page-alert-messages` 继续作为遗产别名提供支持 对于现有的消费者来说,所以当前加价继续起作用. 优先上课 新的标记,以避免在多个布局上架时发生重复的ID相撞.

## 覆盖一个组件

Nuxt给予应用本地组件相对于层组件的优先级. 添加组件 在你的应用软件下同名 `components/` 例如,目录 `components/Loading.vue`,它取代了层的 `<Loading />` 无 伪造或修改此软件包。 App 特定导航项目通过 通过 `links` 道具而不是嵌入层.

深层的进口也可用于工具和测试,但不在 Nuxt 应用程序 :

```ts
import Loading from "@devopsplaybook.io/common-web/components/Loading.vue";
```

## 兼容性和释放政策

此发行支持 Nuxt `^4.0.0` ưμ㼯A `^3.5.0`; Nuxt 提供 Vue,所以 Nuxt 4 应用程序已经满足了此对等点 。 皮尼亚 `^2.0.0 || ^3.0.0 || ^4.0.0` 是可选对等点:只有 `stores/AuthenticationStore` 需要,所以不使用 存储无需安装。 Pinia 4 仅限无害环境管理,需要消耗 应用程序 `@vue/devtools-api` 相对依赖。 数值 3 应用程序(包括心电图)不支持.

对于 Nuxt 大型升级, 更新对等依赖, 建造操场 测试所有从包装中输出的组件/组件 柏油丸,并验证刮伤消费者在放出前可以延长地层. 保留释放语义:用于修正的补丁,用于向后兼容的次要 特性,以及用于打破 API 或框架更改的主要特性。 合并工作流程 当软件包版本尚未发布时, 发布新的 npm 公共版本 已发布; 凸起 `package.json` 手动在发布PR上.

`PR Check` 财务报告和审定财务报表 `Main Build` 运行共享 npm 的寄存器本地版本 工作流程,使审计门只能覆盖生产依赖; 报告关于发展工具链的咨询,但不会失败。 见 [捐款额](https://npmcn.com/package/%40devopsplaybook.io/common-web/CONTRIBUTING.md#dependency-audit-policy) 为政策和 被接受的只有发展的建议。 本地工作只是权宜之计,直到 共享 `common-utils` npm工作流程采用同门.

### 包装、类型和副作用

包件载运生 Vue 和 TypeScript 源头没有构建步骤,所以有 故意拒绝 `types` 或者说 `exports.types` 条目: 类型信息来自 页:1 `.ts`编号 :`.vue` 和深度进口的决心 `exports` nuxt 模块分辨率下的映射. `sideEffects` 白名单 CSS 和 `.vue` 文件这样组件样式和符号样式表都永远不会 树被震动,而无副作用 `.ts` 模块可以是. `npm run build` 当包装的柏油丸中缺少任何公共文件时失败, 而包装 归档是什么 `npm test` 运行对面.

## 发展

```sh
npm ci
npm run lint
npm run typecheck
npm test
npm run build
npm run dev
```

`npm run typecheck` 运行 `nuxi typecheck` (单位:千美元)`vue-tsc --noEmit`在地层上, 在游戏场和测试中失败. `npm test` 收拾东西 库并运行组件、服务和SSR测试. `npm run build` 验证其内容并建造游乐场. 见 [捐款额](https://npmcn.com/package/%40devopsplaybook.io/common-web/CONTRIBUTING.md) 详细情况.

## 常见问题

### @devopsplaybook\.io/common-web 是什么？

DevOpsPlaybook 网络应用程序共享 Nuxt 层

### 如何安装 @devopsplaybook\.io/common-web？

在项目目录运行 npm install @devopsplaybook\.io/common-web，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：vue（^3\.5\.0）、nuxt（^4\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @devopsplaybook\.io/common-web 支持 TypeScript 吗？

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

### @devopsplaybook\.io/common-web 支持 ESM 还是 CommonJS？

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

### @devopsplaybook\.io/common-web 需要什么版本的 Node\.js？

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

### @devopsplaybook\.io/common-web 可以商用吗？

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

### @devopsplaybook\.io/common-web 的下载量有多少？

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

### @devopsplaybook\.io/common-web 还在维护吗？

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

