@rangojs/router 0.0.0-experimental.preview.1774284415 → 0.0.0-experimental.preview.1774295099

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.
@@ -1745,7 +1745,7 @@ import { resolve } from "node:path";
1745
1745
  // package.json
1746
1746
  var package_default = {
1747
1747
  name: "@rangojs/router",
1748
- version: "0.0.0-experimental.preview.1774284415",
1748
+ version: "0.0.0-experimental.preview.1774295099",
1749
1749
  description: "Django-inspired RSC router with composable URL patterns",
1750
1750
  keywords: [
1751
1751
  "react",
@@ -2895,7 +2895,8 @@ function performanceTracksPlugin() {
2895
2895
  const flushBrowserDoneIfReady = (debugId, session) => {
2896
2896
  if (!session.ended || !session.ready || session.browserDoneSent) return;
2897
2897
  session.browserDoneSent = true;
2898
- sendBatch(debugId, [], true);
2898
+ const chunks = session.pendingClientChunks.splice(0);
2899
+ sendBatch(debugId, chunks, true);
2899
2900
  };
2900
2901
  const closeRuntimeWaiters = (session) => {
2901
2902
  const waiters = session.waiters.splice(0);
@@ -2944,20 +2945,7 @@ function performanceTracksPlugin() {
2944
2945
  return;
2945
2946
  }
2946
2947
  const chunk = await readRequestBody(req);
2947
- if (chunk.byteLength <= 3) {
2948
- console.log(
2949
- "[perf-tracks] writable: chunk size:",
2950
- chunk.byteLength,
2951
- "for",
2952
- debugId.slice(0, 8),
2953
- session.ready ? "(sent)" : "(buffered)"
2954
- );
2955
- }
2956
- if (session.ready) {
2957
- sendChunk(debugId, chunk);
2958
- } else {
2959
- session.pendingClientChunks.push(chunk);
2960
- }
2948
+ session.pendingClientChunks.push(chunk);
2961
2949
  res.statusCode = 204;
2962
2950
  res.end();
2963
2951
  return;
@@ -3047,13 +3035,7 @@ function performanceTracksPlugin() {
3047
3035
  "ended:",
3048
3036
  ended
3049
3037
  );
3050
- if (pending > 0 || ended) {
3051
- const chunks = session.pendingClientChunks.splice(0);
3052
- if (ended) {
3053
- session.browserDoneSent = true;
3054
- }
3055
- sendBatch(payload.i, chunks, ended);
3056
- }
3038
+ flushBrowserDoneIfReady(payload.i, session);
3057
3039
  cleanupIfSettled(payload.i, session);
3058
3040
  });
3059
3041
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rangojs/router",
3
- "version": "0.0.0-experimental.preview.1774284415",
3
+ "version": "0.0.0-experimental.preview.1774295099",
4
4
  "description": "Django-inspired RSC router with composable URL patterns",
5
5
  "keywords": [
6
6
  "react",
@@ -141,24 +141,15 @@ export async function initBrowserApp(
141
141
  initialTheme,
142
142
  } = options;
143
143
 
144
- // Dev-only: create debug channel for React Performance Tracks.
145
- // The debugId was injected into the HTML bootstrap by the SSR handler.
146
- // The client sends a "ready" signal so the server flushes buffered data.
147
- const ssrDebugId = (globalThis as any).__RANGO_DEBUG_ID__ as
148
- | string
149
- | undefined;
150
- const ssrDebugChannel =
151
- ssrDebugId && (import.meta as any).hot
152
- ? createClientDebugChannel(ssrDebugId)
153
- : undefined;
154
-
155
144
  // Load initial payload from SSR-injected __FLIGHT_DATA__
156
- const initialPayload = await deps.createFromReadableStream<RscPayload>(
157
- rscStream,
158
- ssrDebugChannel
159
- ? { debugChannel: ssrDebugChannel, findSourceMapURL }
160
- : undefined,
161
- );
145
+ // Note: debug channel is NOT used for hydration. The WS transport is
146
+ // unreliable during initial page load (JS loads after server finishes
147
+ // rendering, so the "ready" signal arrives too late and chunks are dropped).
148
+ // If createFromReadableStream hangs on a stalled debug stream, the entire
149
+ // app never initializes — blocking all subsequent SPA navigations.
150
+ // Server Component tracks are available for SPA navigations instead.
151
+ const initialPayload =
152
+ await deps.createFromReadableStream<RscPayload>(rscStream);
162
153
 
163
154
  // Extract themeConfig and initialTheme from payload if not explicitly provided
164
155
  // This allows virtual entries to work without importing the router
@@ -316,8 +316,9 @@ export function performanceTracksPlugin(): Plugin {
316
316
  ) => {
317
317
  if (!session.ended || !session.ready || session.browserDoneSent) return;
318
318
  session.browserDoneSent = true;
319
- // Send empty batch with done flag
320
- sendBatch(debugId, [], true);
319
+ // Send ALL buffered chunks + done in one WS message
320
+ const chunks = session.pendingClientChunks.splice(0);
321
+ sendBatch(debugId, chunks, true);
321
322
  };
322
323
 
323
324
  const closeRuntimeWaiters = (session: DebugSession) => {
@@ -378,21 +379,10 @@ export function performanceTracksPlugin(): Plugin {
378
379
  return;
379
380
  }
380
381
 
382
+ // Always buffer — we flush everything as one batch when "done" arrives.
383
+ // Individual hot.send calls during request handling are unreliable.
381
384
  const chunk = await readRequestBody(req);
382
- if (chunk.byteLength <= 3) {
383
- console.log(
384
- "[perf-tracks] writable: chunk size:",
385
- chunk.byteLength,
386
- "for",
387
- debugId.slice(0, 8),
388
- session.ready ? "(sent)" : "(buffered)",
389
- );
390
- }
391
- if (session.ready) {
392
- sendChunk(debugId, chunk);
393
- } else {
394
- session.pendingClientChunks.push(chunk);
395
- }
385
+ session.pendingClientChunks.push(chunk);
396
386
  res.statusCode = 204;
397
387
  res.end();
398
388
  return;
@@ -488,7 +478,9 @@ export function performanceTracksPlugin(): Plugin {
488
478
  return;
489
479
  }
490
480
 
491
- // Ready signal — flush all pending chunks as one batch
481
+ // Ready signal — mark session as ready.
482
+ // Chunks are NOT flushed here. We wait for "done" from the server
483
+ // and send everything in one reliable batch.
492
484
  session.ready = true;
493
485
  const pending = session.pendingClientChunks.length;
494
486
  const ended = session.ended;
@@ -500,14 +492,8 @@ export function performanceTracksPlugin(): Plugin {
500
492
  "ended:",
501
493
  ended,
502
494
  );
503
- if (pending > 0 || ended) {
504
- // Send everything in one WS message
505
- const chunks = session.pendingClientChunks.splice(0);
506
- if (ended) {
507
- session.browserDoneSent = true;
508
- }
509
- sendBatch(payload.i, chunks, ended);
510
- }
495
+ // If server already finished, flush now
496
+ flushBrowserDoneIfReady(payload.i, session);
511
497
  cleanupIfSettled(payload.i, session);
512
498
  });
513
499
  },