Skip to content

refactor(packages)!: make build tooling optional - #915

Open
harlan-zw wants to merge 4 commits into
mainfrom
refactor/optional-build-dependencies
Open

harlan-zw wants to merge 4 commits into
mainfrom
refactor/optional-build-dependencies

Conversation

@harlan-zw

@harlan-zw harlan-zw commented Jul 25, 2026 •

Copy link
Copy Markdown
Collaborator

🔗 Linked issue

Follow-up to #911.

❓ Type of change

  • 📖 Documentation
  • 🐞 Bug fix
  • 👌 Enhancement
  • ✨ New feature
  • 🧹 Chore
  • ⚠️ Breaking change

📚 Description

Moves build-only tooling out of framework runtime dependency closures and into optional peers. Runtime-only consumers keep a minimal install, while users of bundler and stream integrations must install the documented build packages.

⚠️ Breaking Changes

Build plugin and stream unplugin entry points no longer install their toolchain dependencies automatically.

📝 Migration

Install the build packages listed for the entry point used by the application.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@harlan-zw, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 4 minutes

Limit details: You’ve used all 4 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: dfb8306d-1a5f-415c-b0f8-53fad6cc9f17

📥 Commits

Reviewing files that changed from the base of the PR and between 72a974c and 9233b2a.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • docs/head/1.guides/build-plugins/0.overview.md
  • packages/react/package.json
  • packages/solid-js/package.json
  • packages/svelte/package.json
  • packages/unhead/package.json
  • packages/vue/package.json
📝 Walkthrough

Walkthrough

The PR updates framework package dependency metadata, adds runtime dependency contract tests, and revises build-plugin installation guidance for optional bundler tooling and unplugin.

Changes

Dependency contracts

Layer / File(s) Summary
Package dependency declarations
packages/{vue,react,solid-js,svelte,unhead}/package.json
Framework packages now depend on unhead at runtime and declare optional build-tool peers; unhead adds optional unplugin support.
Runtime dependency contract validation
test/runtime-dependencies.test.ts
Vitest reads package manifests and verifies runtime dependency sets plus optional peer and development dependency coverage.
Build plugin installation guidance
docs/head/1.guides/build-plugins/0.overview.md, packages/unhead/README.md
Documentation adds framework-specific build-tool installation commands and notes the unplugin requirement for stream integrations.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • unjs/unhead#733: Introduced bundler-related dependency requirements reflected by these manifest and contract updates.
  • unjs/unhead#792: Updated build-plugin documentation around framework-specific bundler imports.

Suggested labels: documentation, vue

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title is concise, conventional, and accurately summarizes the main change to make build tooling optional.
Description check ✅ Passed The description covers the linked issue, change type, breaking change, and migration guidance required by the template.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/optional-build-dependencies

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.

@github-actions

github-actions Bot commented Jul 25, 2026 •

Copy link
Copy Markdown
Contributor

📦 Bundle Size

✅ No notable changes

All bundles (14)
Bundle Gzipped Brotli Raw
Core
Client (Minimal) 5.4 kB 4.9 kB 13.4 kB ✅
Client (Full) 9.6 kB 8.7 kB 25 kB ✅
Client (Self-Contained) 5.7 kB 5.1 kB 14.2 kB ✅
Server (Minimal) 4.9 kB 4.4 kB 12.3 kB ✅
Server (Self-Contained) 5.2 kB 4.7 kB 13 kB ✅
Vue
Vue Client (Minimal) 5.9 kB 5.3 kB 14.5 kB ✅
Vue Client (Full) 10.7 kB 9.7 kB 27.8 kB ✅
Vue Server (Minimal) 5.3 kB 4.8 kB 13.3 kB ✅
React
React Client (Minimal) 5.8 kB 5.3 kB 14.6 kB ✅
React Client (Full) 10.7 kB 9.8 kB 28.2 kB ✅
React Server (Minimal) 5.2 kB 4.7 kB 13 kB ✅
Schema.org
Schema.org (Minimal) 11.7 kB 10.5 kB 34.2 kB ✅
Schema.org Imports 0.1 kB 0.1 kB 0.1 kB ✅
Schema.org Vue Meta 0.5 kB 0.4 kB 1 kB ✅

📦 Runtime Dependencies

🟢 9 packages smaller · net -6.3 MB

