`@workflow/builders` sends every esbuild-traversed JavaScript module through SWC during Nitro builds
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 2.4k
- Forks
- 365
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 169
Description
TL;DR
With @workflow/nitro@5.0.0-beta.26, the builder's esbuild load path calls applySwcTransform() for every JS/TS module. This includes transitive deps that have no 'use workflow' or 'use step' directive.
Especially when using the AI SDK WorkflowAgent: its dependency graph sends 391 unique JavaScript modules through the transform; 383 contain no Workflow directive. For us, this translates to a 30s rebuild time for simple workflows.
Minimal Reproduction
Repository: https://github.com/ecumene/slow-workflows-swc-build
corepack enable
pnpm install --frozen-lockfile
pnpm profile:published
pnpm profile
pnpm benchmark
pnpm compare
Profile result
| Build | Transform calls | Unique transitive JS | Directive-free transitive JS | Safe fast-path candidates |
|---|---|---|---|---|
| WorkflowAgent + fallback | 1927 | 1892 | 1884 | 1875 |
| WorkflowAgent (real graph only) | 426 | 391 | 383 | 374 |
| Control | 1 | 1 | 0 | 0 |
Benchmark result
Five runs on macOS arm64 / Node 22.23.1:
| Measurement | Published | PR fast path | Speedup |
|---|---|---|---|
| Agent cold | 3888.8 ms | 2818.4 ms | 1.38× |
| Agent rebuild after editing its workflow | 2899.2 ms | 1854.6 ms | 1.56× |
| Control cold | 1037.9 ms | 1066.2 ms | 0.97× |
The benchmark generates a chain of 1,500 ordinary JavaScript modules so the timing difference is easy to reproduce. The generated files are ignored and contain no Workflow directives.
Suspected cause
createSwcPlugin() runs applySwcTransform() on every JavaScript and TypeScript module loaded by esbuild, even when a JavaScript file has no Workflow directive or serialization hook. The discovery pass uses the same transform.
Local comparison
The local patch skips SWC for JavaScript files without Workflow directives or serialization hooks. Workflow, step, serialization, and TypeScript files are still transformed.
| Measurement | Published builder | Local fast path | Speedup |
|---|---|---|---|
| Agent cold median | 3888.8 ms | 2818.4 ms | 1.38× |
| Agent rebuild median | 2899.2 ms | 1854.6 ms | 1.56× |
The workflow and step remain in the manifest, edits still rebuild, and runtime output is unchanged.
Expected behavior
JavaScript without Workflow directives or serialization hooks should skip the Workflow SWC transform.
Environment
- Node 22.23.1
- pnpm 10.34.5
- nitropack 2.13.1
- workflow 5.0.0-beta.26
- @workflow/nitro 5.0.0-beta.26
- @ai-sdk/workflow 1.0.34
- @ai-sdk/openai 4.0.17
- ai 7.0.34
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at createSwcPlugin() and applySwcTransform(), then reproduce the issue with the linked benchmark commands. Trace the esbuild load and discovery passes for directive-free JavaScript modules; done means those modules skip the Workflow SWC transform while workflow, step, serialization, and TypeScript files still transform and rebuild correctly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- build-system, performance
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100