Thanks to visit codestin.com
Credit goes to github.com

Skip to content

v3.0.0#620

Merged
harlan-zw merged 0 commit into
mainfrom
v3
Mar 10, 2026
Merged

v3.0.0#620
harlan-zw merged 0 commit into
mainfrom
v3

Conversation

@harlan-zw

@harlan-zw harlan-zw commented Dec 24, 2025

Copy link
Copy Markdown
Collaborator

Branch to track Unhead v3 that will introduce support for streaming and numerous performance and DX improvmeents.

PRs

Performance

Bundle

Build v3 size main size Δ size v3 gz main gz Δ gz
client 10254 11513 -1259 (-10.9%) 4235 4769 -534 (-11.2%)
server 9894 10361 -467 (-4.5%) 4060 4254 -194 (-4.6%)
vueClient 11323 12567 -1244 (-9.9%) 4676 5209 -533 (-10.2%)
vueServer 10849 11312 -463 (-4.1%) 4460 4651 -191 (-4.1%)

✨ 11.2% smaller client

Bench

e2e benchmark

Suite main (hz) v3 (hz) main v3 Δ ms Δ %
@unhead/vue 9,891 13,878 0.106ms 0.072ms -0.034ms 32% faster
bench 11,333 13,758 0.088ms 0.073ms -0.015ms 17% faster

simple benchmark

Suite main (avg hz) v3 (avg hz) main mean v3 mean Δ ms Δ %
@unhead/vue 113,881 153,648 0.0088ms 0.0065ms -0.0023ms 26% faster
bench 110,724 154,459 0.0090ms 0.0065ms -0.0025ms 28% faster

✨ ~32% faster for mid-size site

@harlan-zw harlan-zw changed the title chore: release v3.0.0-beta.1 v3.0.0 Dec 24, 2025
@github-actions

github-actions Bot commented Dec 24, 2025

Copy link
Copy Markdown
Contributor

Bundle Size Analysis

Bundle Size Gzipped
Client (Minimal) 11.4 kB → 10.2 kB 🟢 1.2 kB 4.7 kB → 4.2 kB 🟢 0.5 kB
Server (Minimal) 10.3 kB → 9.8 kB 🟢 0.5 kB 4.2 kB → 4 kB 🟢 0.2 kB
Vue Client (Minimal) 12.3 kB → 11.1 kB 🟢 1.2 kB 5.1 kB → 4.6 kB 🟢 0.5 kB
Vue Server (Minimal) 11.1 kB → 10.6 kB 🟢 0.5 kB 4.6 kB → 4.4 kB 🟢 0.2 kB

Comment on lines +54 to +87
app.use('/{*path}', async (req, res) => {
try {
const url = req.originalUrl

let template, render
if (!isProd) {
template = fs.readFileSync(resolve('index.html'), 'utf-8')
template = await vite.transformIndexHtml(url, template)
render = (await vite.ssrLoadModule('/src/entry-server.tsx')).render
}
else {
template = indexProd
render = (await import('./dist/server/entry-server.js')).render
}

const stream = render(url, template)

res.status(200).set({ 'Content-Type': 'text/html; charset=utf-8' })
const reader = stream.getReader()

while (true) {
const { done, value } = await reader.read()
if (done) break
if (res.closed) break
res.write(value)
}
res.end()
}
catch (e) {
vite && vite.ssrFixStacktrace(e)
console.log(e.stack)
res.status(500).end(e.stack)
}
})

Check failure

Code scanning / CodeQL

Missing rate limiting

This route handler performs [a file system access](1), but is not rate-limited.

Copilot Autofix

AI 4 months ago

In general, the fix is to introduce rate limiting middleware using a well‑known library (e.g., express-rate-limit) and apply it to the route that performs file system access and SSR work (or globally to all routes). This limits how many requests a client can make within a time window, mitigating DoS risk from that endpoint while preserving existing functionality.

For this specific file (examples/vite-ssr-solidjs-streaming/server.js), the minimal, non‑disruptive change is:

  1. Import express-rate-limit at the top of the file.
  2. Create a limiter instance, for example allowing a reasonable number of requests per IP per time window (e.g., 100 per 15 minutes as in the provided pattern).
  3. Apply this limiter to the path that currently has the expensive handler: app.use('/{*path}', limiter, async (req, res) => { ... }).

This keeps the handler logic unchanged and only adds a middleware step before it. Concretely:

  • At the top of the file, after the existing imports, add:
    import rateLimit from 'express-rate-limit'
  • After const app = express(), define:
    const ssrLimiter = rateLimit({
      windowMs: 15 * 60 * 1000,
      max: 100,
    })
  • Modify the route at line 54 from app.use('/{*path}', async (req, res) => { ... }) to app.use('/{*path}', ssrLimiter, async (req, res) => { ... }).

No other behavior needs to change; Vite dev middleware and static file serving remain unaffected.

Suggested changeset 2
examples/vite-ssr-solidjs-streaming/server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/examples/vite-ssr-solidjs-streaming/server.js b/examples/vite-ssr-solidjs-streaming/server.js
--- a/examples/vite-ssr-solidjs-streaming/server.js
+++ b/examples/vite-ssr-solidjs-streaming/server.js
@@ -3,6 +3,7 @@
 import path from 'node:path'
 import { fileURLToPath } from 'node:url'
 import express from 'express'
