@nestjs-ssr/react 0.1.5 → 0.1.6
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-Bptct1Q3.d.mts → index-Bpzo1KfR.d.mts} +4 -2
- package/dist/{index-Bptct1Q3.d.ts → index-Bpzo1KfR.d.ts} +4 -2
- package/dist/index.d.mts +31 -22
- package/dist/index.d.ts +31 -22
- package/dist/index.js +77 -7046
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +70 -7018
- package/dist/index.mjs.map +1 -1
- package/dist/render/index.d.mts +1 -1
- package/dist/render/index.d.ts +1 -1
- package/dist/render/index.js +61 -26
- package/dist/render/index.js.map +1 -1
- package/dist/render/index.mjs +62 -27
- package/dist/render/index.mjs.map +1 -1
- package/dist/templates/entry-client.tsx +16 -4
- package/dist/templates/entry-server.tsx +4 -8
- package/package.json +1 -1
- package/src/global.d.ts +2 -10
- package/src/templates/entry-client.tsx +16 -4
- package/src/templates/entry-server.tsx +4 -8
- package/dist/vite/index.d.mts +0 -11
- package/dist/vite/index.d.ts +0 -11
- package/dist/vite/index.js +0 -7022
- package/dist/vite/index.js.map +0 -1
- package/dist/vite/index.mjs +0 -6997
- package/dist/vite/index.mjs.map +0 -1
package/dist/render/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Injectable, Logger, Optional, Inject, Global, Module } from '@nestjs/common';
|
|
2
2
|
import { HttpAdapterHost, APP_INTERCEPTOR, Reflector } from '@nestjs/core';
|
|
3
3
|
import { existsSync, readFileSync } from 'fs';
|
|
4
|
-
import { join } from 'path';
|
|
4
|
+
import { join, relative } from 'path';
|
|
5
5
|
import serialize from 'serialize-javascript';
|
|
6
6
|
import escapeHtml from 'escape-html';
|
|
7
7
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
@@ -102,7 +102,7 @@ var TemplateParserService = class {
|
|
|
102
102
|
* This library handles all edge cases including escaping dangerous characters,
|
|
103
103
|
* functions, dates, regexes, and prevents prototype pollution.
|
|
104
104
|
*/
|
|
105
|
-
buildInlineScripts(data, context,
|
|
105
|
+
buildInlineScripts(data, context, componentName) {
|
|
106
106
|
return `<script>
|
|
107
107
|
window.__INITIAL_STATE__ = ${serialize(data, {
|
|
108
108
|
isJSON: true
|
|
@@ -110,7 +110,7 @@ window.__INITIAL_STATE__ = ${serialize(data, {
|
|
|
110
110
|
window.__CONTEXT__ = ${serialize(context, {
|
|
111
111
|
isJSON: true
|
|
112
112
|
})};
|
|
113
|
-
window.
|
|
113
|
+
window.__COMPONENT_NAME__ = ${serialize(componentName, {
|
|
114
114
|
isJSON: true
|
|
115
115
|
})};
|
|
116
116
|
</script>`;
|
|
@@ -420,12 +420,28 @@ var RenderService = class _RenderService {
|
|
|
420
420
|
serverManifest = null;
|
|
421
421
|
isDevelopment;
|
|
422
422
|
ssrMode;
|
|
423
|
+
entryServerPath;
|
|
424
|
+
entryClientPath;
|
|
423
425
|
constructor(templateParser, streamingErrorHandler, ssrMode, defaultHead) {
|
|
424
426
|
this.templateParser = templateParser;
|
|
425
427
|
this.streamingErrorHandler = streamingErrorHandler;
|
|
426
428
|
this.defaultHead = defaultHead;
|
|
427
429
|
this.isDevelopment = process.env.NODE_ENV !== "production";
|
|
428
430
|
this.ssrMode = ssrMode || process.env.SSR_MODE || "string";
|
|
431
|
+
const absoluteServerPath = join(__dirname, "/templates/entry-server.tsx");
|
|
432
|
+
const relativeServerPath = relative(process.cwd(), absoluteServerPath);
|
|
433
|
+
if (relativeServerPath.startsWith("..")) {
|
|
434
|
+
this.entryServerPath = absoluteServerPath;
|
|
435
|
+
} else {
|
|
436
|
+
this.entryServerPath = "/" + relativeServerPath.replace(/\\/g, "/");
|
|
437
|
+
}
|
|
438
|
+
const absoluteClientPath = join(__dirname, "/templates/entry-client.tsx");
|
|
439
|
+
const relativeClientPath = relative(process.cwd(), absoluteClientPath);
|
|
440
|
+
if (relativeClientPath.startsWith("..")) {
|
|
441
|
+
this.entryClientPath = absoluteClientPath;
|
|
442
|
+
} else {
|
|
443
|
+
this.entryClientPath = "/" + relativeClientPath.replace(/\\/g, "/");
|
|
444
|
+
}
|
|
429
445
|
let templatePath;
|
|
430
446
|
if (this.isDevelopment) {
|
|
431
447
|
const packageTemplatePaths = [
|
|
@@ -477,15 +493,15 @@ var RenderService = class _RenderService {
|
|
|
477
493
|
/**
|
|
478
494
|
* Main render method that routes to string or stream mode
|
|
479
495
|
*/
|
|
480
|
-
async render(
|
|
496
|
+
async render(viewComponent, data = {}, res, head) {
|
|
481
497
|
const mergedHead = this.mergeHead(this.defaultHead, head);
|
|
482
498
|
if (this.ssrMode === "stream") {
|
|
483
499
|
if (!res) {
|
|
484
500
|
throw new Error("Response object is required for streaming SSR mode. Pass res as third parameter.");
|
|
485
501
|
}
|
|
486
|
-
return this.renderToStream(
|
|
502
|
+
return this.renderToStream(viewComponent, data, res, mergedHead);
|
|
487
503
|
}
|
|
488
|
-
return this.renderToString(
|
|
504
|
+
return this.renderToString(viewComponent, data, mergedHead);
|
|
489
505
|
}
|
|
490
506
|
/**
|
|
491
507
|
* Merge default head with page-specific head
|
|
@@ -512,7 +528,7 @@ var RenderService = class _RenderService {
|
|
|
512
528
|
/**
|
|
513
529
|
* Traditional string-based SSR using renderToString
|
|
514
530
|
*/
|
|
515
|
-
async renderToString(
|
|
531
|
+
async renderToString(viewComponent, data = {}, head) {
|
|
516
532
|
const startTime = Date.now();
|
|
517
533
|
try {
|
|
518
534
|
let template = this.template;
|
|
@@ -521,7 +537,7 @@ var RenderService = class _RenderService {
|
|
|
521
537
|
}
|
|
522
538
|
let renderModule;
|
|
523
539
|
if (this.vite) {
|
|
524
|
-
renderModule = await this.vite.ssrLoadModule(
|
|
540
|
+
renderModule = await this.vite.ssrLoadModule(this.entryServerPath);
|
|
525
541
|
} else {
|
|
526
542
|
if (this.serverManifest) {
|
|
527
543
|
const manifestEntry = Object.entries(this.serverManifest).find(([key, value]) => value.isEntry && key.includes("entry-server"));
|
|
@@ -537,7 +553,8 @@ var RenderService = class _RenderService {
|
|
|
537
553
|
}
|
|
538
554
|
}
|
|
539
555
|
const { data: pageData, __context: context } = data;
|
|
540
|
-
const appHtml = await renderModule.renderComponent(
|
|
556
|
+
const appHtml = await renderModule.renderComponent(viewComponent, data);
|
|
557
|
+
const componentName = viewComponent.displayName || viewComponent.name || "Component";
|
|
541
558
|
const initialStateScript = `
|
|
542
559
|
<script>
|
|
543
560
|
window.__INITIAL_STATE__ = ${serialize(pageData, {
|
|
@@ -546,7 +563,7 @@ var RenderService = class _RenderService {
|
|
|
546
563
|
window.__CONTEXT__ = ${serialize(context, {
|
|
547
564
|
isJSON: true
|
|
548
565
|
})};
|
|
549
|
-
window.
|
|
566
|
+
window.__COMPONENT_NAME__ = ${serialize(componentName, {
|
|
550
567
|
isJSON: true
|
|
551
568
|
})};
|
|
552
569
|
</script>
|
|
@@ -554,7 +571,7 @@ var RenderService = class _RenderService {
|
|
|
554
571
|
let clientScript = "";
|
|
555
572
|
let styles = "";
|
|
556
573
|
if (this.vite) {
|
|
557
|
-
clientScript = `<script type="module" src="
|
|
574
|
+
clientScript = `<script type="module" src="${this.entryClientPath}"></script>`;
|
|
558
575
|
styles = "";
|
|
559
576
|
} else {
|
|
560
577
|
if (this.manifest) {
|
|
@@ -584,7 +601,8 @@ var RenderService = class _RenderService {
|
|
|
584
601
|
html = html.replace("<!--head-meta-->", headTags);
|
|
585
602
|
if (this.isDevelopment) {
|
|
586
603
|
const duration = Date.now() - startTime;
|
|
587
|
-
|
|
604
|
+
const componentName2 = typeof viewComponent === "function" ? viewComponent.name : String(viewComponent);
|
|
605
|
+
this.logger.log(`[SSR] ${componentName2} rendered in ${duration}ms (string mode)`);
|
|
588
606
|
}
|
|
589
607
|
return html;
|
|
590
608
|
} catch (error) {
|
|
@@ -594,7 +612,7 @@ var RenderService = class _RenderService {
|
|
|
594
612
|
/**
|
|
595
613
|
* Modern streaming SSR using renderToPipeableStream
|
|
596
614
|
*/
|
|
597
|
-
async renderToStream(
|
|
615
|
+
async renderToStream(viewComponent, data = {}, res, head) {
|
|
598
616
|
const startTime = Date.now();
|
|
599
617
|
let shellReadyTime = 0;
|
|
600
618
|
try {
|
|
@@ -605,7 +623,7 @@ var RenderService = class _RenderService {
|
|
|
605
623
|
const templateParts = this.templateParser.parseTemplate(template);
|
|
606
624
|
let renderModule;
|
|
607
625
|
if (this.vite) {
|
|
608
|
-
renderModule = await this.vite.ssrLoadModule(
|
|
626
|
+
renderModule = await this.vite.ssrLoadModule(this.entryServerPath);
|
|
609
627
|
} else {
|
|
610
628
|
if (this.serverManifest) {
|
|
611
629
|
const manifestEntry = Object.entries(this.serverManifest).find(([key, value]) => value.isEntry && key.includes("entry-server"));
|
|
@@ -621,12 +639,13 @@ var RenderService = class _RenderService {
|
|
|
621
639
|
}
|
|
622
640
|
}
|
|
623
641
|
const { data: pageData, __context: context } = data;
|
|
624
|
-
const
|
|
642
|
+
const componentName = viewComponent.displayName || viewComponent.name || "Component";
|
|
643
|
+
const inlineScripts = this.templateParser.buildInlineScripts(pageData, context, componentName);
|
|
625
644
|
const clientScript = this.templateParser.getClientScriptTag(this.isDevelopment, this.manifest);
|
|
626
645
|
const stylesheetTags = this.templateParser.getStylesheetTags(this.isDevelopment, this.manifest);
|
|
627
646
|
const headTags = this.templateParser.buildHeadTags(head);
|
|
628
647
|
let didError = false;
|
|
629
|
-
const { pipe, abort } = renderModule.renderComponentStream(
|
|
648
|
+
const { pipe, abort } = renderModule.renderComponentStream(viewComponent, data, {
|
|
630
649
|
onShellReady: /* @__PURE__ */ __name(() => {
|
|
631
650
|
shellReadyTime = Date.now();
|
|
632
651
|
res.statusCode = didError ? 500 : 200;
|
|
@@ -639,15 +658,15 @@ var RenderService = class _RenderService {
|
|
|
639
658
|
pipe(res);
|
|
640
659
|
if (this.isDevelopment) {
|
|
641
660
|
const ttfb = shellReadyTime - startTime;
|
|
642
|
-
this.logger.log(`[SSR] ${
|
|
661
|
+
this.logger.log(`[SSR] ${componentName} shell ready in ${ttfb}ms (stream mode - TTFB)`);
|
|
643
662
|
}
|
|
644
663
|
}, "onShellReady"),
|
|
645
664
|
onShellError: /* @__PURE__ */ __name((error) => {
|
|
646
|
-
this.streamingErrorHandler.handleShellError(error, res,
|
|
665
|
+
this.streamingErrorHandler.handleShellError(error, res, componentName, this.isDevelopment);
|
|
647
666
|
}, "onShellError"),
|
|
648
667
|
onError: /* @__PURE__ */ __name((error) => {
|
|
649
668
|
didError = true;
|
|
650
|
-
this.streamingErrorHandler.handleStreamError(error,
|
|
669
|
+
this.streamingErrorHandler.handleStreamError(error, componentName);
|
|
651
670
|
}, "onError"),
|
|
652
671
|
onAllReady: /* @__PURE__ */ __name(() => {
|
|
653
672
|
res.write(inlineScripts);
|
|
@@ -658,7 +677,7 @@ var RenderService = class _RenderService {
|
|
|
658
677
|
if (this.isDevelopment) {
|
|
659
678
|
const totalTime = Date.now() - startTime;
|
|
660
679
|
const streamTime = Date.now() - shellReadyTime;
|
|
661
|
-
this.logger.log(`[SSR] ${
|
|
680
|
+
this.logger.log(`[SSR] ${componentName} streaming complete in ${totalTime}ms total (${streamTime}ms streaming)`);
|
|
662
681
|
}
|
|
663
682
|
}, "onAllReady")
|
|
664
683
|
});
|
|
@@ -666,7 +685,8 @@ var RenderService = class _RenderService {
|
|
|
666
685
|
abort();
|
|
667
686
|
});
|
|
668
687
|
} catch (error) {
|
|
669
|
-
|
|
688
|
+
const componentName = typeof viewComponent === "function" ? viewComponent.name : String(viewComponent);
|
|
689
|
+
this.streamingErrorHandler.handleShellError(error, res, componentName, this.isDevelopment);
|
|
670
690
|
}
|
|
671
691
|
}
|
|
672
692
|
};
|
|
@@ -713,8 +733,8 @@ var RenderInterceptor = class {
|
|
|
713
733
|
this.renderService = renderService;
|
|
714
734
|
}
|
|
715
735
|
intercept(context, next) {
|
|
716
|
-
const
|
|
717
|
-
if (!
|
|
736
|
+
const viewPathOrComponent = this.reflector.get(RENDER_KEY, context.getHandler());
|
|
737
|
+
if (!viewPathOrComponent) {
|
|
718
738
|
return next.handle();
|
|
719
739
|
}
|
|
720
740
|
return next.handle().pipe(switchMap(async (data) => {
|
|
@@ -738,7 +758,7 @@ var RenderInterceptor = class {
|
|
|
738
758
|
__context: renderContext
|
|
739
759
|
};
|
|
740
760
|
try {
|
|
741
|
-
const html = await this.renderService.render(
|
|
761
|
+
const html = await this.renderService.render(viewPathOrComponent, fullData, response, renderResponse.head);
|
|
742
762
|
if (html !== void 0) {
|
|
743
763
|
response.type("text/html");
|
|
744
764
|
return html;
|
|
@@ -784,6 +804,7 @@ var ViteInitializerService = class _ViteInitializerService {
|
|
|
784
804
|
logger = new Logger(_ViteInitializerService.name);
|
|
785
805
|
viteMode;
|
|
786
806
|
vitePort;
|
|
807
|
+
viteServer = null;
|
|
787
808
|
constructor(renderService, httpAdapterHost, viteConfig) {
|
|
788
809
|
this.renderService = renderService;
|
|
789
810
|
this.httpAdapterHost = httpAdapterHost;
|
|
@@ -801,15 +822,15 @@ var ViteInitializerService = class _ViteInitializerService {
|
|
|
801
822
|
async setupDevelopmentMode() {
|
|
802
823
|
try {
|
|
803
824
|
const { createServer: createViteServer } = await import('vite');
|
|
804
|
-
|
|
825
|
+
this.viteServer = await createViteServer({
|
|
805
826
|
server: {
|
|
806
827
|
middlewareMode: true
|
|
807
828
|
},
|
|
808
829
|
appType: "custom"
|
|
809
830
|
});
|
|
810
|
-
this.renderService.setViteServer(
|
|
831
|
+
this.renderService.setViteServer(this.viteServer);
|
|
811
832
|
if (this.viteMode === "embedded") {
|
|
812
|
-
await this.mountViteMiddleware(
|
|
833
|
+
await this.mountViteMiddleware(this.viteServer);
|
|
813
834
|
} else if (this.viteMode === "proxy") {
|
|
814
835
|
await this.setupViteProxy();
|
|
815
836
|
}
|
|
@@ -872,6 +893,20 @@ var ViteInitializerService = class _ViteInitializerService {
|
|
|
872
893
|
this.logger.warn(`Failed to setup static assets: ${error.message}`);
|
|
873
894
|
}
|
|
874
895
|
}
|
|
896
|
+
/**
|
|
897
|
+
* Cleanup: Close Vite server on module destroy
|
|
898
|
+
* This prevents port conflicts on hot reload
|
|
899
|
+
*/
|
|
900
|
+
async onModuleDestroy() {
|
|
901
|
+
if (this.viteServer) {
|
|
902
|
+
try {
|
|
903
|
+
await this.viteServer.close();
|
|
904
|
+
this.logger.log("\u2713 Vite server closed");
|
|
905
|
+
} catch (error) {
|
|
906
|
+
this.logger.warn(`Failed to close Vite server: ${error.message}`);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
875
910
|
};
|
|
876
911
|
ViteInitializerService = _ts_decorate5([
|
|
877
912
|
Injectable(),
|