Package Install size Dependencies Δ
@unhead/angular 773.6 kB → 114.2 kB 10 → 2 🟢 -659.4 kB (-85.2%)
@unhead/cli 4.5 MB → 4 MB 18 → 12 🟢 -479.4 kB (-10.8%)
@unhead/eslint-plugin 683.2 kB → 23.8 kB 9 → 1 🟢 -659.4 kB (-96.5%)
@unhead/react 810.7 kB → 23.8 kB 11 → 1 🟢 -786.9 kB (-97.1%)
@unhead/schema-org 683.2 kB → 23.8 kB 9 → 1 🟢 -659.4 kB (-96.5%)
@unhead/solid-js 810.7 kB → 23.8 kB 11 → 1 🟢 -786.9 kB (-97.1%)
@unhead/svelte 810.7 kB → 23.8 kB 11 → 1 🟢 -786.9 kB (-97.1%)
@unhead/vue 810.7 kB → 23.8 kB 11 → 1 🟢 -786.9 kB (-97.1%)
unhead 683.2 kB → 23.8 kB 9 → 1 🟢 -659.4 kB (-96.5%)
All packages (10)
Package External deps Install size Largest dependency Skipped optional
@unhead/angular 2 114.2 kB tslib 90.4 kB 0
@unhead/bundler 10 786.9 kB @jridgewell/trace-mapping 146.7 kB 0
@unhead/cli 12 4 MB @oxc-parser/binding-linux-arm64-gnu 2 MB 18
@unhead/eslint-plugin 1 23.8 kB hookable 23.8 kB 0
@unhead/react 1 23.8 kB hookable 23.8 kB 0
@unhead/schema-org 1 23.8 kB hookable 23.8 kB 0
@unhead/solid-js 1 23.8 kB hookable 23.8 kB 0
@unhead/svelte 1 23.8 kB hookable 23.8 kB 0
@unhead/vue 1 23.8 kB hookable 23.8 kB 0
unhead 1 23.8 kB hookable 23.8 kB 0
Skipped optional dependencies (18)
  • @unhead/cli: oxc-parser -> @oxc-parser/binding-android-arm-eabi, oxc-parser -> @oxc-parser/binding-android-arm64, oxc-parser -> @oxc-parser/binding-darwin-arm64, oxc-parser -> @oxc-parser/binding-darwin-x64, oxc-parser -> @oxc-parser/binding-freebsd-x64, oxc-parser -> @oxc-parser/binding-linux-arm-gnueabihf, oxc-parser -> @oxc-parser/binding-linux-arm-musleabihf, oxc-parser -> @oxc-parser/binding-linux-arm64-musl, oxc-parser -> @oxc-parser/binding-linux-ppc64-gnu, oxc-parser -> @oxc-parser/binding-linux-riscv64-gnu, oxc-parser -> @oxc-parser/binding-linux-riscv64-musl, oxc-parser -> @oxc-parser/binding-linux-s390x-gnu, oxc-parser -> @oxc-parser/binding-linux-x64-gnu, oxc-parser -> @oxc-parser/binding-linux-x64-musl, oxc-parser -> @oxc-parser/binding-openharmony-arm64, oxc-parser -> @oxc-parser/binding-win32-arm64-msvc, oxc-parser -> @oxc-parser/binding-win32-ia32-msvc, oxc-parser -> @oxc-parser/binding-win32-x64-msvc

Production dependencies only. Peer dependencies and Unhead workspace packages are excluded. Skipped optional dependencies are unavailable on the CI platform.


⚡ Performance (directional)

✅ No significant change (within CI noise)