+import rateLimit from 'express-rate-limit'
 
 const isTest = process.env.NODE_ENV === 'test' || !!process.env.VITE_TEST_BUILD
 
@@ -19,6 +20,10 @@
     : ''
 
   const app = express()
+  const ssrLimiter = rateLimit({
+    windowMs: 15 * 60 * 1000,
+    max: 100,
+  })
 
   /** @type {import('vite').ViteDevServer} */
   let vite
@@ -51,7 +56,7 @@
     )
   }
 
-  app.use('/{*path}', async (req, res) => {
+  app.use('/{*path}', ssrLimiter, async (req, res) => {
     try {
       const url = req.originalUrl
 
EOF
@@ -3,6 +3,7 @@
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import express from 'express'
import rateLimit from 'express-rate-limit'

const isTest = process.env.NODE_ENV === 'test' || !!process.env.VITE_TEST_BUILD

@@ -19,6 +20,10 @@
: ''

const app = express()
const ssrLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
})

/** @type {import('vite').ViteDevServer} */
let vite
@@ -51,7 +56,7 @@
)
}

app.use('/{*path}', async (req, res) => {
app.use('/{*path}', ssrLimiter, async (req, res) => {
try {
const url = req.originalUrl

examples/vite-ssr-solidjs-streaming/package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/examples/vite-ssr-solidjs-streaming/package.json b/examples/vite-ssr-solidjs-streaming/package.json
--- a/examples/vite-ssr-solidjs-streaming/package.json
+++ b/examples/vite-ssr-solidjs-streaming/package.json
@@ -16,7 +16,8 @@
     "@unhead/solid-js": "workspace:*",
     "compression": "^1.8.1",
     "express": "^5.2.1",
-    "solid-js": "^1.9.11"
+    "solid-js": "^1.9.11",
+    "express-rate-limit": "^8.3.1"
   },
   "devDependencies": {
     "@playwright/test": "^1.58.2",
EOF
@@ -16,7 +16,8 @@
"@unhead/solid-js": "workspace:*",
"compression": "^1.8.1",
"express": "^5.2.1",
"solid-js": "^1.9.11"
"solid-js": "^1.9.11",
"express-rate-limit": "^8.3.1"
},
"devDependencies": {
"@playwright/test": "^1.58.2",
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 8.3.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +54 to +87
app.use('/{*path}', async (req, res) => {
try {
const url = req.originalUrl

let template, render
if (!isProd) {
template = fs.readFileSync(resolve('index.html'), 'utf-8')
template = await vite.transformIndexHtml(url, template)
render = (await vite.ssrLoadModule('/src/entry-server.ts')).render
}
else {
template = indexProd
render = (await import('./dist/server/entry-server.js')).render
}

const stream = await render(url, template)

res.status(200).set({ 'Content-Type': 'text/html; charset=utf-8' })
const reader = stream.getReader()

while (true) {
const { done, value } = await reader.read()
if (done) break
if (res.closed) break
res.write(value)
}
res.end()
}
catch (e) {
vite && vite.ssrFixStacktrace(e)
console.log(e.stack)
res.status(500).end(e.stack)
}
})

Check failure

Code scanning / CodeQL

Missing rate limiting

This route handler performs [a file system access](1), but is not rate-limited.

Copilot Autofix

AI 4 months ago

In general, we should introduce a rate-limiting middleware and apply it to the expensive route handler so that any client can only make a bounded number of requests in a given time window. In Express, the standard approach is to use a library such as express-rate-limit, configure a limiter (e.g., N requests per IP per time window), and attach it either globally (app.use(limiter)) or specifically to the route (app.use('/{*path}', limiter, handler)).

For this specific file, the least invasive fix is:

  • Import express-rate-limit at the top of examples/vite-ssr-svelte-streaming/server.js.
  • Inside createServer, after const app = express(), define a limiter instance with a reasonable window and max request count.
  • Attach that limiter to the SSR route used at line 54 so that only this expensive handler is affected and existing functional behavior is preserved aside from enforcing limits.

Concretely:

  • Add import rateLimit from 'express-rate-limit' near the other imports.
  • After const app = express(), define const ssrLimiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }) (values can mirror the example in the background).
  • Change app.use('/{*path}', async (req, res) => { ... }) into app.use('/{*path}', ssrLimiter, async (req, res) => { ... }).

No other logic should be changed.

Suggested changeset 2
examples/vite-ssr-svelte-streaming/server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/examples/vite-ssr-svelte-streaming/server.js b/examples/vite-ssr-svelte-streaming/server.js
--- a/examples/vite-ssr-svelte-streaming/server.js
+++ b/examples/vite-ssr-svelte-streaming/server.js
@@ -3,6 +3,7 @@
 import path from 'node:path'
 import { fileURLToPath } from 'node:url'
 import express from 'express'
+import rateLimit from 'express-rate-limit'
 
 const isTest = process.env.NODE_ENV === 'test' || !!process.env.VITE_TEST_BUILD
 
@@ -19,6 +20,10 @@
     : ''
 
   const app = express()
+  const ssrLimiter = rateLimit({
+    windowMs: 15 * 60 * 1000,
+    max: 100,
+  })
 
   /** @type {import('vite').ViteDevServer} */
   let vite
@@ -51,7 +56,7 @@
     )
   }
 
-  app.use('/{*path}', async (req, res) => {
+  app.use('/{*path}', ssrLimiter, async (req, res) => {
     try {
       const url = req.originalUrl
 
EOF
@@ -3,6 +3,7 @@
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import express from 'express'
import rateLimit from 'express-rate-limit'

const isTest = process.env.NODE_ENV === 'test' || !!process.env.VITE_TEST_BUILD

@@ -19,6 +20,10 @@
: ''

const app = express()
const ssrLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
})

/** @type {import('vite').ViteDevServer} */
let vite
@@ -51,7 +56,7 @@
)
}

app.use('/{*path}', async (req, res) => {
app.use('/{*path}', ssrLimiter, async (req, res) => {
try {
const url = req.originalUrl

examples/vite-ssr-svelte-streaming/package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/examples/vite-ssr-svelte-streaming/package.json b/examples/vite-ssr-svelte-streaming/package.json
--- a/examples/vite-ssr-svelte-streaming/package.json
+++ b/examples/vite-ssr-svelte-streaming/package.json
@@ -15,7 +15,8 @@
     "@unhead/svelte": "workspace:*",
     "compression": "^1.8.1",
     "express": "^5.2.1",
-    "sirv": "^3.0.2"
+    "sirv": "^3.0.2",
+    "express-rate-limit": "^8.3.1"
   },
   "devDependencies": {
     "@playwright/test": "^1.58.2",
EOF
@@ -15,7 +15,8 @@
"@unhead/svelte": "workspace:*",
"compression": "^1.8.1",
"express": "^5.2.1",
"sirv": "^3.0.2"
"sirv": "^3.0.2",
"express-rate-limit": "^8.3.1"
},
"devDependencies": {
"@playwright/test": "^1.58.2",
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 8.3.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
catch (e) {
vite && vite.ssrFixStacktrace(e)
console.log(e.stack)
res.status(500).end(e.stack)

Check warning

Code scanning / CodeQL

Exception text reinterpreted as HTML

[Exception text](1) is reinterpreted as HTML without escaping meta-characters.

Copilot Autofix

AI 6 months ago

In general, never send raw exception messages or stack traces directly to the browser as HTML. For user-facing responses, either (a) send a generic error page/message that does not include user input, or (b) if you must include details, escape/encode the text appropriately (for example, HTML-escape it, or serve it with a safe content type like text/plain).

For this specific code, the safest and simplest change without altering core functionality is:

  • Stop writing e.stack directly as HTML.
  • Instead, respond with a generic error message to the client (for example, Internal Server Error) and continue logging the full stack trace to the server console.
  • Optionally, if you still want to expose some detail (e.g., in dev), you can encode the stack trace before sending it or change the content type to text/plain. Since we should not change surrounding behavior more than necessary and avoid adding new configuration toggles, the minimal secure fix is to replace res.status(500).end(e.stack) with a generic constant string response such as res.status(500).end('Internal Server Error').

Concretely:

  • In examples/vite-ssr-solidjs-streaming/server.js, within the catch (e) block around line 82, keep vite && vite.ssrFixStacktrace(e) and console.log(e.stack) as-is, but change the final response so it no longer includes e.stack. No new imports or helper functions are required.
Suggested changeset 1
examples/vite-ssr-solidjs-streaming/server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/examples/vite-ssr-solidjs-streaming/server.js b/examples/vite-ssr-solidjs-streaming/server.js
--- a/examples/vite-ssr-solidjs-streaming/server.js
+++ b/examples/vite-ssr-solidjs-streaming/server.js
@@ -82,7 +82,7 @@
     catch (e) {
       vite && vite.ssrFixStacktrace(e)
       console.log(e.stack)
-      res.status(500).end(e.stack)
+      res.status(500).end('Internal Server Error')
     }
   })
 
EOF
@@ -82,7 +82,7 @@
catch (e) {
vite && vite.ssrFixStacktrace(e)
console.log(e.stack)
res.status(500).end(e.stack)
res.status(500).end('Internal Server Error')
}
})

Copilot is powered by AI and may make mistakes. Always verify output.
catch (e) {
vite && vite.ssrFixStacktrace(e)
console.log(e.stack)
res.status(500).end(e.stack)

Check warning

Code scanning / CodeQL

Information exposure through a stack trace

This information exposed to the user depends on [stack trace information](1).

Copilot Autofix

AI 6 months ago

In general, the fix is to avoid sending the stack trace (or detailed error object) to the client, and instead log it on the server while returning a generic error message and status code to the user. This preserves debuggability without exposing internal implementation details.

Specifically for this file, we should:

  • Keep server-side logging (console.log or similar) of the full error/stack trace.
  • Replace res.status(500).end(e.stack) with a generic message like res.status(500).end('Internal Server Error') (or localized/alternative wording) that does not depend on e or e.stack.
  • Optionally slightly improve logging by logging both the error and its stack, but without changing behavior observed by the client.

All required functionality can be implemented within examples/vite-ssr-solidjs-streaming/server.js without new imports. The only change is in the catch block of the app.use('/{*path}', ...) handler around lines 82–86.

Suggested changeset 1
examples/vite-ssr-solidjs-streaming/server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/examples/vite-ssr-solidjs-streaming/server.js b/examples/vite-ssr-solidjs-streaming/server.js
--- a/examples/vite-ssr-solidjs-streaming/server.js
+++ b/examples/vite-ssr-solidjs-streaming/server.js
@@ -82,7 +82,7 @@
     catch (e) {
       vite && vite.ssrFixStacktrace(e)
       console.log(e.stack)
-      res.status(500).end(e.stack)
+      res.status(500).end('Internal Server Error')
     }
   })
 
EOF
@@ -82,7 +82,7 @@
catch (e) {
vite && vite.ssrFixStacktrace(e)
console.log(e.stack)
res.status(500).end(e.stack)
res.status(500).end('Internal Server Error')
}
})

Copilot is powered by AI and may make mistakes. Always verify output.
catch (e) {
vite && vite.ssrFixStacktrace(e)
console.log(e.stack)
res.status(500).end(e.stack)

Check warning

Code scanning / CodeQL

Exception text reinterpreted as HTML

[Exception text](1) is reinterpreted as HTML without escaping meta-characters.

Copilot Autofix

AI 6 months ago

In general, to fix this class of issue you should avoid sending raw exception messages or stack traces directly in an HTML response. For production, it’s safer to send a generic error page or message that contains no user-controllable data. For development, if you really need to expose the error content to the browser, you must HTML‑escape (encode) it so that any <, >, &, quotes, etc. are rendered as text instead of being interpreted as HTML or JavaScript.

The best fix here without changing existing functionality too much is:

  • In the catch block, keep logging the full stack trace to the server console (console.log(e.stack)).
  • Change the HTTP response so that it no longer sends e.stack directly. Instead:
    • In production (isProd === true), send a generic error message (e.g., "Internal Server Error").
    • In non‑production, either:
      • send an HTML‑escaped version of e.stack, or
      • for maximum simplicity and safety, also send a generic message.
  • Implement a small HTML-escaping helper within this file if you want to preserve error content in dev. This avoids adding new dependencies and keeps the change localized.

Concretely, in examples/vite-ssr-svelte-streaming/server.js:

  • Add a simple escapeHtml helper function near the top of the file.
  • Replace res.status(500).end(e.stack) with something like:
    • const msg = isProd ? 'Internal Server Error' : escapeHtml(String(e.stack || e));
    • res.status(500).set({ 'Content-Type': 'text/html; charset=utf-8' }).end(msg);
  • Make sure the catch block doesn’t introduce any new tainted pathway (i.e., only escapes or discards exception content).
Suggested changeset 1
examples/vite-ssr-svelte-streaming/server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/examples/vite-ssr-svelte-streaming/server.js b/examples/vite-ssr-svelte-streaming/server.js
--- a/examples/vite-ssr-svelte-streaming/server.js
+++ b/examples/vite-ssr-svelte-streaming/server.js
@@ -6,6 +6,15 @@
 
 const isTest = process.env.NODE_ENV === 'test' || !!process.env.VITE_TEST_BUILD
 
+function escapeHtml(str) {
+  return String(str)
+    .replace(/&/g, '&amp;')
+    .replace(/</g, '&lt;')
+    .replace(/>/g, '&gt;')
+    .replace(/"/g, '&quot;')
+    .replace(/'/g, '&#39;')
+}
+
 export async function createServer(
   root = process.cwd(),
   isProd = process.env.NODE_ENV === 'production',
@@ -81,8 +90,14 @@
     }
     catch (e) {
       vite && vite.ssrFixStacktrace(e)
-      console.log(e.stack)
-      res.status(500).end(e.stack)
+      console.log(e && e.stack ? e.stack : e)
+      const message = isProd
+        ? 'Internal Server Error'
+        : escapeHtml(e && e.stack ? e.stack : String(e))
+      res
+        .status(500)
+        .set({ 'Content-Type': 'text/html; charset=utf-8' })
+        .end(message)
     }
   })
 
EOF
@@ -6,6 +6,15 @@

const isTest = process.env.NODE_ENV === 'test' || !!process.env.VITE_TEST_BUILD

function escapeHtml(str) {
return String(str)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
}

export async function createServer(
root = process.cwd(),
isProd = process.env.NODE_ENV === 'production',
@@ -81,8 +90,14 @@
}
catch (e) {
vite && vite.ssrFixStacktrace(e)
console.log(e.stack)
res.status(500).end(e.stack)
console.log(e && e.stack ? e.stack : e)
const message = isProd
? 'Internal Server Error'
: escapeHtml(e && e.stack ? e.stack : String(e))
res
.status(500)
.set({ 'Content-Type': 'text/html; charset=utf-8' })
.end(message)
}
})

Copilot is powered by AI and may make mistakes. Always verify output.
catch (e) {
vite && vite.ssrFixStacktrace(e)
console.log(e.stack)
res.status(500).end(e.stack)

Check warning

Code scanning / CodeQL

Information exposure through a stack trace

This information exposed to the user depends on [stack trace information](1).

Copilot Autofix

AI 6 months ago

In general, the fix is to stop sending full stack traces to the client and instead send a generic error message while logging the stack trace on the server. The server logs retain the detail needed for debugging without exposing it over HTTP.

For this specific file, the best minimal change is inside the catch (e) block of the app.use('/{*path}', ...) handler. We should:

  • Keep vite && vite.ssrFixStacktrace(e) as-is (it adjusts stack traces for server-side logging and debugging).
  • Keep logging the error stack to the server console (or potentially improve logging later), but not include it in the HTTP response.
  • Replace res.status(500).end(e.stack) with a response that sends a generic message such as "Internal Server Error" or "An error occurred" without any stack/implementation details.

No new imports or external libraries are strictly required. All changes are localized to the existing catch block in examples/vite-ssr-svelte-streaming/server.js, around lines 82–86.

Suggested changeset 1
examples/vite-ssr-svelte-streaming/server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/examples/vite-ssr-svelte-streaming/server.js b/examples/vite-ssr-svelte-streaming/server.js
--- a/examples/vite-ssr-svelte-streaming/server.js
+++ b/examples/vite-ssr-svelte-streaming/server.js
@@ -82,7 +82,7 @@
     catch (e) {
       vite && vite.ssrFixStacktrace(e)
       console.log(e.stack)
-      res.status(500).end(e.stack)
+      res.status(500).end('Internal Server Error')
     }
   })
 
EOF
@@ -82,7 +82,7 @@
catch (e) {
vite && vite.ssrFixStacktrace(e)
console.log(e.stack)
res.status(500).end(e.stack)
res.status(500).end('Internal Server Error')
}
})

Copilot is powered by AI and may make mistakes. Always verify output.
@harlan-zw harlan-zw marked this pull request as ready for review January 5, 2026 13:39
@coderabbitai

coderabbitai Bot commented Mar 2, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 299 files, which is 149 over the limit of 150.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 624872d1-7c6c-4fe1-aadf-db2b030a4462

📥 Commits

Reviewing files that changed from the base of the PR and between 9864940 and 1f0cee8.

⛔ Files ignored due to path filters (1)
  • examples/vite-ssr-vue-streaming/src/assets/vue.svg is excluded by !**/*.svg
📒 Files selected for processing (299)
  • .claude/.active-plan-903cfee5-14e0-4f83-b09a-243c64e6ab4e
  • .claude/plans/docs-content-improvements.md
  • .claude/session-context.md
  • .github/workflows/release.yml
  • .github/workflows/test.yml
  • .gitignore
  • bench/bundle/last.json
  • bench/bundle/src/schema-org/minimal.ts
  • bench/bundle/src/server/minimal.ts
  • bench/bundle/src/vue-server/minimal.ts
  • bench/ssr-harlanzw-com-e2e.bench.ts
  • bench/ssr-harlanzw-com-e2e.test.ts
  • bench/ssr-harlanzw-no-schema-e2e.bench.ts
  • bench/use-seo-meta-perf.bench.ts
  • docs/0.angular/head/guides/0.get-started/2.migration.md
  • docs/0.angular/schema-org/guides/get-started/0.installation.md
  • docs/0.nuxt/head/guides/0.get-started/1.migration.md
  • docs/0.react/head/guides/0.get-started/1.installation.md
  • docs/0.react/head/guides/0.get-started/2.migration.md
  • docs/0.react/head/guides/0.get-started/migrate-from-react-helmet.md
  • docs/0.react/head/guides/1.core-concepts/5.streaming.md
  • docs/0.react/schema-org/guides/get-started/0.installation.md
  • docs/0.solid-js/head/guides/0.get-started/1.installation.md
  • docs/0.solid-js/head/guides/0.get-started/2.migration.md
  • docs/0.solid-js/head/guides/1.core-concepts/5.streaming.md
  • docs/0.solid-js/schema-org/guides/get-started/0.installation.md
  • docs/0.svelte/head/guides/0.get-started/1.installation.md
  • docs/0.svelte/head/guides/0.get-started/2.migration.md
  • docs/0.svelte/head/guides/1.core-concepts/5.streaming.md
  • docs/0.svelte/schema-org/guides/get-started/0.installation.md
  • docs/0.typescript/head/guides/0.get-started/1.installation.md
  • docs/0.typescript/head/guides/0.get-started/1.migration.md
  • docs/0.typescript/head/guides/1.core-concepts/5.streaming.md
  • docs/0.typescript/schema-org/guides/get-started/0.installation.md
  • docs/0.vue/head/guides/0.get-started/1.installation.md
  • docs/0.vue/head/guides/0.get-started/1.migration.md
  • docs/0.vue/head/guides/1.core-concepts/4.pausing-dom-rendering.md
  • docs/0.vue/head/guides/1.core-concepts/5.streaming.md
  • docs/0.vue/schema-org/guides/0.get-started/0.installation.md
  • docs/head/1.guides/0.get-started/0.overview.md
  • docs/head/1.guides/1.core-concepts/8.dom-event-handling.md
  • docs/head/1.guides/2.advanced/11.extending-unhead.md
  • docs/head/1.guides/2.advanced/7.client-only-tags.md
  • docs/head/1.guides/2.advanced/9.vite-plugin.md
  • docs/head/7.api/0.get-started/overview.md
  • docs/head/7.api/composables/3.use-seo-meta.md
  • docs/head/7.api/composables/6.use-server-head.md
  • docs/head/7.api/hooks/01.init.md
  • docs/head/7.api/hooks/02.entries-updated.md
  • docs/head/7.api/hooks/09.dom-before-render.md
  • docs/head/7.api/hooks/10.dom-render-tag.md
  • docs/head/7.api/hooks/11.dom-rendered.md
  • docs/head/7.api/hooks/12.ssr-before-render.md
  • docs/head/7.api/hooks/13.ssr-render.md
  • docs/head/7.api/hooks/14.ssr-rendered.md
  • docs/schema-org/5.api/0.composables/0.use-schema-org.md
  • docs/schema-org/5.api/9.schema/article.md
  • docs/schema-org/5.api/9.schema/how-to.md
  • docs/schema-org/5.api/9.schema/item-list.md
  • docs/schema-org/5.api/9.schema/job-posting.md
  • docs/schema-org/5.api/9.schema/local-business.md
  • docs/schema-org/5.api/9.schema/organization.md
  • docs/schema-org/5.api/9.schema/software-app.md
  • eslint.config.js
  • examples/angular/package.json
  • examples/vite-ssr-react-streaming/index.html
  • examples/vite-ssr-react-streaming/package.json
  • examples/vite-ssr-react-streaming/playwright.config.ts
  • examples/vite-ssr-react-streaming/server.js
  • examples/vite-ssr-react-streaming/src/App.tsx
  • examples/vite-ssr-react-streaming/src/components/Header.tsx
  • examples/vite-ssr-react-streaming/src/components/HeroBanner.tsx
  • examples/vite-ssr-react-streaming/src/components/Newsletter.tsx
  • examples/vite-ssr-react-streaming/src/components/ProductCard.tsx
  • examples/vite-ssr-react-streaming/src/components/Reviews.tsx
  • examples/vite-ssr-react-streaming/src/components/Sidebar.tsx
  • examples/vite-ssr-react-streaming/src/entry-client.tsx
  • examples/vite-ssr-react-streaming/src/entry-server.tsx
  • examples/vite-ssr-react-streaming/src/global.d.ts
  • examples/vite-ssr-react-streaming/src/pages/AboutPage.tsx
  • examples/vite-ssr-react-streaming/src/pages/HomePage.tsx
  • examples/vite-ssr-react-streaming/src/utils/cache.ts
  • examples/vite-ssr-react-streaming/tests/streaming.spec.ts
  • examples/vite-ssr-react-streaming/tsconfig.json
  • examples/vite-ssr-react-streaming/vite.config.ts
  • examples/vite-ssr-react-ts/package.json
  • examples/vite-ssr-solidjs-streaming/index.html
  • examples/vite-ssr-solidjs-streaming/package.json
  • examples/vite-ssr-solidjs-streaming/playwright.config.ts
  • examples/vite-ssr-solidjs-streaming/server.js
  • examples/vite-ssr-solidjs-streaming/src/App.tsx
  • examples/vite-ssr-solidjs-streaming/src/components/Header.tsx
  • examples/vite-ssr-solidjs-streaming/src/components/HeroBanner.tsx
  • examples/vite-ssr-solidjs-streaming/src/components/Newsletter.tsx
  • examples/vite-ssr-solidjs-streaming/src/components/ProductCard.tsx
  • examples/vite-ssr-solidjs-streaming/src/components/Reviews.tsx
  • examples/vite-ssr-solidjs-streaming/src/components/Sidebar.tsx
  • examples/vite-ssr-solidjs-streaming/src/components/StatsSection.tsx
  • examples/vite-ssr-solidjs-streaming/src/components/TeamSection.tsx
  • examples/vite-ssr-solidjs-streaming/src/entry-client.tsx
  • examples/vite-ssr-solidjs-streaming/src/entry-server.tsx
  • examples/vite-ssr-solidjs-streaming/src/pages/AboutPage.tsx
  • examples/vite-ssr-solidjs-streaming/src/pages/HomePage.tsx
  • examples/vite-ssr-solidjs-streaming/tests/streaming.spec.ts
  • examples/vite-ssr-solidjs-streaming/tsconfig.json
  • examples/vite-ssr-solidjs-streaming/vite.config.ts
  • examples/vite-ssr-svelte-streaming/index.html
  • examples/vite-ssr-svelte-streaming/package.json
  • examples/vite-ssr-svelte-streaming/playwright.config.ts
  • examples/vite-ssr-svelte-streaming/server.js
  • examples/vite-ssr-svelte-streaming/src/App.svelte
  • examples/vite-ssr-svelte-streaming/src/components/Header.svelte
  • examples/vite-ssr-svelte-streaming/src/components/HeroBanner.svelte
  • examples/vite-ssr-svelte-streaming/src/components/Newsletter.svelte
  • examples/vite-ssr-svelte-streaming/src/components/ProductCard.svelte
  • examples/vite-ssr-svelte-streaming/src/components/Reviews.svelte
  • examples/vite-ssr-svelte-streaming/src/components/Sidebar.svelte
  • examples/vite-ssr-svelte-streaming/src/components/StatsSection.svelte
  • examples/vite-ssr-svelte-streaming/src/components/TeamSection.svelte
  • examples/vite-ssr-svelte-streaming/src/entry-client.ts
  • examples/vite-ssr-svelte-streaming/src/entry-server.ts
  • examples/vite-ssr-svelte-streaming/src/pages/AboutPage.svelte
  • examples/vite-ssr-svelte-streaming/src/pages/HomePage.svelte
  • examples/vite-ssr-svelte-streaming/src/vite-env.d.ts
  • examples/vite-ssr-svelte-streaming/svelte.config.js
  • examples/vite-ssr-svelte-streaming/tests/streaming.spec.ts
  • examples/vite-ssr-svelte-streaming/tsconfig.json
  • examples/vite-ssr-svelte-streaming/tsconfig.node.json
  • examples/vite-ssr-svelte-streaming/vite.config.ts
  • examples/vite-ssr-svelte/package.json
  • examples/vite-ssr-ts/package.json
  • examples/vite-ssr-vue-prerender/package.json
  • examples/vite-ssr-vue-prerender/src/entry-server.js
  • examples/vite-ssr-vue-streaming/head-stream.js
  • examples/vite-ssr-vue-streaming/index.html
  • examples/vite-ssr-vue-streaming/package.json
  • examples/vite-ssr-vue-streaming/playwright.config.ts
  • examples/vite-ssr-vue-streaming/prerender.js
  • examples/vite-ssr-vue-streaming/server.js
  • examples/vite-ssr-vue-streaming/src/App.vue
  • examples/vite-ssr-vue-streaming/src/components/HeadStream.vue
  • examples/vite-ssr-vue-streaming/src/components/Header.vue
  • examples/vite-ssr-vue-streaming/src/components/HelloWorld.vue
  • examples/vite-ssr-vue-streaming/src/components/HeroBanner.vue
  • examples/vite-ssr-vue-streaming/src/components/Newsletter.vue
  • examples/vite-ssr-vue-streaming/src/components/ProductCard.vue
  • examples/vite-ssr-vue-streaming/src/components/Reviews.vue
  • examples/vite-ssr-vue-streaming/src/components/Sidebar.vue
  • examples/vite-ssr-vue-streaming/src/components/SlowComponent.vue
  • examples/vite-ssr-vue-streaming/src/components/SlowComponentThree.vue
  • examples/vite-ssr-vue-streaming/src/components/SlowComponentTwo.vue
  • examples/vite-ssr-vue-streaming/src/components/StatsSection.vue
  • examples/vite-ssr-vue-streaming/src/components/TeamSection.vue
  • examples/vite-ssr-vue-streaming/src/entry-client.js
  • examples/vite-ssr-vue-streaming/src/entry-client.ts
  • examples/vite-ssr-vue-streaming/src/entry-server.js
  • examples/vite-ssr-vue-streaming/src/entry-server.ts
  • examples/vite-ssr-vue-streaming/src/main.js
  • examples/vite-ssr-vue-streaming/src/main.ts
  • examples/vite-ssr-vue-streaming/src/pages/AboutPage.vue
  • examples/vite-ssr-vue-streaming/src/pages/HomePage.vue
  • examples/vite-ssr-vue-streaming/src/router.js
  • examples/vite-ssr-vue-streaming/src/router.ts
  • examples/vite-ssr-vue-streaming/tests/streaming.spec.ts
  • examples/vite-ssr-vue-streaming/tsconfig.json
  • examples/vite-ssr-vue-streaming/vite.config.js
  • examples/vite-ssr-vue-streaming/vite.config.noexternal.js
  • examples/vite-ssr-vue-streaming/vite.config.ts
  • examples/vite-ssr-vue/package.json
  • package.json
  • packages-aliased/dom/package.json
  • packages-aliased/schema/package.json
  • packages-aliased/shared/package.json
  • packages-aliased/ssr/package.json
  • packages/addons/package.json
  • packages/addons/src/unplugin/TreeshakeServerComposables.ts
  • packages/addons/src/unplugin/UseSeoMetaTransform.ts
  • packages/addons/test/treeshakeServerComposables.test.ts
  • packages/addons/test/useSeoMetaTransform.test.ts
  • packages/angular/client/src/client.ts
  • packages/angular/package.json
  • packages/angular/server/src/ssr.service.ts
  • packages/angular/vitest.config.ts
  • packages/react/build.config.ts
  • packages/react/package.json
  • packages/react/src/client.ts
  • packages/react/src/composables.ts
  • packages/react/src/server.ts
  • packages/react/src/stream/client.ts
  • packages/react/src/stream/server.ts
  • packages/react/src/stream/vite.ts
  • packages/react/test/ReactiveTitle.test.tsx
  • packages/react/test/SimpleHead.test.tsx
  • packages/react/test/SimpleHeadSSR.test.tsx
  • packages/react/test/e2e-streaming.test.ts
  • packages/react/test/ssr-useHead.test.tsx
  • packages/react/test/streaming.test.tsx
  • packages/react/test/useHead.test.tsx
  • packages/react/test/useSeoMeta.test.tsx
  • packages/react/test/vite-plugin.test.ts
  • packages/react/vitest.config.ts
  • packages/schema-org/package.json
  • packages/schema-org/src/core/graph.ts
  • packages/schema-org/src/core/resolve.ts
  • packages/schema-org/src/core/util.ts
  • packages/schema-org/src/index.ts
  • packages/schema-org/src/nodes/Organization/index.ts
  • packages/schema-org/src/nodes/Question/index.ts
  • packages/schema-org/src/plugin.ts
  • packages/schema-org/src/runtime.ts
  • packages/schema-org/src/types.ts
  • packages/schema-org/src/vue/index.ts
  • packages/schema-org/src/vue/runtime/components.ts
  • packages/schema-org/src/vue/runtime/composables.ts
  • packages/schema-org/test/bench/ssr-e2e.bench.ts
  • packages/schema-org/test/e2e/basic.test.ts
  • packages/schema-org/test/e2e/no-plugin.test.ts
  • packages/schema-org/test/index.ts
  • packages/schema-org/test/ssr/dupes.test.ts
  • packages/schema-org/test/ssr/i18n.test.ts
  • packages/schema-org/test/ssr/ids.test.ts
  • packages/schema-org/test/ssr/prototype-pollution.test.ts
  • packages/schema-org/test/ssr/xss.test.ts
  • packages/schema-org/test/vue/vue.test.ts
  • packages/schema-org/vitest.config.ts
  • packages/solid-js/build.config.ts
  • packages/solid-js/package.json
  • packages/solid-js/src/client.ts
  • packages/solid-js/src/composables.ts
  • packages/solid-js/src/server.ts
  • packages/solid-js/src/stream/client.ts
  • packages/solid-js/src/stream/server.ts
  • packages/solid-js/src/stream/vite.ts
  • packages/solid-js/test/e2e-streaming.test.ts
  • packages/solid-js/test/streaming.test.ts
  • packages/solid-js/test/vite-plugin.test.ts
  • packages/solid-js/vitest.config.ts
  • packages/svelte/build.config.ts
  • packages/svelte/package.json
  • packages/svelte/src/client.ts
  • packages/svelte/src/composables.ts
  • packages/svelte/src/context.ts
  • packages/svelte/src/server.ts
  • packages/svelte/src/stream/client.ts
  • packages/svelte/src/stream/server.ts
  • packages/svelte/src/stream/vite.ts
  • packages/svelte/test/dom/counter.test.ts
  • packages/svelte/test/e2e-streaming.test.ts
  • packages/svelte/test/streaming.test.ts
  • packages/svelte/test/vite-plugin.test.ts
  • packages/svelte/vitest.config.ts
  • packages/unhead/README.md
  • packages/unhead/build.config.ts
  • packages/unhead/legacy.d.ts
  • packages/unhead/package.json
  • packages/unhead/src/client/createHead.ts
  • packages/unhead/src/client/index.ts
  • packages/unhead/src/client/renderDOMHead.ts
  • packages/unhead/src/composables.ts
  • packages/unhead/src/index.ts
  • packages/unhead/src/legacy.ts
  • packages/unhead/src/parser/index.ts
  • packages/unhead/src/plugins/aliasSorting.ts
  • packages/unhead/src/plugins/deprecations.ts
  • packages/unhead/src/plugins/flatMeta.ts
  • packages/unhead/src/plugins/index.ts
  • packages/unhead/src/plugins/inferSeoMetaPlugin.ts
  • packages/unhead/src/plugins/safe.ts
  • packages/unhead/src/plugins/templateParams.ts
  • packages/unhead/src/scripts/index.ts
  • packages/unhead/src/scripts/types.ts
  • packages/unhead/src/scripts/useScript.ts
  • packages/unhead/src/server/createHead.ts
  • packages/unhead/src/server/index.ts
  • packages/unhead/src/server/renderSSRHead.ts
  • packages/unhead/src/server/sort.ts
  • packages/unhead/src/server/transformHtmlTemplate.ts
  • packages/unhead/src/server/util/extractUnheadInputFromHtml.ts
  • packages/unhead/src/server/util/index.ts
  • packages/unhead/src/server/util/propsToString.ts
  • packages/unhead/src/server/util/tagToString.ts
  • packages/unhead/src/stream/client.ts
  • packages/unhead/src/stream/iife.ts
  • packages/unhead/src/stream/server.ts
  • packages/unhead/src/stream/vite.ts
  • packages/unhead/src/types/head.ts
  • packages/unhead/src/types/hooks.ts
  • packages/unhead/src/types/plugins.ts
  • packages/unhead/src/types/safeSchema.ts
  • packages/unhead/src/types/schema/attributes/global.ts
  • packages/unhead/src/types/schema/base.ts
  • packages/unhead/src/types/schema/bodyAttributes.ts
  • packages/unhead/src/types/schema/head.ts
  • packages/unhead/src/types/schema/index.ts
  • packages/unhead/src/types/schema/link.ts
  • packages/unhead/src/types/schema/meta.ts
  • packages/unhead/src/types/schema/metaFlat.ts
  • packages/unhead/src/types/schema/noscript.ts
  • packages/unhead/src/types/schema/script.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch v3

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.

@harlan-zw harlan-zw merged commit 1f0cee8 into main Mar 10, 2026
4 of 5 checks passed
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.

2 participants