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

精品功能 04:零依赖 ZIP 写入器 + sha256 清单打包

再用"文件清单 + sha256"保证打包内容可校验。

而且不想为了打个 zip 引入几十 MB 的依赖。

核心实现

ZIP 的本质是"本地文件头 + 压缩数据 + 中央目录 + 结束记录",
ZipWriter 把这四部分按规范拼出来(第 17-60 行,节选):

export class ZipWriter {
  constructor(entries) { ... }
  async build() {
    const local = []; const central = []; let offset = 0;
    for (const entry of this.entries) {
      const name = Buffer.from(entry.name, "utf8");
      const compressed = deflateRawSync(entry.content);   // Node 内置压缩
      const sum = checksum(entry.content);                // CRC32 校验和
      const header = Buffer.alloc(30);
      header.writeUInt32LE(0x04034b50, 0);                // 本地文件头签名
      header.writeUInt16LE(0x0800, 6);                    // UTF-8 文件名
      header.writeUInt16LE(8, 8);                         // 压缩方式 = deflate
      header.writeUInt32LE(sum, 14);
      ...
      const record = Buffer.concat([header, name, compressed]);
      local.push(record);
      // ...再写中央目录项(含 offset 指回本地头)
      offset += record.length;
    }
    // ...最后写"中央目录结束记录"
  }
}

CRC32 兼容性处理(第 1-15 行)——很实用的细节:

// Node 的 zlib.crc32 在较新版本才可用,旧版用上面的表兜底,保证行为一致。
function checksum(buffer) {
  if (typeof crc32 === "function") return crc32(buffer) >>> 0;
  let value = 0xffffffff;
  for (const byte of buffer) value = CRC_TABLE[(value ^ byte) & 0xff] ^ (value >>> 8);
  return (value ^ 0xffffffff) >>> 0;
}

配套的 package.mjs:按 build-manifest.json 列的清单收集文件、
逐个核对 sha256、再交给 ZipWriter 打包。

设计亮点

  1. 吃透二进制格式:ZIP 头字段、偏移、CRC32、中央目录——写一遍就再也不会怕二进制协议
  2. 零依赖:只用 node:zlib,交付工具不该拖累项目依赖
  3. 版本兼容兜底:crc32 有就用、没有就自己算,保证"行为一致"
  4. 清单 + 哈希:打包不是"把文件塞一起",而是"按已验证的清单打包"
  5. 注释声明边界:文件头就写了"仅支持 deflate 与小于 4GB 的文件,够交付包用"

可复用性评估

开源化建议

对照开源

相关课程

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