Skip to content

fix(vite): support Bun-only dev server#4310

Open
puneetdixit200 wants to merge 1 commit into
nitrojs:mainfrom
puneetdixit200:fix/bun-dev-runner-response
Open

fix(vite): support Bun-only dev server#4310
puneetdixit200 wants to merge 1 commit into
nitrojs:mainfrom
puneetdixit200:fix/bun-dev-runner-response

Conversation

@puneetdixit200

Copy link
Copy Markdown

🔗 Linked issue

Resolves #4182

❓ 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

When Nitro dev runs inside Bun, the default node-worker runner still requires Node to be available. This selects the bun-process dev runner by default when Nitro itself is running under Bun, while preserving explicit devServer.runner and NITRO_DEV_RUNNER overrides.

The dev worker now also normalizes responses before Bun serves them by dropping explicit content-length, avoiding duplicate header parse errors when Bun sends the response. It waits briefly for Vite to register the environment before handling the first request, which avoids a first-request race in the Bun process runner.

Validation:

  • pnpm vitest run test/unit/vite-dev-worker.test.ts --reporter verbose
  • pnpm fmt
  • pnpm typecheck
  • pnpm build --stub
  • No-Node Bun smoke: PATH=/tmp/nitro-no-node-bin:/usr/bin:/bin:/usr/sbin:/sbin bun run dev in examples/vite-nitro-plugin, first request returned HTTP/1.1 200 OK and Hello from virtual entry!

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly. (Not applicable: runtime dev-server bug fix.)

@puneetdixit200 puneetdixit200 requested a review from pi0 as a code owner June 4, 2026 05:55
@vercel

vercel Bot commented Jun 4, 2026

Copy link
Copy Markdown

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

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR centralizes dev runner selection to detect Bun at runtime and adds Bun response normalization to the async dev worker. New helpers detect Bun globals and default to "bun-process" when present. Build and dev-server code refactored to use these helpers. Dev worker fetch is now async with exponential backoff environment polling and removes content-length headers for Bun Response objects.

Changes

Bun Dev Runner Detection and Response Normalization

Layer / File(s) Summary
Default Bun runner detection helpers
src/build/vite/env.ts, src/dev/server.ts
New getDefaultDevRunnerName() detects globalThis.Bun and returns "bun-process" if present, otherwise "node-worker". getDevRunnerName(ctx) checks options and env vars before falling back to the default.
Dev runner selection refactoring
src/build/vite/env.ts, src/dev/server.ts
_loadRunner, _isWorkerdRunner, and #reload() now use the centralized helpers instead of inlining runner-name logic, ensuring consistent Bun detection across build and dev contexts.
Async dev worker with Bun response normalization
src/runtime/internal/vite/dev-worker.mjs
fetch(req) is now async and waits for Vite environments via waitForViteEnv with exponential backoff. New normalizeBunResponse removes content-length headers and reconstructs Response objects to address Bun's strict Response type checking.
Response normalization tests
test/unit/vite-dev-worker.test.ts
Vitest suite validates that normalization preserves non-Bun responses unchanged and removes content-length while preserving other headers and body when Bun is present.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title 'fix(vite): support Bun-only dev server' follows conventional commits format with type 'fix' and describes the main change clearly.
Description check ✅ Passed The description is directly related to the changeset, explaining the Bun dev runner selection logic and response normalization changes implemented in the code.
Linked Issues check ✅ Passed The code changes address issue #4182 by implementing Bun-specific dev runner selection and response normalization to prevent Node-specific response errors in Bun-only environments.
Out of Scope Changes check ✅ Passed All changes are in-scope: dev runner selection logic, response normalization for Bun, and corresponding unit tests directly address the linked issue #4182.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/build/vite/env.ts`:
- Around line 255-259: There are two identical implementations of
getDefaultDevRunnerName() causing duplication; extract this helper into a single
internal utility (e.g., create a new module like
internal/getDefaultDevRunnerName or utils/devRunner) that exports
getDefaultDevRunnerName, update both locations that currently define the
function (the Vite env module and the dev server module) to import and use the
shared function, and remove the local definitions so both modules call the same
exported getDefaultDevRunnerName; keep the implementation exactly as-is
(checking globalThis.Bun) and ensure the import is typed as RunnerName where
used.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 46e4149e-d443-4a57-b7c5-dc0e698a4d43

📥 Commits

