npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

swc-plugindev-canyon

v0.1.0

Published

[Canyon](https://github.com/canyon-project/canyon) 生态下的 **SWC 覆盖率后处理插件**。它在 `swc-plugin-coverage-instrument` 完成代码插桩之后运行,对 AST 中的 `coverageData` 对象做精简、注入构建元数据,并可在 CI 环境中写出初始覆盖率文件。

Readme

swc-plugindev-canyon

Canyon 生态下的 SWC 覆盖率后处理插件。它在 swc-plugin-coverage-instrument 完成代码插桩之后运行,对 AST 中的 coverageData 对象做精简、注入构建元数据,并可在 CI 环境中写出初始覆盖率文件。

本仓库是 Canyon SWC 插件的开发/验证版本,产物为 WebAssembly(.wasm),通过 SWC 的 experimental plugins 机制加载。

功能概览

| 能力 | 说明 | |------|------| | 精简运行时 bundle | 默认移除 statementMapfnMapbranchMapinputSourceMaphash_coverageSchema 等大体积字段 | | 注入 buildHash | 根据仓库元数据生成唯一构建标识,用于将运行时 hit 数据与对应构建版本关联 | | 文件过滤 | 支持 include / exclude glob、extensions 扩展名白名单 | | CI 输出 | 开启 ci 后,将带完整 map 与元数据的初始覆盖率写入 .canyon_output/ | | 内容哈希 | 为源码及 statement 片段计算 contentHash,便于后端做源码版本校验 |

工作原理

Canyon 采用 「Hit 与 Map 分离」 策略:构建阶段保留完整 coverage map(供服务端存储),运行时 bundle 只携带精简后的 hit 计数结构,以减小体积。

源码
  │
  ▼
swc-plugin-coverage-instrument   ← 第一步:插桩,生成 coverageData(含 _coverageSchema)
  │
  ▼
swc-plugindev-canyon               ← 第二步:精简 / 注入 buildHash / 可选写 CI 文件
  │
  ▼
最终产物(dist / 部署包)

CI 模式 下,插件会在变异 coverageData 之前,先将包含完整 map 的覆盖率快照序列化为 JSON,写入:

.canyon_output/coverage-final-init-{随机后缀}.json

该文件可由 Canyon CLI 上传至服务端,与运行时收集的 hit 数据合并。

环境要求

  • Rust(含 wasm32-wasip1 target)
  • Node.js ≥ 18(用于本地测试脚本)
  • @swc/core ≥ 1.x
  • swc-plugin-coverage-instrument(插桩前置插件)

安装 Rust WASM 目标

rustup target add wasm32-wasip1

构建

# 编译 release 版 WASM
cargo build-wasip1 --release

# 产物路径
# target/wasm32-wasip1/release/swc_plugindev_canyon.wasm

也可通过 npm 脚本触发构建:

npm run prepack

在 SWC 中使用

插件必须排在 swc-plugin-coverage-instrument 之后,对已经插桩的代码做二次 transform。

import swc from "@swc/core";

const coverageWasm =
  "node_modules/swc-plugin-coverage-instrument/target/wasm32-wasip1/release/swc_plugin_coverage.wasm";

const canyonWasm =
  "target/wasm32-wasip1/release/swc_plugindev_canyon.wasm";

const pluginConfig = {
  repoId: "9050",
  sha: "abc123def456",
  provider: "gitlab",
  buildTarget: "production",
  ci: true,
  keepMap: false,
  include: ["src/**/*.js"],
  exclude: ["**/*.test.js"],
  instrumentCwd: "/path/to/project",
};

// 第一步:插桩
const { code: instrumented } = await swc.transform(source, {
  filename: "/path/to/project/src/foo.js",
  jsc: {
    experimental: {
      plugins: [[coverageWasm, {}]],
    },
  },
});

// 第二步:Canyon 后处理
const { code } = await swc.transform(instrumented, {
  filename: "/path/to/project/src/foo.js",
  jsc: {
    experimental: {
      plugins: [[canyonWasm, pluginConfig]],
    },
  },
});

.swcrc 中配置时,需保证两个插件按上述顺序出现在 jsc.experimental.plugins 数组中,且 Canyon 插件位于 coverage-instrument 之后。

配置项

所有配置通过 SWC plugin 的第二个参数传入,字段名为 camelCase JSON:

| 字段 | 类型 | 默认值 | 说明 | |------|------|--------|------| | repoId | string | "" | 仓库 ID(如 GitLab CI_PROJECT_ID) | | sha | string | "" | Git commit SHA | | provider | string | "" | 代码托管平台,如 gitlabgithub | | buildTarget | string | "" | 构建目标标识(如 productionstaging) | | ci | boolean | false | 为 true 时写出 .canyon_output/coverage-final-init-*.json | | instrumentCwd | string | "." | 插桩根目录,用于路径归一化及 buildHash 计算 | | include | string[] | [] | 需要处理的文件 glob;为空表示不过滤 include | | exclude | string[] | [] | 排除的文件 glob | | extensions | string[] | 见下方 | 允许处理的文件扩展名 | | keepMap | boolean | false | 为 true 时保留 statement/fn/branch map,不精简 bundle |

默认 extensions

.js  .cjs  .mjs  .ts  .tsx  .jsx  .vue

buildHash 生成规则

buildHash 是对以下字段按 字典序 序列化后做 SHA-1 的结果:

  • provider
  • repoID
  • sha
  • buildTarget
  • instrumentCwd

相同配置在不同构建中会得到相同的 buildHash,用于 Canyon 服务端关联覆盖率 hit 与源码 map。

keepMap 与 ci 的组合

| keepMap | ci | 运行时 bundle | CI 产物 | |-----------|------|---------------|---------| | false | false | 精简,仅含 hit 计数 + buildHash | 无 | | false | true | 精简 | 写出完整 map 至 .canyon_output/ | | true | * | 保留完整 map | 按 ci 决定是否写文件 |

生产环境通常使用 keepMap: false + ci: true,在 bundle 体积与服务端 map 完整性之间取得平衡。

转换效果示例

插桩后(coverage-instrument 输出)coverageData 包含完整 map:

var coverageData = {
  path: "/project/features/add.js",
  statementMap: { /* ... */ },
  fnMap: { /* ... */ },
  branchMap: { /* ... */ },
  _coverageSchema: "1a...",
  s: { "0": 0, "1": 0 },
  f: { "0": 0 },
  b: { "0": [0, 0] },
};

经本插件处理后keepMap: false):

