@nestjs-ssr/react 0.2.6 → 0.3.0
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/cli/init.js +35 -72
- package/dist/cli/init.mjs +35 -72
- package/dist/client.d.mts +55 -304
- package/dist/client.d.ts +55 -304
- package/dist/client.js +360 -13
- package/dist/client.mjs +336 -5
- package/dist/{index-BMdluY1g.d.mts → index-BzOLOiIZ.d.ts} +207 -44
- package/dist/{index-rl0S5kqW.d.ts → index-DdE--mA2.d.mts} +207 -44
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +646 -317
- package/dist/index.mjs +640 -319
- package/dist/render/index.d.mts +2 -2
- package/dist/render/index.d.ts +2 -2
- package/dist/render/index.js +610 -315
- package/dist/render/index.mjs +610 -315
- package/dist/{render-response.interface-Dc-Kwb09.d.mts → render-response.interface-CxbuKGnV.d.mts} +57 -1
- package/dist/{render-response.interface-Dc-Kwb09.d.ts → render-response.interface-CxbuKGnV.d.ts} +57 -1
- package/dist/templates/entry-client.tsx +21 -5
- package/dist/templates/entry-server.tsx +28 -6
- package/dist/use-page-context-05ODF4zW.d.ts +281 -0
- package/dist/use-page-context-CGT9woWe.d.mts +281 -0
- package/package.json +1 -1
- package/src/global.d.ts +11 -0
- package/src/templates/entry-client.tsx +21 -5
- package/src/templates/entry-server.tsx +28 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DynamicModule, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
|
|
2
2
|
import { ComponentType } from 'react';
|
|
3
|
-
import { H as HeadData } from './render-response.interface-
|
|
3
|
+
import { H as HeadData, R as RenderContext } from './render-response.interface-CxbuKGnV.mjs';
|
|
4
4
|
import { ViteDevServer } from 'vite';
|
|
5
5
|
import { Response } from 'express';
|
|
6
6
|
import { Reflector } from '@nestjs/core';
|
|
@@ -20,23 +20,14 @@ interface ErrorPageDevelopmentProps$1 {
|
|
|
20
20
|
phase: 'shell' | 'streaming';
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
* Vite
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
* Vite configuration options
|
|
23
|
+
* Vite configuration options for development
|
|
24
|
+
*
|
|
25
|
+
* In development, NestJS proxies requests to an external Vite dev server
|
|
26
|
+
* which provides HMR (Hot Module Replacement) for React components.
|
|
28
27
|
*/
|
|
29
28
|
interface ViteConfig {
|
|
30
29
|
/**
|
|
31
|
-
* Vite
|
|
32
|
-
* - 'embedded': Vite runs inside NestJS (no HMR, simplest setup) - DEFAULT
|
|
33
|
-
* - 'proxy': External Vite server with HMR support (requires running `vite` separately)
|
|
34
|
-
*
|
|
35
|
-
* @default 'embedded'
|
|
36
|
-
*/
|
|
37
|
-
mode?: ViteMode;
|
|
38
|
-
/**
|
|
39
|
-
* Port where external Vite dev server is running (proxy mode only)
|
|
30
|
+
* Port where Vite dev server is running
|
|
40
31
|
*
|
|
41
32
|
* @default 5173
|
|
42
33
|
*/
|
|
@@ -48,8 +39,18 @@ interface ViteConfig {
|
|
|
48
39
|
interface RenderConfig {
|
|
49
40
|
/**
|
|
50
41
|
* SSR rendering mode
|
|
51
|
-
* - 'string': Traditional renderToString
|
|
52
|
-
* - 'stream': Modern renderToPipeableStream
|
|
42
|
+
* - 'string': Traditional renderToString - atomic responses, proper HTTP status codes (default)
|
|
43
|
+
* - 'stream': Modern renderToPipeableStream - better TTFB, Suspense support (advanced)
|
|
44
|
+
*
|
|
45
|
+
* String mode is recommended for most applications because:
|
|
46
|
+
* - Atomic responses: either complete HTML or error page, never partial
|
|
47
|
+
* - Proper HTTP status codes: 200 for success, 500 for errors
|
|
48
|
+
* - Simpler error handling and debugging
|
|
49
|
+
*
|
|
50
|
+
* Use stream mode only when you need:
|
|
51
|
+
* - Better Time to First Byte (TTFB) for performance-critical pages
|
|
52
|
+
* - Progressive rendering with Suspense boundaries
|
|
53
|
+
* - And you understand the trade-offs (errors after shell may result in HTTP 200 with partial content)
|
|
53
54
|
*
|
|
54
55
|
* @default 'string'
|
|
55
56
|
*/
|
|
@@ -64,20 +65,17 @@ interface RenderConfig {
|
|
|
64
65
|
/**
|
|
65
66
|
* Vite configuration for development
|
|
66
67
|
*
|
|
68
|
+
* In development, run Vite separately (`pnpm dev:vite`) and NestJS will
|
|
69
|
+
* proxy requests to it. This enables HMR for React components.
|
|
70
|
+
*
|
|
67
71
|
* @example
|
|
68
72
|
* ```typescript
|
|
69
|
-
* //
|
|
70
|
-
*
|
|
71
|
-
* imports: [RenderModule],
|
|
72
|
-
* })
|
|
73
|
+
* // Default port 5173
|
|
74
|
+
* RenderModule.forRoot()
|
|
73
75
|
*
|
|
74
|
-
* //
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* RenderModule.forRoot({
|
|
78
|
-
* vite: { mode: 'proxy', port: 5173 }
|
|
79
|
-
* })
|
|
80
|
-
* ],
|
|
76
|
+
* // Custom Vite port
|
|
77
|
+
* RenderModule.forRoot({
|
|
78
|
+
* vite: { port: 3001 }
|
|
81
79
|
* })
|
|
82
80
|
* ```
|
|
83
81
|
*/
|
|
@@ -191,6 +189,25 @@ interface TemplateParts {
|
|
|
191
189
|
htmlEnd: string;
|
|
192
190
|
}
|
|
193
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Response format for segment rendering (client-side navigation).
|
|
194
|
+
* Returned when a GET request includes the X-Current-Layouts header.
|
|
195
|
+
*/
|
|
196
|
+
interface SegmentResponse {
|
|
197
|
+
/** The rendered HTML for the segment (content below swapTarget layout) */
|
|
198
|
+
html: string;
|
|
199
|
+
/** Head metadata to update (title, description, etc.) */
|
|
200
|
+
head?: HeadData;
|
|
201
|
+
/** Component props for hydration */
|
|
202
|
+
props: any;
|
|
203
|
+
/** Which outlet to swap (the deepest common layout). Null if no common ancestor. */
|
|
204
|
+
swapTarget: string | null;
|
|
205
|
+
/** Component name for resolving in module registry during hydration */
|
|
206
|
+
componentName: string;
|
|
207
|
+
/** Page context for updating hooks (path, params, query, etc.) */
|
|
208
|
+
context?: RenderContext;
|
|
209
|
+
}
|
|
210
|
+
|
|
194
211
|
declare class RenderModule {
|
|
195
212
|
/**
|
|
196
213
|
* Configure the render module
|
|
@@ -200,17 +217,17 @@ declare class RenderModule {
|
|
|
200
217
|
*
|
|
201
218
|
* @example
|
|
202
219
|
* ```ts
|
|
203
|
-
* // Zero config - uses
|
|
220
|
+
* // Zero config - uses string mode (default, recommended)
|
|
204
221
|
* RenderModule.forRoot()
|
|
205
222
|
*
|
|
206
|
-
* //
|
|
207
|
-
* RenderModule.forRoot({ mode: 'stream' })
|
|
208
|
-
*
|
|
209
|
-
* // Enable HMR with proxy mode
|
|
223
|
+
* // Custom Vite port
|
|
210
224
|
* RenderModule.forRoot({
|
|
211
|
-
* vite: {
|
|
225
|
+
* vite: { port: 3001 }
|
|
212
226
|
* })
|
|
213
227
|
*
|
|
228
|
+
* // Enable streaming SSR (advanced - see mode docs for trade-offs)
|
|
229
|
+
* RenderModule.forRoot({ mode: 'stream' })
|
|
230
|
+
*
|
|
214
231
|
* // Custom error pages
|
|
215
232
|
* RenderModule.forRoot({
|
|
216
233
|
* errorPageDevelopment: DevErrorPage,
|
|
@@ -327,6 +344,47 @@ declare class TemplateParserService {
|
|
|
327
344
|
private buildTag;
|
|
328
345
|
}
|
|
329
346
|
|
|
347
|
+
interface ViteManifest$1 {
|
|
348
|
+
[key: string]: {
|
|
349
|
+
file: string;
|
|
350
|
+
src?: string;
|
|
351
|
+
isEntry?: boolean;
|
|
352
|
+
imports?: string[];
|
|
353
|
+
css?: string[];
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
interface StringRenderContext {
|
|
357
|
+
template: string;
|
|
358
|
+
vite: ViteDevServer | null;
|
|
359
|
+
manifest: ViteManifest$1 | null;
|
|
360
|
+
serverManifest: ViteManifest$1 | null;
|
|
361
|
+
entryServerPath: string;
|
|
362
|
+
isDevelopment: boolean;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* String-based SSR renderer using React's renderToString
|
|
366
|
+
*
|
|
367
|
+
* This is the default renderer that provides:
|
|
368
|
+
* - Atomic responses (complete HTML or error page)
|
|
369
|
+
* - Proper HTTP status codes
|
|
370
|
+
* - Simple error handling
|
|
371
|
+
* - Easy debugging
|
|
372
|
+
*/
|
|
373
|
+
declare class StringRenderer {
|
|
374
|
+
private readonly templateParser;
|
|
375
|
+
private readonly logger;
|
|
376
|
+
constructor(templateParser: TemplateParserService);
|
|
377
|
+
/**
|
|
378
|
+
* Render a React component to a complete HTML string
|
|
379
|
+
*/
|
|
380
|
+
render(viewComponent: any, data: any, context: StringRenderContext, head?: HeadData): Promise<string>;
|
|
381
|
+
/**
|
|
382
|
+
* Render a segment for client-side navigation.
|
|
383
|
+
* Returns just the HTML and metadata without the full page template.
|
|
384
|
+
*/
|
|
385
|
+
renderSegment(viewComponent: any, data: any, context: StringRenderContext, swapTarget: string, head?: HeadData): Promise<SegmentResponse>;
|
|
386
|
+
}
|
|
387
|
+
|
|
330
388
|
/**
|
|
331
389
|
* Error handling strategies for streaming SSR
|
|
332
390
|
*
|
|
@@ -358,11 +416,86 @@ declare class StreamingErrorHandler {
|
|
|
358
416
|
* Render production error page using React component
|
|
359
417
|
*/
|
|
360
418
|
private renderProductionErrorPage;
|
|
419
|
+
/**
|
|
420
|
+
* Render inline error overlay for when headers are already sent
|
|
421
|
+
* This gets injected into the stream to show a visible error UI
|
|
422
|
+
*/
|
|
423
|
+
private renderInlineErrorOverlay;
|
|
361
424
|
}
|
|
362
425
|
|
|
363
|
-
|
|
426
|
+
interface ViteManifest {
|
|
427
|
+
[key: string]: {
|
|
428
|
+
file: string;
|
|
429
|
+
src?: string;
|
|
430
|
+
isEntry?: boolean;
|
|
431
|
+
imports?: string[];
|
|
432
|
+
css?: string[];
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
interface StreamRenderContext {
|
|
436
|
+
template: string;
|
|
437
|
+
vite: ViteDevServer | null;
|
|
438
|
+
manifest: ViteManifest | null;
|
|
439
|
+
serverManifest: ViteManifest | null;
|
|
440
|
+
entryServerPath: string;
|
|
441
|
+
isDevelopment: boolean;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Streaming SSR renderer using React's renderToPipeableStream
|
|
445
|
+
*
|
|
446
|
+
* This renderer provides:
|
|
447
|
+
* - Better TTFB (Time to First Byte)
|
|
448
|
+
* - Progressive rendering with Suspense support
|
|
449
|
+
* - Lower memory usage for large pages
|
|
450
|
+
*
|
|
451
|
+
* Trade-offs:
|
|
452
|
+
* - More complex error handling (shell vs streaming errors)
|
|
453
|
+
* - Errors after shell may result in partial responses with HTTP 200
|
|
454
|
+
* - Requires careful Suspense boundary design
|
|
455
|
+
*
|
|
456
|
+
* Use this mode when:
|
|
457
|
+
* - Performance is critical
|
|
458
|
+
* - You're using Suspense for data fetching
|
|
459
|
+
* - You understand the error handling implications
|
|
460
|
+
*/
|
|
461
|
+
declare class StreamRenderer {
|
|
364
462
|
private readonly templateParser;
|
|
365
463
|
private readonly streamingErrorHandler;
|
|
464
|
+
private readonly logger;
|
|
465
|
+
constructor(templateParser: TemplateParserService, streamingErrorHandler: StreamingErrorHandler);
|
|
466
|
+
/**
|
|
467
|
+
* Render a React component using streaming SSR
|
|
468
|
+
*
|
|
469
|
+
* @param viewComponent - The React component to render
|
|
470
|
+
* @param data - Data to pass to the component
|
|
471
|
+
* @param res - Express response object (required for streaming)
|
|
472
|
+
* @param context - Render context with Vite and manifest info
|
|
473
|
+
* @param head - Head data for SEO tags
|
|
474
|
+
*/
|
|
475
|
+
render(viewComponent: any, data: any, res: Response, context: StreamRenderContext, head?: HeadData): Promise<void>;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Main render service that orchestrates SSR rendering
|
|
480
|
+
*
|
|
481
|
+
* This service:
|
|
482
|
+
* - Loads and manages HTML templates
|
|
483
|
+
* - Handles Vite manifest loading for production
|
|
484
|
+
* - Discovers root layouts
|
|
485
|
+
* - Delegates rendering to StringRenderer (default) or StreamRenderer
|
|
486
|
+
*
|
|
487
|
+
* String mode is the default because it provides:
|
|
488
|
+
* - Atomic responses (complete HTML or error page)
|
|
489
|
+
* - Proper HTTP status codes always
|
|
490
|
+
* - Simpler error handling and debugging
|
|
491
|
+
*
|
|
492
|
+
* Stream mode is available for advanced use cases requiring:
|
|
493
|
+
* - Better TTFB (Time to First Byte)
|
|
494
|
+
* - Progressive rendering with Suspense
|
|
495
|
+
*/
|
|
496
|
+
declare class RenderService {
|
|
497
|
+
private readonly stringRenderer;
|
|
498
|
+
private readonly streamRenderer;
|
|
366
499
|
private readonly defaultHead?;
|
|
367
500
|
private readonly logger;
|
|
368
501
|
private vite;
|
|
@@ -374,7 +507,14 @@ declare class RenderService {
|
|
|
374
507
|
private readonly entryServerPath;
|
|
375
508
|
private rootLayout;
|
|
376
509
|
private rootLayoutChecked;
|
|
377
|
-
constructor(
|
|
510
|
+
constructor(stringRenderer: StringRenderer, streamRenderer: StreamRenderer, ssrMode?: SSRMode, defaultHead?: HeadData | undefined, customTemplate?: string);
|
|
511
|
+
/**
|
|
512
|
+
* Load HTML template from custom path, package, or local location
|
|
513
|
+
*/
|
|
514
|
+
private loadTemplate;
|
|
515
|
+
private loadCustomTemplate;
|
|
516
|
+
private loadDefaultTemplate;
|
|
517
|
+
private loadManifests;
|
|
378
518
|
setViteServer(vite: ViteDevServer): void;
|
|
379
519
|
/**
|
|
380
520
|
* Get the root layout component if it exists
|
|
@@ -386,21 +526,28 @@ declare class RenderService {
|
|
|
386
526
|
getRootLayout(): Promise<any | null>;
|
|
387
527
|
/**
|
|
388
528
|
* Main render method that routes to string or stream mode
|
|
529
|
+
*
|
|
530
|
+
* String mode (default):
|
|
531
|
+
* - Returns complete HTML string
|
|
532
|
+
* - Atomic responses - works completely or fails completely
|
|
533
|
+
* - Proper HTTP status codes always
|
|
534
|
+
*
|
|
535
|
+
* Stream mode:
|
|
536
|
+
* - Writes directly to response
|
|
537
|
+
* - Better TTFB, progressive rendering
|
|
538
|
+
* - Requires response object
|
|
389
539
|
*/
|
|
390
540
|
render(viewComponent: any, data?: any, res?: Response, head?: HeadData): Promise<string | void>;
|
|
541
|
+
/**
|
|
542
|
+
* Render a segment for client-side navigation.
|
|
543
|
+
* Always uses string mode (streaming not supported for segments).
|
|
544
|
+
*/
|
|
545
|
+
renderSegment(viewComponent: any, data: any, swapTarget: string, head?: HeadData): Promise<SegmentResponse>;
|
|
391
546
|
/**
|
|
392
547
|
* Merge default head with page-specific head
|
|
393
548
|
* Page-specific head values override defaults
|
|
394
549
|
*/
|
|
395
550
|
private mergeHead;
|
|
396
|
-
/**
|
|
397
|
-
* Traditional string-based SSR using renderToString
|
|
398
|
-
*/
|
|
399
|
-
private renderToString;
|
|
400
|
-
/**
|
|
401
|
-
* Modern streaming SSR using renderToPipeableStream
|
|
402
|
-
*/
|
|
403
|
-
private renderToStream;
|
|
404
551
|
}
|
|
405
552
|
|
|
406
553
|
declare class RenderInterceptor implements NestInterceptor {
|
|
@@ -419,6 +566,22 @@ declare class RenderInterceptor implements NestInterceptor {
|
|
|
419
566
|
* 3. Dynamic props from controller return (final override)
|
|
420
567
|
*/
|
|
421
568
|
private resolveLayoutChain;
|
|
569
|
+
/**
|
|
570
|
+
* Detect request type based on headers.
|
|
571
|
+
* - If X-Current-Layouts header is present, this is a segment request
|
|
572
|
+
* - Only GET requests can be segments
|
|
573
|
+
*/
|
|
574
|
+
private detectRequestType;
|
|
575
|
+
/**
|
|
576
|
+
* Determine swap target by finding deepest common layout.
|
|
577
|
+
* Returns null if no common ancestor (client should do full navigation).
|
|
578
|
+
*/
|
|
579
|
+
private determineSwapTarget;
|
|
580
|
+
/**
|
|
581
|
+
* Filter layouts to only include those below the swap target.
|
|
582
|
+
* The swap target's outlet will contain the filtered layouts.
|
|
583
|
+
*/
|
|
584
|
+
private filterLayoutsFromSwapTarget;
|
|
422
585
|
intercept(context: ExecutionContext, next: CallHandler): Observable<any>;
|
|
423
586
|
}
|
|
424
587
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { E as ErrorPageDevelopment, e as ErrorPageProduction, c as RenderConfig, b as RenderInterceptor, R as RenderModule, a as RenderService, d as SSRMode, S as StreamingErrorHandler, T as TemplateParserService } from './index-
|
|
1
|
+
export { E as ErrorPageDevelopment, e as ErrorPageProduction, c as RenderConfig, b as RenderInterceptor, R as RenderModule, a as RenderService, d as SSRMode, S as StreamingErrorHandler, T as TemplateParserService } from './index-DdE--mA2.mjs';
|
|
2
2
|
import React, { ComponentType, ReactNode } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
export { PageContextProvider, createSSRHooks } from './
|
|
5
|
-
import { H as HeadData,
|
|
3
|
+
import { P as PageProps } from './use-page-context-CGT9woWe.mjs';
|
|
4
|
+
export { a as PageContextProvider, c as createSSRHooks, i as useCookie, h as useCookies, g as useHeader, f as useHeaders, u as usePageContext, b as useParams, d as useQuery, e as useRequest } from './use-page-context-CGT9woWe.mjs';
|
|
5
|
+
import { R as RenderContext, H as HeadData, a as RenderResponse } from './render-response.interface-CxbuKGnV.mjs';
|
|
6
6
|
import '@nestjs/common';
|
|
7
7
|
import 'vite';
|
|
8
8
|
import 'express';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { E as ErrorPageDevelopment, e as ErrorPageProduction, c as RenderConfig, b as RenderInterceptor, R as RenderModule, a as RenderService, d as SSRMode, S as StreamingErrorHandler, T as TemplateParserService } from './index-
|
|
1
|
+
export { E as ErrorPageDevelopment, e as ErrorPageProduction, c as RenderConfig, b as RenderInterceptor, R as RenderModule, a as RenderService, d as SSRMode, S as StreamingErrorHandler, T as TemplateParserService } from './index-BzOLOiIZ.js';
|
|
2
2
|
import React, { ComponentType, ReactNode } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
export { PageContextProvider, createSSRHooks } from './
|
|
5
|
-
import { H as HeadData,
|
|
3
|
+
import { P as PageProps } from './use-page-context-05ODF4zW.js';
|
|
4
|
+
export { a as PageContextProvider, c as createSSRHooks, i as useCookie, h as useCookies, g as useHeader, f as useHeaders, u as usePageContext, b as useParams, d as useQuery, e as useRequest } from './use-page-context-05ODF4zW.js';
|
|
5
|
+
import { R as RenderContext, H as HeadData, a as RenderResponse } from './render-response.interface-CxbuKGnV.js';
|
|
6
6
|
import '@nestjs/common';
|
|
7
7
|
import 'vite';
|
|
8
8
|
import 'express';
|