Reviewing files that changed from the base of the PR and between a75e3a5 and 8d8843d.

📒 Files selected for processing (4)
  • src/build/vite/env.ts
  • src/dev/server.ts
  • src/runtime/internal/vite/dev-worker.mjs
  • test/unit/vite-dev-worker.test.ts

Comment thread src/build/vite/env.ts
Comment on lines +255 to +259
function getDefaultDevRunnerName(): RunnerName {
return typeof (globalThis as typeof globalThis & { Bun?: unknown }).Bun === "undefined"
? "node-worker"
: "bun-process";
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check env-runner for valid runner names and bun-process support

# Search for RunnerName type definition or valid runner strings
rg -n -C5 'bun-process|RunnerName|type.*Runner.*=' --type=ts node_modules/env-runner/

# Check for bun-process runner implementation
fd -e ts -e js bun node_modules/env-runner/ --exec cat {}

Repository: nitrojs/nitro

Length of output: 234


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Repo-wide search for bun-process / RunnerName / env-runner
rg -n --hidden --no-ignore-vcs "bun-process" . || true
rg -n --hidden --no-ignore-vcs "RunnerName" . || true
rg -n --hidden --no-ignore-vcs "env-runner" . || true

# Identify env-runner version from package manifests/lockfiles
for f in package.json pnpm-lock.yaml package-lock.json yarn.lock; do
  if [ -f "$f" ]; then
    echo "---- $f ----"
    rg -n "env-runner" "$f" || true
  fi
done

Repository: nitrojs/nitro

Length of output: 4259


🌐 Web query:

unjs env-runner 0.1.9 RunnerName bun-process

💡 Result:

The BunProcessEnvRunner is a specific runner class provided by the unjs/env-runner library designed to execute server applications using the Bun runtime or a Node.js process [1][2]. Key details regarding the runner: Isolation: It operates by spawning a child process using Bun or Node.js [1][2]. IPC Mechanism: It utilizes Bun's spawn IPC or Node.js's fork mechanism for inter-process communication [1][2]. Usage: It is one of the available runners supported by the env-runner package, which can be selected via the --runner bun-process CLI flag or imported directly from env-runner/runners/bun-process [2]. The env-runner library is a generic environment runner that supports various runtimes and deployment contexts, including Node.js (worker threads and child processes), Bun, Deno, Cloudflare Workers (via miniflare), Vercel, and Netlify [1][3]. As of June 2026, the project continues to receive updates to its runner implementations [3][4].

Citations:


🌐 Web query:

env-runner@0.1.9 RunnerName "bun-process" type

💡 Result:

In the env-runner package, "bun-process" is a valid member of the RunnerName type [1][2]. It refers to a runner that executes applications in a separate process using the Bun runtime, utilizing Bun.spawn for IPC (Inter-Process Communication) or Node.js-style fork mechanisms [3][4][5]. The RunnerName type is a union of strings used to specify which environment runner should be utilized [1][2]. As of the current version, the available runners include: - node-worker [4][5] - node-process [4][5] - bun-process [4][5] - deno-process [4][5] - self [4][5] - miniflare [4][5] - vercel [1] - netlify [1] Users can select a runner via the --runner flag in the CLI or through configuration options in tools like Nitro [4][5][2]. The "bun-process" runner specifically provides isolation by running the target application as a child process with the Bun runtime [3][4].

Citations:


Remove duplicated getDefaultDevRunnerName() helper to prevent drift.

getDefaultDevRunnerName() is defined identically in both src/build/vite/env.ts (lines 255-259) and src/dev/server.ts (lines 254-258). Extract it into a shared internal utility and import it in both places to avoid divergence.
"bun-process" is a valid RunnerName in the repo’s env-runner@^0.1.9 dependency, so no change is needed there.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/build/vite/env.ts` around lines 255 - 259, There are two identical
implementations of getDefaultDevRunnerName() causing duplication; extract this
helper into a single internal utility (e.g., create a new module like
internal/getDefaultDevRunnerName or utils/devRunner) that exports
getDefaultDevRunnerName, update both locations that currently define the
function (the Vite env module and the dev server module) to import and use the
shared function, and remove the local definitions so both modules call the same
exported getDefaultDevRunnerName; keep the implementation exactly as-is
(checking globalThis.Bun) and ensure the import is typed as RunnerName where
used.

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.

Bun throws error when not having Node installed

1 participant