← 精品代码功能 · 可复用实现库

精品功能 14:原子发布构建器与浏览器验收

核心实现

原子发布(build.mjs 第 79-110 行):

const stage = path.join(..., `.${path.basename(output)}.staging-${randomUUID()}`);
...
await mkdir(stage);
for (const file of [...staticFiles, ...images]) { /* 复制到 staging */ }
await writeFile(path.join(stage, "index.html"), html);
// ...写 projects.js / hanzi-data.js / portfolio.v1.json,算 sha256 写 manifest
if (await exists(output)) {
  backup = path.join(..., `.${path.basename(output)}.previous-${randomUUID()}`);
  await rename(output, backup);            // 旧版先改名为备份
}
try { await rename(stage, output); }       // staging 原子上位
catch (error) { if (backup) await rename(backup, output); throw error; }  // 失败回滚

构建锁 + 边界校验(第 22-28、75-78 行):

export async function validateOutput(source, output) {
  // outputs 必须在工作区内;输出必须是 outputs 内的独立子目录;
  // 输出不能与源码重叠;输出路径不能含符号链接/目录联接
}
const lockPath = path.join(..., `.${path.basename(output)}.build.lock`);
try { lock = await open(lockPath, "wx"); }          // wx = 排他创建
catch (error) { if (error.code === "EEXIST") throw new Error("构建锁已存在……"); }

跨项目契约测试(contracts.test.mjs 第 90-106 行):验证 core.adaptCourseIndex
能正确读取 course-publisher 生成的 index.json——兼容旧格式、拒绝未知版本、
"没生成 HTML 就不伪造入口"。

真浏览器验收(verify.mjs):校验 manifest 的 sha256 → 起本地 HTTP 并注入不同数据夹具
→ spawn headless Edge(--remote-debugging-port=0)→ 用内置 WebSocket 走 CDP 执行断言,
最后断言未捕获异常数为 0;覆盖 file://、缓存自愈、响应式、XSS 等约 40 个检查点。

设计亮点

  1. staging + 原子 rename + 备份回滚:和数据库事务同思想——要么全成功,要么保持原样
  2. 构建锁:open(..., "wx") 防并发构建
  3. 边界校验:realpath + inside() 防止覆盖源码/输出到系统目录
  4. 不替换"未认领"目录:没有本项目 manifest 的目录一律拒绝——宁可失败,不可误伤
  5. 契约测试:保护"数据结构 + 跨项目接口",协作安全网
  6. 零依赖浏览器验收:不用 Puppeteer,直接用 CDP(理解原理最透彻)
  7. sha256 清单:产物内容可校验,verify.mjs 先核对再验收

可复用性评估

开源化建议

对照开源

相关课程

第 19 课(零依赖构建与交付验收)