Skip to content

ci: skip redundant CJS api-extractor lint checks in ci:build #26592

@frankmueller-msft

Description

@frankmueller-msft

Summary

The ci:build step runs 224 redundant api-extractor invocations validating CJS entry points that are byte-for-byte identical to their ESM counterparts. Removing them would save ~22 minutes of CPU time (~1 minute wall-clock on the 8-core CI agent).

Analysis

Current state

From build #381019 CI logs, npm run ci:build completes 1,510 leaf tasks in 8m 15s. The api-extractor and flub generate entrypoints invocations break down as:

Category Count CPU Time
api-extractor lint (ESM configs) 167 16m 26s
api-extractor lint (CJS configs) 159 15m 60s
api-extractor lint (bundle) 86 11m 20s
api-extractor run (doc model) 92 11m 11s
api-extractor run (reports) 94 9m 49s
flub generate entrypoints (ESM/lib) 68 6m 48s
flub generate entrypoints (CJS/dist) 65 6m 21s
Total CJS-related 224 22m 21s

At 22.7x effective concurrency, this is ~1 minute of the 8m 15s wall-clock time (12%).

Why the CJS checks are redundant

Both api-extractor:commonjs and api-extractor:esnext run flub generate entrypoints — one targeting --outDir ./dist (CJS), the other --outDir ./lib (ESM). The generated entry point files (public.d.ts, legacy.d.ts, index.d.ts) are byte-for-byte identical across all packages:

  • public.d.ts: 41/41 identical
  • legacy.d.ts: 35/35 identical
  • index.d.ts: 50/50 identical (where both exist)

The check:exports:cjs:* lint scripts then run api-extractor against the CJS entry points (dist/public.d.ts) using -lint-public.cjs.json configs. These configs extend the same api-extractor-lint.entrypoint.json base and generate no output — they only validate the entry point is well-formed. Since the entry point files are identical to the ESM versions already validated by check:exports:esm:*, the CJS validation is tautological.

No reports, doc models, or documentation depend on CJS api-extractor output — all use ESM paths (api-extractor-model.esm.json, api-extractor-report-base.esm.json).

Dependency chain

ci:build
 └─ lint
     └─ check:exports              ← depends on "api"
         └─ api                    ← depends on BOTH api-extractor:commonjs AND api-extractor:esnext
             ├─ api-extractor:commonjs  ← "flub generate entrypoints --outDir ./dist" (REDUNDANT)
             └─ api-extractor:esnext    ← "flub generate entrypoints --outDir ./lib"

Each package's check:exports runs concurrently "npm:check:exports:*", picking up both check:exports:cjs:* and check:exports:esm:* scripts.

Proposed changes

Files to modify

  1. fluidBuild.config.cjs — Remove api-extractor:commonjs from api task and build:test dependencies
  2. 86 package.json files — Remove check:exports:cjs:* and api-extractor:commonjs scripts
  3. ~160 api-extractor-lint-*.cjs.json files — Delete (no longer referenced)

Config changes

// fluidBuild.config.cjs — BEFORE
"api": {
    dependsOn: ["api-extractor:commonjs", "api-extractor:esnext"],
    script: false,
},
"build:test": ["typetests:gen", "tsc", "api-extractor:commonjs", "api-extractor:esnext"],
"build:test:cjs": ["typetests:gen", "tsc", "api-extractor:commonjs"],

// fluidBuild.config.cjs — AFTER
"api": {
    dependsOn: ["api-extractor:esnext"],
    script: false,
},
"build:test": ["typetests:gen", "tsc", "api-extractor:esnext"],
"build:test:cjs": ["typetests:gen", "tsc"],

Scripted cleanup

The package.json and config file changes could be scripted:

# Remove check:exports:cjs:* scripts from all package.json files
# Remove api-extractor:commonjs scripts from all package.json files
# Delete all api-extractor-lint-*.cjs.json config files

Expected impact

  • 224 fewer task invocations per CI build (1,510 → 1,286)
  • ~22 minutes less CPU time (187m → 165m)
  • ~1 minute faster wall-clock (8m 15s → ~7m 15s for ci:build)
  • ~250 fewer files in the repo (config files + script entries)

Risks

  • If flub generate entrypoints ever produces different output for CJS vs ESM, the divergence would go undetected. This seems unlikely since both use the same TypeScript source and the tool has no CJS-specific logic.
  • Local developer builds would no longer validate CJS entry points. Developers using npm run build would still get ESM validation.

Data source

All timing data from build #381019 (PR #26586 on ci/combined-pipeline-parallelization), extracted via ADO timeline API.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions