vinext 0.0.20 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -12
- package/dist/index.js.map +1 -1
- package/dist/server/app-dev-server.d.ts.map +1 -1
- package/dist/server/app-dev-server.js +70 -3
- package/dist/server/app-dev-server.js.map +1 -1
- package/dist/server/middleware.d.ts.map +1 -1
- package/dist/server/middleware.js +13 -4
- package/dist/server/middleware.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-dev-server.d.ts","sourceRoot":"","sources":["../../src/server/app-dev-server.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAKtF;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,WAAW,EAAE,WAAW,EAAE,CAAC;QAC3B,UAAU,EAAE,WAAW,EAAE,CAAC;QAC1B,QAAQ,EAAE,WAAW,EAAE,CAAC;KACzB,CAAC;IACF,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,4GAA4G;IAC5G,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,uGAAuG;IACvG,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,QAAQ,EAAE,EAClB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,EAC9B,cAAc,CAAC,EAAE,iBAAiB,EAAE,EACpC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,EAC/B,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,OAAO,EACvB,MAAM,CAAC,EAAE,eAAe,GACvB,MAAM,
|
|
1
|
+
{"version":3,"file":"app-dev-server.d.ts","sourceRoot":"","sources":["../../src/server/app-dev-server.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAKtF;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,WAAW,EAAE,WAAW,EAAE,CAAC;QAC3B,UAAU,EAAE,WAAW,EAAE,CAAC;QAC1B,QAAQ,EAAE,WAAW,EAAE,CAAC;KACzB,CAAC;IACF,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,4GAA4G;IAC5G,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,uGAAuG;IACvG,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,QAAQ,EAAE,EAClB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,EAC9B,cAAc,CAAC,EAAE,iBAAiB,EAAE,EACpC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,EAC/B,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,OAAO,EACvB,MAAM,CAAC,EAAE,eAAe,GACvB,MAAM,CAurER;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAibzC;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CA4S7C"}
|
|
@@ -294,6 +294,48 @@ function rscOnError(error) {
|
|
|
294
294
|
if (error && typeof error === "object" && "digest" in error) {
|
|
295
295
|
return String(error.digest);
|
|
296
296
|
}
|
|
297
|
+
|
|
298
|
+
// In dev, detect the "Only plain objects" RSC serialization error and emit
|
|
299
|
+
// an actionable hint. This error occurs when a Server Component passes a
|
|
300
|
+
// class instance, ES module namespace object, or null-prototype object as a
|
|
301
|
+
// prop to a Client Component.
|
|
302
|
+
//
|
|
303
|
+
// Root cause: Vite bundles modules as true ESM (module namespace objects
|
|
304
|
+
// have a null-like internal slot), while Next.js's webpack build produces
|
|
305
|
+
// plain CJS-wrapped objects with __esModule:true. React's RSC serializer
|
|
306
|
+
// accepts the latter as plain objects but rejects the former — which means
|
|
307
|
+
// code that accidentally passes "import * as X" works in webpack/Next.js
|
|
308
|
+
// but correctly fails in vinext.
|
|
309
|
+
//
|
|
310
|
+
// Common triggers:
|
|
311
|
+
// - "import * as utils from './utils'" passed as a prop
|
|
312
|
+
// - class instances (new Foo()) passed as props
|
|
313
|
+
// - Date / Map / Set instances passed as props
|
|
314
|
+
// - Objects with Object.create(null) (null prototype)
|
|
315
|
+
if (
|
|
316
|
+
process.env.NODE_ENV !== "production" &&
|
|
317
|
+
error instanceof Error &&
|
|
318
|
+
error.message.includes("Only plain objects, and a few built-ins, can be passed to Client Components")
|
|
319
|
+
) {
|
|
320
|
+
console.error(
|
|
321
|
+
"[vinext] RSC serialization error: a non-plain object was passed from a Server Component to a Client Component.\\n" +
|
|
322
|
+
"\\n" +
|
|
323
|
+
"Common causes:\\n" +
|
|
324
|
+
" * Passing a module namespace (import * as X) directly as a prop.\\n" +
|
|
325
|
+
" Unlike Next.js (webpack), Vite produces real ESM module namespace objects\\n" +
|
|
326
|
+
" which are not serializable. Fix: pass individual values instead,\\n" +
|
|
327
|
+
" e.g. <Comp value={module.value} />\\n" +
|
|
328
|
+
" * Passing a class instance (new Foo()) as a prop.\\n" +
|
|
329
|
+
" Fix: convert to a plain object, e.g. { id: foo.id, name: foo.name }\\n" +
|
|
330
|
+
" * Passing a Date, Map, or Set. Use .toISOString(), [...map.entries()], etc.\\n" +
|
|
331
|
+
" * Passing Object.create(null). Use { ...obj } to restore a prototype.\\n" +
|
|
332
|
+
"\\n" +
|
|
333
|
+
"Original error:",
|
|
334
|
+
error.message,
|
|
335
|
+
);
|
|
336
|
+
return undefined;
|
|
337
|
+
}
|
|
338
|
+
|
|
297
339
|
// In production, generate a digest hash for non-navigation errors
|
|
298
340
|
if (process.env.NODE_ENV === "production" && error) {
|
|
299
341
|
const msg = error instanceof Error ? error.message : String(error);
|
|
@@ -2257,6 +2299,20 @@ async function collectStreamChunks(stream) {
|
|
|
2257
2299
|
return chunks;
|
|
2258
2300
|
}
|
|
2259
2301
|
|
|
2302
|
+
// React 19 dev-mode workaround (see VinextFlightRoot in handleSsr):
|
|
2303
|
+
//
|
|
2304
|
+
// In dev, Flight error decoding in react-server-dom-webpack/client.edge
|
|
2305
|
+
// can hit resolveErrorDev() which (via React's dev error stack capture)
|
|
2306
|
+
// expects a non-null hooks dispatcher.
|
|
2307
|
+
//
|
|
2308
|
+
// Vinext previously called createFromReadableStream() outside of any React render.
|
|
2309
|
+
// When an RSC stream contains an error, dev-mode decoding could crash with:
|
|
2310
|
+
// - "Invalid hook call"
|
|
2311
|
+
// - "Cannot read properties of null (reading 'useContext')"
|
|
2312
|
+
//
|
|
2313
|
+
// Fix: call createFromReadableStream() lazily inside a React component render.
|
|
2314
|
+
// This mirrors Next.js behavior and ensures the dispatcher is set.
|
|
2315
|
+
|
|
2260
2316
|
/**
|
|
2261
2317
|
* Create a TransformStream that appends RSC chunks as inline <script> tags
|
|
2262
2318
|
* to the HTML stream. This allows progressive hydration — the browser receives
|
|
@@ -2391,7 +2447,18 @@ export async function handleSsr(rscStream, navContext, fontData) {
|
|
|
2391
2447
|
// immediately in the HTML shell, then stream in resolved content as RSC
|
|
2392
2448
|
// chunks arrive. Awaiting here would block until all async server components
|
|
2393
2449
|
// complete, collapsing the streaming behavior.
|
|
2394
|
-
|
|
2450
|
+
// Lazily create the Flight root inside render so React's hook dispatcher is set
|
|
2451
|
+
// (avoids React 19 dev-mode resolveErrorDev() crash). VinextFlightRoot returns
|
|
2452
|
+
// a thenable (not a ReactNode), which React 19 consumes via its internal
|
|
2453
|
+
// thenable-as-child suspend/resume behavior. This matches Next.js's approach.
|
|
2454
|
+
let flightRoot;
|
|
2455
|
+
function VinextFlightRoot() {
|
|
2456
|
+
if (!flightRoot) {
|
|
2457
|
+
flightRoot = createFromReadableStream(ssrStream);
|
|
2458
|
+
}
|
|
2459
|
+
return flightRoot;
|
|
2460
|
+
}
|
|
2461
|
+
const root = _ssrCE(VinextFlightRoot);
|
|
2395
2462
|
|
|
2396
2463
|
// Wrap with ServerInsertedHTMLContext.Provider so libraries that use
|
|
2397
2464
|
// useContext(ServerInsertedHTMLContext) (Apollo Client, styled-components,
|
|
@@ -2446,11 +2513,11 @@ export async function handleSsr(rscStream, navContext, fontData) {
|
|
|
2446
2513
|
const insertedElements = flushServerInsertedHTML();
|
|
2447
2514
|
|
|
2448
2515
|
// Render the inserted elements to HTML strings
|
|
2449
|
-
const {
|
|
2516
|
+
const { Fragment } = await import("react");
|
|
2450
2517
|
let insertedHTML = "";
|
|
2451
2518
|
for (const el of insertedElements) {
|
|
2452
2519
|
try {
|
|
2453
|
-
insertedHTML += renderToStaticMarkup(
|
|
2520
|
+
insertedHTML += renderToStaticMarkup(_ssrCE(Fragment, null, el));
|
|
2454
2521
|
} catch {
|
|
2455
2522
|
// Skip elements that can't be rendered
|
|
2456
2523
|
}
|