var coverageData = {
  all: false,
  path: "/project/features/add.js",
  s: { "0": 0, "1": 0, "2": 0, "3": 0 },
  f: { "0": 0 },
  b: { "0": [0, 0] },
  buildHash: "a7b7d1390cdbc0b473cf76bb6a2eaae88a07e718",
};

未被 include 匹配的文件(如 features/jian.jsinclude 仅含 features/add.js 时)将跳过 Canyon 处理,保留 coverage-instrument 的原始输出。

本地开发与测试

# 安装依赖
npm install

# 构建 WASM 并运行端到端测试
npm run test-swc-plugin

测试脚本 scripts/test-swc-plugin.mjs 会:

  1. features/ 下所有 .js 文件先跑 coverage-instrument,再跑本插件
  2. 将结果写入 dist/
  3. 校验 features/add.jsbuildHash 且已移除 statementMap
  4. 校验未 include 的 features/jian.js 未被 Canyon 处理
  5. ci: true 时检查 .canyon_output/ 是否生成文件

运行 Rust 单元测试:

cargo test

项目结构

swc-plugindev-canyon/
├── src/
│   ├── lib.rs          # SWC plugin 入口(#[plugin_transform])
│   ├── visitor.rs      # AST 访问器:识别 coverageData、触发 CI 输出
│   ├── coverage.rs     # coverageData 识别、精简、序列化、文件 I/O
│   ├── config.rs       # 插件配置解析与文件过滤逻辑
│   └── hash.rs         # buildHash / contentHash 计算
├── features/           # 测试用示例源码
├── scripts/
│   └── test-swc-plugin.mjs
├── .cargo/config.toml  # cargo build-wasip1 别名
├── Cargo.toml
└── package.json

与 Canyon 生态的关系

本插件对应 Canyon monorepo 中的 SWC Plugin 能力,与以下组件配合使用:

更多概念说明见 Canyon 文档中的 Separate Hit and Map 设计。

许可证

ISC