4.4 KiB
L7 · 性能与检验(plugin:check)
前置:L0–L6。约 20 分钟。 目标:插件百花齐放,但绝不卡宿主、绝不风格跑偏;发布前有机器关卡把关。
性能铁律
1. 主进程不阻塞(检验器:error)
main.mjs 运行在宿主主进程。任何同步 IO——fs 的 *Sync、execSync、
spawnSync——都会卡住整个应用的事件循环(聊天流、其他插件全部冻结)。
一律用 node:fs/promises 与异步子进程:
// ❌ const text = fs.readFileSync(path, 'utf8')
// ✅
import { readFile } from 'node:fs/promises'
const text = await readFile(path, 'utf8')
2. 激活限时 10 秒(宿主强制)
插件工厂若返回 Promise,宿主限时 10s;超时或 reject 即把插件标记为失败 (插件管理页可见红字),绝不无限等待拖垮 runtime 重建。因此:
- 激活路径只做「注册」级别的工作,重活(预取数据、预热连接)放到工具首次调用
- 自己
catch并api.log.error——被宿主兜住意味着插件没跑起来
3. renderer 装载限时 8 秒(宿主强制)
读源与 import 各限时 8s,超时/失败由宿主呈现统一失败态(重试按钮); 组件渲染期崩溃由 PluginErrorBoundary 兜底。插件只需管好组件内部的异步。
4. 自己的异步自己兜(sdk 提供 withTimeout / withRetry)
先于宿主超时并自行恢复,而不是等宿主判死:
import { withTimeout, withRetry, TimeoutError } from '@aso/plugin-sdk'
// 网络请求:3s 超时,失败退避重试 2 次(300ms → 600ms)
const data = await withRetry(() => callApi(), { retries: 2, delayMs: 300, timeoutMs: 3000 })
// 单次限时
const cfg = await withTimeout(loadConfig(), 2000, '加载配置')
try {
await risky()
} catch (err) {
if (err instanceof TimeoutError) { /* 降级路径 */ }
throw err
}
注意:withTimeout 只是竞速,底层操作不会被取消——有 AbortController 的
调用方请把 signal 接到底层,再用它兜底计时。
5. 渲染不卡顿
长列表分页/虚拟化,不要一次渲染数万节点;重计算放进工具(Agent 侧)或
setTimeout(fn, 0) 分帧,不占渲染主线程。
三态呈现(检验器:warn)
任何异步 UI 必须是四态之一:LoadingState / ErrorState / EmptyState / 数据。
alert/confirm/prompt 是阻塞式同步对话框,禁止(用 Button + 状态组件替代)。
详见 L6。
样式一致性(检验器:error)
- 只用公共组件库 + DESIGN.md token;硬编码 hex 色值是 error
(
#fff/#ffffff白字除外) - renderer.mjs 必须经宿主 shim 使用单实例 React(
__ASO_PLUGIN_HOST__)—— 自带 React 副本 = hooks 全部失效
日志(检验器:error)
main.mjs 禁 console.*,统一 api.log.*——Agent 自诊断闭环见 L5。
检验器:pnpm plugin:check <插件目录>
发布前必跑;Agent 自迭代时,通过检验器是完成定义(DoD)的一部分。
| 级别 | 检查项 |
|---|---|
| error | manifest 缺失/不可解析;id/name/version(semver) 缺失;minContract 高于宿主契约;entry 指向的文件不存在;renderer.mjs > 8MB / main.mjs > 2MB;main.mjs 同步 IO;main.mjs console.*;renderer.mjs 未引用 __ASO_PLUGIN_HOST__;任何源码硬编码 hex 色值 |
| warn | 缺 minContract;renderer.mjs > 300KB(疑似打包自带 React);注册 view/panel 但未用三态组件;alert/confirm/prompt;entry.renderer 产物缺失但有 src/renderer.tsx(未构建) |
宿主契约版本从 plugin-host.ts 源码提取(单一事实源),检验器与宿主永不会各执一词。
一张自查表
pnpm plugin:check <目录>0 error- main.mjs 无同步 IO,激活 10s 内完成
- 一切异步有超时与重试,catch 后
api.log+ErrorState
一张自查表
pnpm plugin:check <目录>0 error- main.mjs 无同步 IO,激活 10s 内完成
- 一切异步有超时与重试,catch 后
api.log+ErrorState - 长列表不整批渲染
- 深浅色各看一眼(token 正确时自动成立)