All benchmarks (25)
Benchmark PR Δ RME
SSR render (CPU) 0.362 ms ~ noise ±9.5%
SSR render (wall) 0.261 ms ~ noise ±4.8%
SSR allocated / render 242.2 KiB ~ noise ±5.8%
Schema.org cached render (CPU) 0.364 ms ~ noise ±5.3%
Schema.org cached render (wall) 0.265 ms ~ noise ±2.5%
Schema.org cached allocated / render 129.1 KiB ~ noise ±1.7%
Streaming wrapStream drain (CPU) 0.237 ms ~ noise ±3.5%
Streaming wrapStream drain (wall) 0.137 ms ~ noise ±4.4%
Streaming allocated / drain 149.3 KiB ~ noise ±2.6%
Streaming suspense chunk (CPU) 0.012 ms ~ noise ±5.8%
Streaming allocated / suspense chunk 4.9 KiB ~ noise ±0.2%
CSR DOM mutations / nav 38 ~ noise —
CSR re-render (CPU) 0.990 ms ~ noise ±5.1%
CSR re-render (wall) 0.552 ms ~ noise ±2.5%
Bundler: transform id filter mixed ids 0.191 ms ~ noise ±0.5%
Bundler: useSeoMetaTransform static calls 3.562 ms ~ noise ±4.3%
Bundler: minifyTransform inline script/style 0.523 ms ~ noise ±3.5%
Bundler: treeshakeServerComposables many calls 2.594 ms ~ noise ±6.1%
Bundler: treeshakeServerComposables skip unrelated code 0.002 ms ~ noise ±1.1%
Bundler: ssrStaticReplace many head.ssr reads 1.677 ms ~ noise ±6.6%
Bundler: ssrStaticReplace skip unrelated code 0.002 ms ~ noise ±3.1%
Bundler: createHeadTransform many createHead calls 0.598 ms ~ noise ±5.3%
Bundler: react streaming skip JSX without head calls 0.002 ms ~ noise ±0.6%
Bundler: react streaming transform JSX with head calls 1.603 ms ~ noise ±6.7%
Bundler: solid streaming skip JSX without head calls 0.002 ms ~ noise ±1.0%

Baseline: main @ 7206ece · 2026-08-21 · gzipped is the headline size metric · perf is directional (shared-runner, gated)

@harlan-zw
harlan-zw marked this pull request as ready for review July 26, 2026 05:55

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/runtime-dependencies.test.ts (1)

5-10: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Also guard against optionalDependencies.

The test checks only dependencies; a build package moved into optionalDependencies would still enter consumers’ install graph while passing this contract. Add optionalDependencies to PackageJson and assert it is empty for these runtime packages.

Proposed test adjustment
 interface PackageJson {
   dependencies?: Record<string, string>
   devDependencies?: Record<string, string>
   name: string
+  optionalDependencies?: Record<string, string>
   peerDependencies?: Record<string, string>
   peerDependenciesMeta?: Record<string, { optional?: boolean }>
 }

       expect(Object.keys(packageJson.dependencies || {}).sort()).toEqual(contract.runtimeDependencies)
+      expect(Object.keys(packageJson.optionalDependencies || {})).toEqual([])

Also applies to: 47-54

🤖 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 `@test/runtime-dependencies.test.ts` around lines 5 - 10, Extend the
PackageJson interface with optionalDependencies and update the runtime-package
dependency assertions in the affected test cases to require both dependencies
and optionalDependencies to be empty. Preserve the existing checks for other
dependency categories and apply the same guard consistently to all referenced
runtime packages.
🤖 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 `@docs/head/1.guides/build-plugins/0.overview.md`:
- Line 25: Update the guidance in the overview so the Vite configuration
instructions explicitly apply only to /vite or /bundler users. Tell runtime-only
projects to skip the remaining plugin setup instructions, while preserving the
existing plugin guidance for applicable projects.

---

Nitpick comments:
In `@test/runtime-dependencies.test.ts`:
- Around line 5-10: Extend the PackageJson interface with optionalDependencies
and update the runtime-package dependency assertions in the affected test cases
to require both dependencies and optionalDependencies to be empty. Preserve the
existing checks for other dependency categories and apply the same guard
consistently to all referenced runtime packages.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3a619d60-092a-45c8-8c24-a48df04fda4f

📥 Commits

Reviewing files that changed from the base of the PR and between 00efefb and 72a974c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (8)
  • docs/head/1.guides/build-plugins/0.overview.md
  • packages/react/package.json
  • packages/solid-js/package.json
  • packages/svelte/package.json
  • packages/unhead/README.md
  • packages/unhead/package.json
  • packages/vue/package.json
  • test/runtime-dependencies.test.ts

Comment thread docs/head/1.guides/build-plugins/0.overview.md Outdated
@harlan-zw

Copy link
Copy Markdown
Collaborator Author

🤖 Harlan Agent Kit automated review

This was generated and posted by a robot, not Harlan's personal review.

PASS · 90/100 confidence

  • Reviewed 34104712 against main@d9b3d2a6
  • Base current; GitHub reports no conflicts
  • PR title and body match the project template; review threads are resolved
  • Adversarial review found no remaining material code issue
  • Broad diff reviewed; required CI passed 9/9; confidence includes limited local execution

Human merge decision still required.

This branch has not been deployed

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant