@webtypen/webframez-react 0.0.4 → 0.0.5
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/http.cjs +171 -67
- package/dist/http.js +172 -68
- package/dist/index.cjs +171 -67
- package/dist/index.js +172 -68
- package/dist/webframez-core.cjs +171 -67
- package/dist/webframez-core.js +172 -68
- package/package.json +1 -1
package/dist/http.cjs
CHANGED
|
@@ -478,57 +478,16 @@ function parseSearchParams(query) {
|
|
|
478
478
|
}
|
|
479
479
|
|
|
480
480
|
// src/http.ts
|
|
481
|
-
|
|
482
|
-
if (!basePath || basePath === "/") {
|
|
483
|
-
return "";
|
|
484
|
-
}
|
|
485
|
-
const withLeadingSlash = basePath.startsWith("/") ? basePath : `/${basePath}`;
|
|
486
|
-
return withLeadingSlash.endsWith("/") ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
|
|
487
|
-
}
|
|
488
|
-
function stripBasePath(pathname, basePath) {
|
|
489
|
-
if (!basePath) {
|
|
490
|
-
return pathname;
|
|
491
|
-
}
|
|
492
|
-
if (pathname === basePath) {
|
|
493
|
-
return "/";
|
|
494
|
-
}
|
|
495
|
-
if (pathname.startsWith(`${basePath}/`)) {
|
|
496
|
-
return pathname.slice(basePath.length) || "/";
|
|
497
|
-
}
|
|
498
|
-
return pathname;
|
|
499
|
-
}
|
|
500
|
-
function runNodeCommand(args) {
|
|
501
|
-
return new Promise((resolve, reject) => {
|
|
502
|
-
const execArgs = [
|
|
503
|
-
"--conditions",
|
|
504
|
-
"react-server",
|
|
505
|
-
"-r",
|
|
506
|
-
"@webtypen/webframez-react/register",
|
|
507
|
-
...args
|
|
508
|
-
];
|
|
509
|
-
(0, import_node_child_process.execFile)(
|
|
510
|
-
process.execPath,
|
|
511
|
-
execArgs,
|
|
512
|
-
{ timeout: 1e4, maxBuffer: 1024 * 1024 * 5 },
|
|
513
|
-
(error, stdout, stderr) => {
|
|
514
|
-
if (error) {
|
|
515
|
-
const out = stderr && stderr.trim() !== "" ? stderr : stdout;
|
|
516
|
-
reject(new Error(out || error.message));
|
|
517
|
-
return;
|
|
518
|
-
}
|
|
519
|
-
resolve({ stdout, stderr });
|
|
520
|
-
}
|
|
521
|
-
);
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
async function renderInitialHtmlInWorker(options) {
|
|
525
|
-
const payload = Buffer.from(JSON.stringify(options), "utf8").toString("base64url");
|
|
526
|
-
const script = `
|
|
481
|
+
var INITIAL_HTML_WORKER_SCRIPT = `
|
|
527
482
|
const path = require("node:path");
|
|
528
483
|
const Module = require("node:module");
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
484
|
+
|
|
485
|
+
const pagesDir = process.env.WEBFRAMEZ_REACT_PAGES_DIR || "";
|
|
486
|
+
if (!pagesDir) {
|
|
487
|
+
throw new Error("Missing WEBFRAMEZ_REACT_PAGES_DIR");
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const appRequire = Module.createRequire(path.join(pagesDir, "__webframez_react_worker__.js"));
|
|
532
491
|
const originalResolveFilename = Module._resolveFilename;
|
|
533
492
|
const forcedResolutions = new Map([
|
|
534
493
|
["react", appRequire.resolve("react")],
|
|
@@ -536,35 +495,174 @@ const forcedResolutions = new Map([
|
|
|
536
495
|
["react/jsx-dev-runtime", appRequire.resolve("react/jsx-dev-runtime")],
|
|
537
496
|
["react-dom/client", appRequire.resolve("react-dom/client")]
|
|
538
497
|
]);
|
|
498
|
+
|
|
539
499
|
Module._resolveFilename = function(request, parent, isMain, options) {
|
|
540
500
|
if (forcedResolutions.has(request)) {
|
|
541
501
|
return forcedResolutions.get(request);
|
|
542
502
|
}
|
|
543
503
|
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
544
504
|
};
|
|
505
|
+
|
|
545
506
|
const { createFileRouter } = require("@webtypen/webframez-react/router");
|
|
546
507
|
const reactDomPkg = require.resolve("react-dom/package.json", {
|
|
547
|
-
paths: [process.cwd(),
|
|
508
|
+
paths: [process.cwd(), pagesDir]
|
|
548
509
|
});
|
|
549
510
|
const reactDomServer = require(path.join(path.dirname(reactDomPkg), "server.node.js"));
|
|
511
|
+
const router = createFileRouter({ pagesDir });
|
|
550
512
|
|
|
551
|
-
(async () => {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
513
|
+
process.on("message", async (message) => {
|
|
514
|
+
if (!message || message.type !== "render") {
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
const previousBasename = globalThis.__RSC_BASENAME;
|
|
519
|
+
globalThis.__RSC_BASENAME = message.payload.basename || "";
|
|
520
|
+
|
|
521
|
+
try {
|
|
522
|
+
const resolved = await router.resolve({
|
|
523
|
+
pathname: message.payload.pathname,
|
|
524
|
+
searchParams: message.payload.searchParams || {},
|
|
525
|
+
cookies: message.payload.cookies || {},
|
|
526
|
+
});
|
|
527
|
+
const html = reactDomServer.renderToString(resolved.model);
|
|
528
|
+
if (typeof process.send === "function") {
|
|
529
|
+
process.send({ id: message.id, ok: true, html });
|
|
530
|
+
}
|
|
531
|
+
} catch (error) {
|
|
532
|
+
const formatted = error && (error.stack || String(error))
|
|
533
|
+
? (error.stack || String(error))
|
|
534
|
+
: "Unknown SSR worker error";
|
|
535
|
+
if (typeof process.send === "function") {
|
|
536
|
+
process.send({ id: message.id, ok: false, error: formatted });
|
|
537
|
+
}
|
|
538
|
+
} finally {
|
|
539
|
+
globalThis.__RSC_BASENAME = previousBasename;
|
|
540
|
+
}
|
|
563
541
|
});
|
|
564
542
|
`;
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
543
|
+
function normalizeBasePath(basePath) {
|
|
544
|
+
if (!basePath || basePath === "/") {
|
|
545
|
+
return "";
|
|
546
|
+
}
|
|
547
|
+
const withLeadingSlash = basePath.startsWith("/") ? basePath : `/${basePath}`;
|
|
548
|
+
return withLeadingSlash.endsWith("/") ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
|
|
549
|
+
}
|
|
550
|
+
function stripBasePath(pathname, basePath) {
|
|
551
|
+
if (!basePath) {
|
|
552
|
+
return pathname;
|
|
553
|
+
}
|
|
554
|
+
if (pathname === basePath) {
|
|
555
|
+
return "/";
|
|
556
|
+
}
|
|
557
|
+
if (pathname.startsWith(`${basePath}/`)) {
|
|
558
|
+
return pathname.slice(basePath.length) || "/";
|
|
559
|
+
}
|
|
560
|
+
return pathname;
|
|
561
|
+
}
|
|
562
|
+
function createInitialHtmlWorker(pagesDir) {
|
|
563
|
+
let child = null;
|
|
564
|
+
let nextRequestId = 1;
|
|
565
|
+
let stderrBuffer = "";
|
|
566
|
+
const pending = /* @__PURE__ */ new Map();
|
|
567
|
+
const rejectPending = (error) => {
|
|
568
|
+
for (const entry of pending.values()) {
|
|
569
|
+
clearTimeout(entry.timeout);
|
|
570
|
+
entry.reject(error);
|
|
571
|
+
}
|
|
572
|
+
pending.clear();
|
|
573
|
+
};
|
|
574
|
+
const stopWorker = () => {
|
|
575
|
+
if (!child) {
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
child.removeAllListeners();
|
|
579
|
+
if (!child.killed) {
|
|
580
|
+
child.kill();
|
|
581
|
+
}
|
|
582
|
+
child = null;
|
|
583
|
+
};
|
|
584
|
+
const startWorker = () => {
|
|
585
|
+
if (child && child.connected && !child.killed) {
|
|
586
|
+
return child;
|
|
587
|
+
}
|
|
588
|
+
stderrBuffer = "";
|
|
589
|
+
child = (0, import_node_child_process.spawn)(process.execPath, ["-e", INITIAL_HTML_WORKER_SCRIPT], {
|
|
590
|
+
cwd: process.cwd(),
|
|
591
|
+
env: {
|
|
592
|
+
...process.env,
|
|
593
|
+
WEBFRAMEZ_REACT_PAGES_DIR: pagesDir
|
|
594
|
+
},
|
|
595
|
+
stdio: ["ignore", "ignore", "pipe", "ipc"]
|
|
596
|
+
});
|
|
597
|
+
child.on("message", (message) => {
|
|
598
|
+
if (!message || typeof message.id !== "number") {
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
const entry = pending.get(message.id);
|
|
602
|
+
if (!entry) {
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
pending.delete(message.id);
|
|
606
|
+
clearTimeout(entry.timeout);
|
|
607
|
+
if (message.ok) {
|
|
608
|
+
entry.resolve(message.html);
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
entry.reject(new Error(message.error));
|
|
612
|
+
});
|
|
613
|
+
child.stderr?.on("data", (chunk) => {
|
|
614
|
+
stderrBuffer = `${stderrBuffer}${chunk.toString("utf8")}`.slice(-8192);
|
|
615
|
+
});
|
|
616
|
+
child.on("exit", (code, signal) => {
|
|
617
|
+
const suffix = stderrBuffer.trim() !== "" ? `
|
|
618
|
+
${stderrBuffer.trim()}` : "";
|
|
619
|
+
rejectPending(
|
|
620
|
+
new Error(
|
|
621
|
+
`[webframez-react] Initial HTML worker exited (${signal ?? code ?? "unknown"})${suffix}`
|
|
622
|
+
)
|
|
623
|
+
);
|
|
624
|
+
child = null;
|
|
625
|
+
});
|
|
626
|
+
child.on("error", (error) => {
|
|
627
|
+
rejectPending(error instanceof Error ? error : new Error(String(error)));
|
|
628
|
+
child = null;
|
|
629
|
+
});
|
|
630
|
+
return child;
|
|
631
|
+
};
|
|
632
|
+
return {
|
|
633
|
+
render(payload) {
|
|
634
|
+
const activeChild = startWorker();
|
|
635
|
+
const requestId = nextRequestId++;
|
|
636
|
+
return new Promise((resolve, reject) => {
|
|
637
|
+
const timeout = setTimeout(() => {
|
|
638
|
+
rejectPending(new Error("[webframez-react] Initial HTML worker timed out"));
|
|
639
|
+
stopWorker();
|
|
640
|
+
}, 1e4);
|
|
641
|
+
pending.set(requestId, { resolve, reject, timeout });
|
|
642
|
+
const request = {
|
|
643
|
+
id: requestId,
|
|
644
|
+
type: "render",
|
|
645
|
+
payload
|
|
646
|
+
};
|
|
647
|
+
activeChild.send(request, (error) => {
|
|
648
|
+
if (!error) {
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
const entry = pending.get(requestId);
|
|
652
|
+
if (!entry) {
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
pending.delete(requestId);
|
|
656
|
+
clearTimeout(entry.timeout);
|
|
657
|
+
entry.reject(error instanceof Error ? error : new Error(String(error)));
|
|
658
|
+
});
|
|
659
|
+
});
|
|
660
|
+
},
|
|
661
|
+
dispose() {
|
|
662
|
+
rejectPending(new Error("[webframez-react] Initial HTML worker disposed"));
|
|
663
|
+
stopWorker();
|
|
664
|
+
}
|
|
665
|
+
};
|
|
568
666
|
}
|
|
569
667
|
function withRequestBasename(basename, fn) {
|
|
570
668
|
const target = globalThis;
|
|
@@ -624,6 +722,13 @@ function createNodeRequestHandler(options) {
|
|
|
624
722
|
const liveReloadClients = /* @__PURE__ */ new Set();
|
|
625
723
|
const router = createFileRouter({ pagesDir });
|
|
626
724
|
const moduleMap = JSON.parse(import_node_fs2.default.readFileSync(manifestPath, "utf-8"));
|
|
725
|
+
const initialHtmlWorker = createInitialHtmlWorker(pagesDir);
|
|
726
|
+
const disposeInitialHtmlWorker = () => {
|
|
727
|
+
initialHtmlWorker.dispose();
|
|
728
|
+
};
|
|
729
|
+
process.once("exit", disposeInitialHtmlWorker);
|
|
730
|
+
process.once("SIGINT", disposeInitialHtmlWorker);
|
|
731
|
+
process.once("SIGTERM", disposeInitialHtmlWorker);
|
|
627
732
|
return async function handleRequest(req, res) {
|
|
628
733
|
if (!req.url) {
|
|
629
734
|
res.statusCode = 400;
|
|
@@ -723,8 +828,7 @@ function createNodeRequestHandler(options) {
|
|
|
723
828
|
);
|
|
724
829
|
let rootHtml = "";
|
|
725
830
|
try {
|
|
726
|
-
rootHtml = await
|
|
727
|
-
pagesDir,
|
|
831
|
+
rootHtml = await initialHtmlWorker.render({
|
|
728
832
|
pathname: stripBasePath(url.pathname, basePath),
|
|
729
833
|
searchParams: parseSearchParams(url.searchParams),
|
|
730
834
|
cookies: requestCookies,
|
package/dist/http.js
CHANGED
|
@@ -9,7 +9,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
9
9
|
// src/http.ts
|
|
10
10
|
import fs2 from "node:fs";
|
|
11
11
|
import path2 from "node:path";
|
|
12
|
-
import {
|
|
12
|
+
import { spawn } from "node:child_process";
|
|
13
13
|
|
|
14
14
|
// src/server.ts
|
|
15
15
|
import { renderToPipeableStream } from "react-server-dom-webpack/server";
|
|
@@ -453,57 +453,16 @@ function parseSearchParams(query) {
|
|
|
453
453
|
}
|
|
454
454
|
|
|
455
455
|
// src/http.ts
|
|
456
|
-
|
|
457
|
-
if (!basePath || basePath === "/") {
|
|
458
|
-
return "";
|
|
459
|
-
}
|
|
460
|
-
const withLeadingSlash = basePath.startsWith("/") ? basePath : `/${basePath}`;
|
|
461
|
-
return withLeadingSlash.endsWith("/") ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
|
|
462
|
-
}
|
|
463
|
-
function stripBasePath(pathname, basePath) {
|
|
464
|
-
if (!basePath) {
|
|
465
|
-
return pathname;
|
|
466
|
-
}
|
|
467
|
-
if (pathname === basePath) {
|
|
468
|
-
return "/";
|
|
469
|
-
}
|
|
470
|
-
if (pathname.startsWith(`${basePath}/`)) {
|
|
471
|
-
return pathname.slice(basePath.length) || "/";
|
|
472
|
-
}
|
|
473
|
-
return pathname;
|
|
474
|
-
}
|
|
475
|
-
function runNodeCommand(args) {
|
|
476
|
-
return new Promise((resolve, reject) => {
|
|
477
|
-
const execArgs = [
|
|
478
|
-
"--conditions",
|
|
479
|
-
"react-server",
|
|
480
|
-
"-r",
|
|
481
|
-
"@webtypen/webframez-react/register",
|
|
482
|
-
...args
|
|
483
|
-
];
|
|
484
|
-
execFile(
|
|
485
|
-
process.execPath,
|
|
486
|
-
execArgs,
|
|
487
|
-
{ timeout: 1e4, maxBuffer: 1024 * 1024 * 5 },
|
|
488
|
-
(error, stdout, stderr) => {
|
|
489
|
-
if (error) {
|
|
490
|
-
const out = stderr && stderr.trim() !== "" ? stderr : stdout;
|
|
491
|
-
reject(new Error(out || error.message));
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
resolve({ stdout, stderr });
|
|
495
|
-
}
|
|
496
|
-
);
|
|
497
|
-
});
|
|
498
|
-
}
|
|
499
|
-
async function renderInitialHtmlInWorker(options) {
|
|
500
|
-
const payload = Buffer.from(JSON.stringify(options), "utf8").toString("base64url");
|
|
501
|
-
const script = `
|
|
456
|
+
var INITIAL_HTML_WORKER_SCRIPT = `
|
|
502
457
|
const path = require("node:path");
|
|
503
458
|
const Module = require("node:module");
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
459
|
+
|
|
460
|
+
const pagesDir = process.env.WEBFRAMEZ_REACT_PAGES_DIR || "";
|
|
461
|
+
if (!pagesDir) {
|
|
462
|
+
throw new Error("Missing WEBFRAMEZ_REACT_PAGES_DIR");
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const appRequire = Module.createRequire(path.join(pagesDir, "__webframez_react_worker__.js"));
|
|
507
466
|
const originalResolveFilename = Module._resolveFilename;
|
|
508
467
|
const forcedResolutions = new Map([
|
|
509
468
|
["react", appRequire.resolve("react")],
|
|
@@ -511,35 +470,174 @@ const forcedResolutions = new Map([
|
|
|
511
470
|
["react/jsx-dev-runtime", appRequire.resolve("react/jsx-dev-runtime")],
|
|
512
471
|
["react-dom/client", appRequire.resolve("react-dom/client")]
|
|
513
472
|
]);
|
|
473
|
+
|
|
514
474
|
Module._resolveFilename = function(request, parent, isMain, options) {
|
|
515
475
|
if (forcedResolutions.has(request)) {
|
|
516
476
|
return forcedResolutions.get(request);
|
|
517
477
|
}
|
|
518
478
|
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
519
479
|
};
|
|
480
|
+
|
|
520
481
|
const { createFileRouter } = require("@webtypen/webframez-react/router");
|
|
521
482
|
const reactDomPkg = require.resolve("react-dom/package.json", {
|
|
522
|
-
paths: [process.cwd(),
|
|
483
|
+
paths: [process.cwd(), pagesDir]
|
|
523
484
|
});
|
|
524
485
|
const reactDomServer = require(path.join(path.dirname(reactDomPkg), "server.node.js"));
|
|
486
|
+
const router = createFileRouter({ pagesDir });
|
|
525
487
|
|
|
526
|
-
(async () => {
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
488
|
+
process.on("message", async (message) => {
|
|
489
|
+
if (!message || message.type !== "render") {
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
const previousBasename = globalThis.__RSC_BASENAME;
|
|
494
|
+
globalThis.__RSC_BASENAME = message.payload.basename || "";
|
|
495
|
+
|
|
496
|
+
try {
|
|
497
|
+
const resolved = await router.resolve({
|
|
498
|
+
pathname: message.payload.pathname,
|
|
499
|
+
searchParams: message.payload.searchParams || {},
|
|
500
|
+
cookies: message.payload.cookies || {},
|
|
501
|
+
});
|
|
502
|
+
const html = reactDomServer.renderToString(resolved.model);
|
|
503
|
+
if (typeof process.send === "function") {
|
|
504
|
+
process.send({ id: message.id, ok: true, html });
|
|
505
|
+
}
|
|
506
|
+
} catch (error) {
|
|
507
|
+
const formatted = error && (error.stack || String(error))
|
|
508
|
+
? (error.stack || String(error))
|
|
509
|
+
: "Unknown SSR worker error";
|
|
510
|
+
if (typeof process.send === "function") {
|
|
511
|
+
process.send({ id: message.id, ok: false, error: formatted });
|
|
512
|
+
}
|
|
513
|
+
} finally {
|
|
514
|
+
globalThis.__RSC_BASENAME = previousBasename;
|
|
515
|
+
}
|
|
538
516
|
});
|
|
539
517
|
`;
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
518
|
+
function normalizeBasePath(basePath) {
|
|
519
|
+
if (!basePath || basePath === "/") {
|
|
520
|
+
return "";
|
|
521
|
+
}
|
|
522
|
+
const withLeadingSlash = basePath.startsWith("/") ? basePath : `/${basePath}`;
|
|
523
|
+
return withLeadingSlash.endsWith("/") ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
|
|
524
|
+
}
|
|
525
|
+
function stripBasePath(pathname, basePath) {
|
|
526
|
+
if (!basePath) {
|
|
527
|
+
return pathname;
|
|
528
|
+
}
|
|
529
|
+
if (pathname === basePath) {
|
|
530
|
+
return "/";
|
|
531
|
+
}
|
|
532
|
+
if (pathname.startsWith(`${basePath}/`)) {
|
|
533
|
+
return pathname.slice(basePath.length) || "/";
|
|
534
|
+
}
|
|
535
|
+
return pathname;
|
|
536
|
+
}
|
|
537
|
+
function createInitialHtmlWorker(pagesDir) {
|
|
538
|
+
let child = null;
|
|
539
|
+
let nextRequestId = 1;
|
|
540
|
+
let stderrBuffer = "";
|
|
541
|
+
const pending = /* @__PURE__ */ new Map();
|
|
542
|
+
const rejectPending = (error) => {
|
|
543
|
+
for (const entry of pending.values()) {
|
|
544
|
+
clearTimeout(entry.timeout);
|
|
545
|
+
entry.reject(error);
|
|
546
|
+
}
|
|
547
|
+
pending.clear();
|
|
548
|
+
};
|
|
549
|
+
const stopWorker = () => {
|
|
550
|
+
if (!child) {
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
child.removeAllListeners();
|
|
554
|
+
if (!child.killed) {
|
|
555
|
+
child.kill();
|
|
556
|
+
}
|
|
557
|
+
child = null;
|
|
558
|
+
};
|
|
559
|
+
const startWorker = () => {
|
|
560
|
+
if (child && child.connected && !child.killed) {
|
|
561
|
+
return child;
|
|
562
|
+
}
|
|
563
|
+
stderrBuffer = "";
|
|
564
|
+
child = spawn(process.execPath, ["-e", INITIAL_HTML_WORKER_SCRIPT], {
|
|
565
|
+
cwd: process.cwd(),
|
|
566
|
+
env: {
|
|
567
|
+
...process.env,
|
|
568
|
+
WEBFRAMEZ_REACT_PAGES_DIR: pagesDir
|
|
569
|
+
},
|
|
570
|
+
stdio: ["ignore", "ignore", "pipe", "ipc"]
|
|
571
|
+
});
|
|
572
|
+
child.on("message", (message) => {
|
|
573
|
+
if (!message || typeof message.id !== "number") {
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
const entry = pending.get(message.id);
|
|
577
|
+
if (!entry) {
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
pending.delete(message.id);
|
|
581
|
+
clearTimeout(entry.timeout);
|
|
582
|
+
if (message.ok) {
|
|
583
|
+
entry.resolve(message.html);
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
entry.reject(new Error(message.error));
|
|
587
|
+
});
|
|
588
|
+
child.stderr?.on("data", (chunk) => {
|
|
589
|
+
stderrBuffer = `${stderrBuffer}${chunk.toString("utf8")}`.slice(-8192);
|
|
590
|
+
});
|
|
591
|
+
child.on("exit", (code, signal) => {
|
|
592
|
+
const suffix = stderrBuffer.trim() !== "" ? `
|
|
593
|
+
${stderrBuffer.trim()}` : "";
|
|
594
|
+
rejectPending(
|
|
595
|
+
new Error(
|
|
596
|
+
`[webframez-react] Initial HTML worker exited (${signal ?? code ?? "unknown"})${suffix}`
|
|
597
|
+
)
|
|
598
|
+
);
|
|
599
|
+
child = null;
|
|
600
|
+
});
|
|
601
|
+
child.on("error", (error) => {
|
|
602
|
+
rejectPending(error instanceof Error ? error : new Error(String(error)));
|
|
603
|
+
child = null;
|
|
604
|
+
});
|
|
605
|
+
return child;
|
|
606
|
+
};
|
|
607
|
+
return {
|
|
608
|
+
render(payload) {
|
|
609
|
+
const activeChild = startWorker();
|
|
610
|
+
const requestId = nextRequestId++;
|
|
611
|
+
return new Promise((resolve, reject) => {
|
|
612
|
+
const timeout = setTimeout(() => {
|
|
613
|
+
rejectPending(new Error("[webframez-react] Initial HTML worker timed out"));
|
|
614
|
+
stopWorker();
|
|
615
|
+
}, 1e4);
|
|
616
|
+
pending.set(requestId, { resolve, reject, timeout });
|
|
617
|
+
const request = {
|
|
618
|
+
id: requestId,
|
|
619
|
+
type: "render",
|
|
620
|
+
payload
|
|
621
|
+
};
|
|
622
|
+
activeChild.send(request, (error) => {
|
|
623
|
+
if (!error) {
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
const entry = pending.get(requestId);
|
|
627
|
+
if (!entry) {
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
pending.delete(requestId);
|
|
631
|
+
clearTimeout(entry.timeout);
|
|
632
|
+
entry.reject(error instanceof Error ? error : new Error(String(error)));
|
|
633
|
+
});
|
|
634
|
+
});
|
|
635
|
+
},
|
|
636
|
+
dispose() {
|
|
637
|
+
rejectPending(new Error("[webframez-react] Initial HTML worker disposed"));
|
|
638
|
+
stopWorker();
|
|
639
|
+
}
|
|
640
|
+
};
|
|
543
641
|
}
|
|
544
642
|
function withRequestBasename(basename, fn) {
|
|
545
643
|
const target = globalThis;
|
|
@@ -599,6 +697,13 @@ function createNodeRequestHandler(options) {
|
|
|
599
697
|
const liveReloadClients = /* @__PURE__ */ new Set();
|
|
600
698
|
const router = createFileRouter({ pagesDir });
|
|
601
699
|
const moduleMap = JSON.parse(fs2.readFileSync(manifestPath, "utf-8"));
|
|
700
|
+
const initialHtmlWorker = createInitialHtmlWorker(pagesDir);
|
|
701
|
+
const disposeInitialHtmlWorker = () => {
|
|
702
|
+
initialHtmlWorker.dispose();
|
|
703
|
+
};
|
|
704
|
+
process.once("exit", disposeInitialHtmlWorker);
|
|
705
|
+
process.once("SIGINT", disposeInitialHtmlWorker);
|
|
706
|
+
process.once("SIGTERM", disposeInitialHtmlWorker);
|
|
602
707
|
return async function handleRequest(req, res) {
|
|
603
708
|
if (!req.url) {
|
|
604
709
|
res.statusCode = 400;
|
|
@@ -698,8 +803,7 @@ function createNodeRequestHandler(options) {
|
|
|
698
803
|
);
|
|
699
804
|
let rootHtml = "";
|
|
700
805
|
try {
|
|
701
|
-
rootHtml = await
|
|
702
|
-
pagesDir,
|
|
806
|
+
rootHtml = await initialHtmlWorker.render({
|
|
703
807
|
pathname: stripBasePath(url.pathname, basePath),
|
|
704
808
|
searchParams: parseSearchParams(url.searchParams),
|
|
705
809
|
cookies: requestCookies,
|