N.11 · 开发 · 2026.07.24 · 2026.10.24 更新 · 约 5 分钟

一个 Prompt 插件被 Code Review打回之后

测试、类型检查和构建都已经通过,代码审查却给了 REQUEST CHANGES。接下来的一天,我才真正处理完这个浏览器插件的发布边角。

PromptCrate 第一次被认真 review 的时候,结果有点刺眼:REQUEST CHANGES。更尴尬的是,那个版本并非完全跑不起来。pnpm test 通过,pnpm check 通过,pnpm build 也通过。换成我刚开始写个人项目时的心态,可能已经觉得“差不多能发了”。

真正的问题藏在这些绿色结果旁边。pnpm lint 扫到了打包后解开的 release 目录,一口气报了 778 个错误。它们大多来自构建产物,可这件事本身已经说明发布流程不干净:一个准备交给别人侧载试用的插件,连本地质量门禁都需要开发者记住“别扫那个目录”,这很脆。

另一个拦路点是 dev 依赖审计。Vite、Vitest、esbuild 相关工具链有高危和严重告警。它们不会进入扩展运行时,可 README 里会鼓励开发者跑本地 dev server,CI 和测试也依赖这套链路。浏览器插件本来就运行在别人的网页上,我不想在发布前留下这种“只影响开发环境”的含糊账。

文字显示出来,不代表网页接住了

PromptCrate 的卖点很简单:按快捷键,把本地 prompt 模板插进网页输入框。原生 textarea 很容易,普通 input 也还好,麻烦来自真实 Web App。很多站点用 React controlled input、contenteditable 富文本、iframe、Shadow DOM。直接改 value 或插一个 text node,看起来能显示文字,提交时却可能被框架状态吞掉。

Review 里那句风险提醒很准:用户看到文字进去了,不代表网页真的接住了。

后面我把修复拆成几件小事。release 解包目录被明确忽略,lint 不再被构建产物污染。工具链升级后重新跑 audit,已知漏洞清零。文本输入改成 beforeinput、原生 value setter 和 input 事件组合;contenteditable 优先走 beforeinput 和 execCommand("insertText") fallback。iframe 场景也补了 frame-aware 的探测和消息路由,菜单会发给真正聚焦输入框所在的 frame。

顺手清掉几笔旧账

数据这边也清了一轮。导入 JSON 会拒绝重复 template id;storage 初始化和写入都经过 normalize、业务校验和重复 id 检查;非法历史数据会备份到 promptCrate.invalidTemplatesBackup 后再重置。content script 里那套重复的 template/storage 逻辑被删掉,改为复用 shared 模块,避免 options 和页面菜单以后各走各的规则。

最后补的是可访问性。菜单 dialog 加上 aria-modal、焦点陷阱和关闭后的焦点返回;搜索框补齐 combobox/listbox 语义;关闭按钮也从一个含糊的 x 变成有明确名称的按钮。这些改动不抢眼,可插件依赖键盘快捷键打开,键盘和读屏体验就不能靠运气。

第二天的门禁

修完后再跑一遍,结果才配得上“可侧载候选”:

  • 9 个测试文件、33 个测试通过;
  • pnpm lint、pnpm check、pnpm build 全部通过;
  • pnpm audit --audit-level moderate 没有已知漏洞;
  • pnpm package:zip 重新生成了侧载包。

它依然还没到 Chrome Web Store 发布状态,我更愿意把它叫作 side-load candidate。

这次 review 给我留下了一个很具体的提醒:小插件的工程质量,经常坏在“看起来只是边角”的地方。release 目录、dev audit、iframe、焦点返回、重复 id,这些都不像主功能,却会决定别人第一次安装时会不会信任它。PromptCrate 被打回那天不算舒服,但那份 REQUEST CHANGES 比一次草率通过更有价值。

后来

之后 PromptCrate 推进到了发布准备阶段:权限与隐私说明、release checklist、截图、图标和试用 zip 都齐了,仍然通过开发者模式侧载试用。10 月又补了一次修复,拒绝无效的、或者无法确认真的生效的模板插入——还是那句话,文字显示出来,不代表网页接住了。它还没有提交到扩展商店。