apex-dev-tools / apex-dev-tools/benchmarker

Migrate package to ESM (dual build), following apex-parser

未关闭
#95 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
主要语言
TypeScript
星标
5
派生
10
平均合并
3 小时 23 分钟
30 天内合并 PR
3

描述

## Problem

`benchmarker` is published as CommonJS, and a growing part of its dependency tree has gone ESM-only. This is no longer a per-dependency annoyance — it is now blocking security and version updates outright.

Currently blocked Dependabot PRs, both failing for the same underlying reason:

- **#89 — chai stack.** The locked versions all declare `"type": "module"`: chai 6.2.2, chai-as-promised 8.0.2, sinon-chai 4.0.1. `npm run build` fails with widespread **TS1479** — CommonJS test files cannot statically import ESM-only packages. Compilation fails before any test runs.
- **#91 — puppeteer 22 → 25.** v23 and v24 are actually clean against this codebase. **v25** is ESM-only, and additionally raises Puppeteer's minimum Node to 22 while this package declares `"node": ">20.0.0"`. There is also an API rename to absorb: `PuppeteerNodeLaunchOptions` (imported by `src/shared/env.ts`) is now `LaunchOptions`.

Until this is resolved, both PRs are unmergeable and the repo stays pinned on older majors.

## Current state

```
package.json no "type" field → CommonJS
main dist/src/index.js
types dist/types/src/index.d.ts
exports "." and "./database", single "default" condition, no import/require split
engines node >20.0.0
tsconfig module: node16, target: es2020, outDir: ./dist
build tsc only (no bundler)
```

Worth noting the setup is already *partly* hybrid and inconsistent:

- `npm test` runs with `NODE_OPTIONS='--loader ts-node/esm --experimental-specifier-resolution=node'`
- `.mocharc.yml` requires `ts-node/register` (the CommonJS loader)
- `npm run test:system` uses neither

So the test path already has one foot in ESM while the package contract is CommonJS.

## Prior art: apex-parser

[`apex-parser`](https://github.com/apex-dev-tools/apex-parser) has already been through this and is the reference implementation. It went **dual-build rather than ESM-only**, so existing CommonJS consumers kept working.

Its `npm/package.json` now looks like:

```jsonc
{
"type": "module",
"main": "./dist/cjs/index.cjs",
"module": "./dist/esm/index.js",
"types": "./dist/types/index.d.ts",
"exports": {
".": {
"browser": { "types": "...", "default": "./dist/browser/apex-parser.mjs" },
"import": { "types": "./dist/types/index.d.ts", "default": "./dist/esm/index.js" },
"require": { "types": "./dist/types/index.d.cts", "default": "./dist/cjs/index.cjs" }
}
}
}
```

Dual output is produced by Rollup (`npm/rollup.config.js`) emitting both `format: "es"` → `dist/esm/*.js` and `format: "cjs"` → `dist/cjs/*.cjs` with `preserveModules: true`, plus separate `.d.ts` / `.d.cts` type outputs per condition.

Useful commits to follow:

- `ed23f8b` — update inner npm package for ESM and exports
- `802347a` — update src to ES modules, fix strict type errors (PR #79)
- `f375e4f` — add CJS and browser builds via Rollup
- `06949ca` — use dynamic `import()` in the check script for ESM compatibility (PR #106)

That last one is the pattern for reaching an ESM-only dependency from a CommonJS context, which is directly relevant to the Puppeteer situation.

## Scope

- Add `"type": "module"`; decide dual-build vs ESM-only (dual recommended, per apex-parser)
- Introduce a bundler for dual output, or an equivalent two-pass `tsc` setup
- Rework `exports` with proper `import` / `require` conditions and matching `.d.ts` / `.d.cts`
- Review `module` / `moduleResolution` in `tsconfig.json`
- Audit imports for explicit file extensions and CommonJS assumptions (`__dirname`, `require`, `module.exports`)
- Reconcile the test setup: `.mocharc.yml` `ts-node/register` vs the `ts-node/esm` loader in `npm test`, plus nyc
- Decide whether to raise `engines.node` to `>=22` (required if Puppeteer 25 becomes a production dependency)
- Check downstream consumers — this is a **package-level breaking change** to the published contract

## Related

- #89 — recommend closing and pinning the CommonJS stack (chai 4.x, chai-as-promised 7.x, sinon-chai 3.x) until this lands
- #91 — a separate PR will take Puppeteer to **v24**, which is the highest version compatible with CommonJS. v25 is deferred to this work.

贡献指南

这个仓库没有索引到贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。