Skip to content

Conversation

@medz
Copy link
Contributor

@medz medz commented Feb 10, 2026

🔗 Linked issue

❓ Type of change

  • 📖 Documentation (updates to the documentation, readme, or JSdoc annotations)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

This PR adds builderless mode support so Nitro can keep bundling runtime/virtual modules while externalizing user code for downstream bundlers (for example Wrangler).

This targets the Cloudflare Worker compatibility scenario discussed in #4010.
Default behavior is unchanged (builderless: false).

Validation:

  • pnpm format
  • pnpm typecheck
  • pnpm vitest run test/minimal/minimal.test.ts
  • pnpm vitest run test/minimal/minimal.test.ts -t builderless
  • Repro repo: medz/nitro-issue-4010-pg-cloudflare-repro (validated with Nitro linked from this PR branch)
  • NITRO_BUILDER=rollup pnpm exec nitro build
  • NITRO_BUILDER=vite pnpm exec nitro build
  • pnpm exec wrangler deploy --dry-run --config .output/server/wrangler.json
  • pnpm exec wrangler dev --config .output/server/wrangler.json and request / returns 200

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@medz medz requested a review from pi0 as a code owner February 10, 2026 06:09
@vercel
Copy link

vercel bot commented Feb 10, 2026

@medz is attempting to deploy a commit to the Nitro Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Feb 10, 2026

📝 Walkthrough

Walkthrough

Adds a "builderless" option and implements support so Nitro can bundle its runtime while leaving user code external: new path utilities, a Rollup plugin to mark user files external, post-build import rewriting, integration across build backends, a Cloudflare preset tweak, and tests.

Changes

Cohort / File(s) Summary
Config & Types
src/types/config.ts, src/config/defaults.ts
Add builderless?: boolean to NitroOptions and set default builderless: false in NitroDefaults.
Builderless path utilities
src/build/utils/builderless-path.ts
New helpers: splitSpecifier, isNodeModulesPath, isSubpath, isBuilderlessUserCodePath to classify absolute user-code paths versus runtime/preset/build dirs.
Externalization plugin
src/build/plugins.ts, src/build/plugins/user-code-external.ts
Register new userCodeExternal(nitro) Rollup plugin when builderless is enabled. Plugin marks matching absolute user-code paths as external during resolveId (pre).
Import rewrite post-build
src/build/rewrite.ts
New rewriteBuilderlessImports(nitro) exported function that scans server .mjs/.js outputs and rewrites absolute builderless specifiers to relative POSIX paths, preserving queries.
Build backend integration
src/build/rolldown/prod.ts, src/build/rollup/prod.ts, src/build/vite/prod.ts
Import and invoke rewriteBuilderlessImports(nitro) as a post-build step in Rollup, Rolldown, and Vite production flows.
Cloudflare preset
src/presets/cloudflare/utils.ts
For cfTarget === "module", make wranglerConfig.no_bundle default depend on !nitro.options.builderless only when undefined (conditional assignment).
Tests
test/minimal/minimal.test.ts
Add builderless test suite covering builders ["rolldown","rollup","vite","vite7"]: checks user-code externalization and that absolute imports are rewritten to relative paths in outputs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat(builder): add builderless mode support' follows conventional commits format with type and scope.
Description check ✅ Passed The PR description clearly relates to the changeset, explaining the builderless mode feature, its purpose for Cloudflare Worker compatibility, and includes validation details.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
src/build/utils/builderless-path.ts (2)

17-20: isSubpath — consider adding a brief JSDoc.

The function is correct (handles exact match via !rel, parent-prefix via !rel.startsWith(".."), and cross-root via !isAbsolute(rel)). However, the semantics aren't immediately obvious from the name alone — a one-line JSDoc (/** Returns true if path is equal to or nested under parent */) would help future readers. As per coding guidelines: "Update types and JSDoc for API changes".


30-36: Consider filtering potentially falsy excludeRoots entries defensively.

If any of nitro.options.output.dir, .serverDir, or .publicDir were ever undefined or empty, isSubpath would receive a degenerate parent. While Nitro defaults should always populate these, a .filter(Boolean) guard would be cheap insurance against a subtle bug in edge configs.

Proposed defensive filter
   const excludeRoots = [
     nitro.options.buildDir,
     nitro.options.output.dir,
     nitro.options.output.serverDir,
     nitro.options.output.publicDir,
-  ];
+  ].filter(Boolean);

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 10, 2026

Open in StackBlitz

npm i https://pkg.pr.new/nitrojs/nitro@4018

commit: 5f9fee8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant