@bleedingdev/modern-js-runtime 3.2.0-ultramodern.120 → 3.2.0-ultramodern.122
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/cjs/boundary-debugger/index.js +4 -0
- package/dist/cjs/cli/index.js +11 -0
- package/dist/cjs/{router/runtime/tanstack/rsc/ClientSlot.js → core/context/extensions.js} +33 -21
- package/dist/cjs/{router/runtime/tanstack/rsc/SlotContext.js → core/context/helmetContext.js} +16 -20
- package/dist/cjs/core/context/index.js +65 -0
- package/dist/cjs/core/react/wrapper.js +6 -4
- package/dist/cjs/core/server/helmet.js +2 -1
- package/dist/cjs/core/server/requestHandler.js +42 -29
- package/dist/cjs/core/server/routerCleanup.js +110 -0
- package/dist/cjs/core/server/scriptOrder.js +75 -4
- package/dist/cjs/core/server/stream/afterTemplate.js +6 -18
- package/dist/cjs/core/server/stream/deferredScript.js +4 -1
- package/dist/cjs/core/server/string/index.js +1 -7
- package/dist/cjs/core/server/string/loadable.js +13 -40
- package/dist/cjs/core/server/string/ssrData.js +1 -1
- package/dist/cjs/core/server/utils.js +31 -8
- package/dist/cjs/exports/head.js +135 -74
- package/dist/cjs/exports/tanstack-router.js +36 -305
- package/dist/cjs/module-federation/index.js +178 -0
- package/dist/cjs/router/cli/code/index.js +1 -47
- package/dist/cjs/router/cli/code/templates.js +1 -14
- package/dist/cjs/router/cli/handler.js +1 -1
- package/dist/cjs/router/cli/index.js +2 -23
- package/dist/cjs/router/runtime/DeferredDataScripts.node.js +16 -4
- package/dist/cjs/router/runtime/PrefetchLink.js +2 -3
- package/dist/cjs/router/runtime/internal.js +20 -13
- package/dist/cjs/router/runtime/lifecycle.js +37 -22
- package/dist/cjs/router/runtime/plugin.js +2 -9
- package/dist/cjs/router/runtime/plugin.node.js +2 -7
- package/dist/cjs/router/runtime/provider.js +107 -0
- package/dist/cjs/router/runtime/utils.js +35 -9
- package/dist/esm/boundary-debugger/index.mjs +4 -0
- package/dist/esm/cli/index.mjs +4 -2
- package/dist/esm/core/context/extensions.mjs +28 -0
- package/dist/esm/core/context/helmetContext.mjs +13 -0
- package/dist/esm/core/context/index.mjs +5 -0
- package/dist/esm/core/react/wrapper.mjs +6 -4
- package/dist/esm/core/server/helmet.mjs +2 -1
- package/dist/esm/core/server/requestHandler.mjs +43 -30
- package/dist/esm/core/server/routerCleanup.mjs +66 -0
- package/dist/esm/core/server/scriptOrder.mjs +60 -1
- package/dist/esm/core/server/stream/afterTemplate.mjs +8 -20
- package/dist/esm/core/server/stream/deferredScript.mjs +4 -1
- package/dist/esm/core/server/string/index.mjs +3 -9
- package/dist/esm/core/server/string/loadable.mjs +11 -38
- package/dist/esm/core/server/string/ssrData.mjs +2 -2
- package/dist/esm/core/server/utils.mjs +31 -8
- package/dist/esm/exports/head.mjs +135 -74
- package/dist/esm/exports/tanstack-router.mjs +30 -4
- package/dist/esm/module-federation/index.mjs +109 -0
- package/dist/esm/router/cli/code/index.mjs +1 -47
- package/dist/esm/router/cli/code/templates.mjs +1 -14
- package/dist/esm/router/cli/handler.mjs +1 -1
- package/dist/esm/router/cli/index.mjs +3 -24
- package/dist/esm/router/runtime/DeferredDataScripts.node.mjs +16 -4
- package/dist/esm/router/runtime/PrefetchLink.mjs +2 -3
- package/dist/esm/router/runtime/internal.mjs +16 -15
- package/dist/esm/router/runtime/lifecycle.mjs +22 -13
- package/dist/esm/router/runtime/plugin.mjs +4 -11
- package/dist/esm/router/runtime/plugin.node.mjs +4 -9
- package/dist/esm/router/runtime/provider.mjs +57 -0
- package/dist/esm/router/runtime/utils.mjs +35 -9
- package/dist/esm-node/boundary-debugger/index.mjs +4 -0
- package/dist/esm-node/cli/index.mjs +4 -2
- package/dist/esm-node/core/context/extensions.mjs +29 -0
- package/dist/esm-node/core/context/helmetContext.mjs +14 -0
- package/dist/esm-node/core/context/index.mjs +5 -0
- package/dist/esm-node/core/react/wrapper.mjs +6 -4
- package/dist/esm-node/core/server/helmet.mjs +2 -1
- package/dist/esm-node/core/server/requestHandler.mjs +43 -30
- package/dist/esm-node/core/server/routerCleanup.mjs +67 -0
- package/dist/esm-node/core/server/scriptOrder.mjs +60 -1
- package/dist/esm-node/core/server/stream/afterTemplate.mjs +8 -20
- package/dist/esm-node/core/server/stream/deferredScript.mjs +4 -1
- package/dist/esm-node/core/server/string/index.mjs +3 -9
- package/dist/esm-node/core/server/string/loadable.mjs +11 -38
- package/dist/esm-node/core/server/string/ssrData.mjs +2 -2
- package/dist/esm-node/core/server/utils.mjs +31 -8
- package/dist/esm-node/exports/head.mjs +135 -74
- package/dist/esm-node/exports/tanstack-router.mjs +30 -4
- package/dist/esm-node/module-federation/index.mjs +110 -0
- package/dist/esm-node/router/cli/code/index.mjs +1 -47
- package/dist/esm-node/router/cli/code/templates.mjs +1 -14
- package/dist/esm-node/router/cli/handler.mjs +1 -1
- package/dist/esm-node/router/cli/index.mjs +3 -24
- package/dist/esm-node/router/runtime/DeferredDataScripts.node.mjs +16 -4
- package/dist/esm-node/router/runtime/PrefetchLink.mjs +2 -3
- package/dist/esm-node/router/runtime/internal.mjs +16 -15
- package/dist/esm-node/router/runtime/lifecycle.mjs +22 -13
- package/dist/esm-node/router/runtime/plugin.mjs +4 -11
- package/dist/esm-node/router/runtime/plugin.node.mjs +4 -9
- package/dist/esm-node/router/runtime/provider.mjs +58 -0
- package/dist/esm-node/router/runtime/utils.mjs +35 -9
- package/dist/types/cli/index.d.ts +3 -1
- package/dist/types/core/context/extensions.d.ts +37 -0
- package/dist/types/core/context/helmetContext.d.ts +10 -0
- package/dist/types/core/context/index.d.ts +6 -0
- package/dist/types/core/context/runtime.d.ts +1 -11
- package/dist/types/core/server/routerCleanup.d.ts +28 -0
- package/dist/types/core/server/scriptOrder.d.ts +24 -0
- package/dist/types/core/server/string/loadable.d.ts +1 -7
- package/dist/types/core/server/utils.d.ts +1 -0
- package/dist/types/exports/tanstack-router.d.ts +88 -7
- package/dist/types/module-federation/index.d.ts +65 -0
- package/dist/types/router/cli/code/index.d.ts +1 -3
- package/dist/types/router/cli/handler.d.ts +0 -3
- package/dist/types/router/runtime/internal.d.ts +1 -0
- package/dist/types/router/runtime/lifecycle.d.ts +2 -0
- package/dist/types/router/runtime/plugin.d.ts +1 -1
- package/dist/types/router/runtime/plugin.node.d.ts +1 -1
- package/dist/types/router/runtime/provider.d.ts +61 -0
- package/package.json +16 -12
- package/rstest.config.mts +2 -4
- package/dist/cjs/router/cli/code/tanstackTypes.js +0 -447
- package/dist/cjs/router/runtime/tanstack/basepathRewrite.js +0 -66
- package/dist/cjs/router/runtime/tanstack/dataMutation.js +0 -349
- package/dist/cjs/router/runtime/tanstack/hydrationBoundary.js +0 -48
- package/dist/cjs/router/runtime/tanstack/outlet.js +0 -58
- package/dist/cjs/router/runtime/tanstack/plugin.js +0 -342
- package/dist/cjs/router/runtime/tanstack/plugin.node.js +0 -272
- package/dist/cjs/router/runtime/tanstack/prefetchLink.js +0 -59
- package/dist/cjs/router/runtime/tanstack/routeTree.js +0 -525
- package/dist/cjs/router/runtime/tanstack/rsc/CompositeComponent.js +0 -79
- package/dist/cjs/router/runtime/tanstack/rsc/ReplayableStream.js +0 -146
- package/dist/cjs/router/runtime/tanstack/rsc/RscNodeRenderer.js +0 -69
- package/dist/cjs/router/runtime/tanstack/rsc/client.js +0 -97
- package/dist/cjs/router/runtime/tanstack/rsc/createRscProxy.js +0 -145
- package/dist/cjs/router/runtime/tanstack/rsc/index.js +0 -46
- package/dist/cjs/router/runtime/tanstack/rsc/server.js +0 -250
- package/dist/cjs/router/runtime/tanstack/rsc/slotUsageSanitizer.js +0 -69
- package/dist/cjs/router/runtime/tanstack/rsc/symbols.js +0 -77
- package/dist/cjs/ssr/index.node.js +0 -125
- package/dist/cjs/ssr/serverRender/renderToStream/buildTemplate.after.js +0 -88
- package/dist/cjs/ssr/serverRender/renderToString/entry.js +0 -200
- package/dist/cjs/ssr/serverRender/types.js +0 -40
- package/dist/esm/router/cli/code/tanstackTypes.mjs +0 -396
- package/dist/esm/router/runtime/tanstack/basepathRewrite.mjs +0 -28
- package/dist/esm/router/runtime/tanstack/dataMutation.mjs +0 -305
- package/dist/esm/router/runtime/tanstack/hydrationBoundary.mjs +0 -10
- package/dist/esm/router/runtime/tanstack/outlet.mjs +0 -17
- package/dist/esm/router/runtime/tanstack/plugin.mjs +0 -304
- package/dist/esm/router/runtime/tanstack/plugin.node.mjs +0 -234
- package/dist/esm/router/runtime/tanstack/prefetchLink.mjs +0 -18
- package/dist/esm/router/runtime/tanstack/routeTree.mjs +0 -481
- package/dist/esm/router/runtime/tanstack/rsc/ClientSlot.mjs +0 -19
- package/dist/esm/router/runtime/tanstack/rsc/CompositeComponent.mjs +0 -41
- package/dist/esm/router/runtime/tanstack/rsc/ReplayableStream.mjs +0 -104
- package/dist/esm/router/runtime/tanstack/rsc/RscNodeRenderer.mjs +0 -31
- package/dist/esm/router/runtime/tanstack/rsc/SlotContext.mjs +0 -17
- package/dist/esm/router/runtime/tanstack/rsc/client.mjs +0 -53
- package/dist/esm/router/runtime/tanstack/rsc/createRscProxy.mjs +0 -107
- package/dist/esm/router/runtime/tanstack/rsc/index.mjs +0 -1
- package/dist/esm/router/runtime/tanstack/rsc/server.mjs +0 -200
- package/dist/esm/router/runtime/tanstack/rsc/slotUsageSanitizer.mjs +0 -31
- package/dist/esm/router/runtime/tanstack/rsc/symbols.mjs +0 -17
- package/dist/esm/ssr/index.node.mjs +0 -44
- package/dist/esm/ssr/serverRender/renderToStream/buildTemplate.after.mjs +0 -50
- package/dist/esm/ssr/serverRender/renderToString/entry.mjs +0 -151
- package/dist/esm/ssr/serverRender/types.mjs +0 -1
- package/dist/esm-node/router/cli/code/tanstackTypes.mjs +0 -397
- package/dist/esm-node/router/runtime/tanstack/basepathRewrite.mjs +0 -29
- package/dist/esm-node/router/runtime/tanstack/dataMutation.mjs +0 -306
- package/dist/esm-node/router/runtime/tanstack/hydrationBoundary.mjs +0 -11
- package/dist/esm-node/router/runtime/tanstack/outlet.mjs +0 -18
- package/dist/esm-node/router/runtime/tanstack/plugin.mjs +0 -305
- package/dist/esm-node/router/runtime/tanstack/plugin.node.mjs +0 -235
- package/dist/esm-node/router/runtime/tanstack/prefetchLink.mjs +0 -19
- package/dist/esm-node/router/runtime/tanstack/routeTree.mjs +0 -482
- package/dist/esm-node/router/runtime/tanstack/rsc/ClientSlot.mjs +0 -20
- package/dist/esm-node/router/runtime/tanstack/rsc/CompositeComponent.mjs +0 -42
- package/dist/esm-node/router/runtime/tanstack/rsc/ReplayableStream.mjs +0 -105
- package/dist/esm-node/router/runtime/tanstack/rsc/RscNodeRenderer.mjs +0 -32
- package/dist/esm-node/router/runtime/tanstack/rsc/SlotContext.mjs +0 -18
- package/dist/esm-node/router/runtime/tanstack/rsc/client.mjs +0 -54
- package/dist/esm-node/router/runtime/tanstack/rsc/createRscProxy.mjs +0 -108
- package/dist/esm-node/router/runtime/tanstack/rsc/index.mjs +0 -2
- package/dist/esm-node/router/runtime/tanstack/rsc/server.mjs +0 -201
- package/dist/esm-node/router/runtime/tanstack/rsc/slotUsageSanitizer.mjs +0 -32
- package/dist/esm-node/router/runtime/tanstack/rsc/symbols.mjs +0 -18
- package/dist/esm-node/ssr/index.node.mjs +0 -45
- package/dist/esm-node/ssr/serverRender/renderToStream/buildTemplate.after.mjs +0 -51
- package/dist/esm-node/ssr/serverRender/renderToString/entry.mjs +0 -152
- package/dist/esm-node/ssr/serverRender/types.mjs +0 -2
- package/dist/types/router/cli/code/tanstackTypes.d.ts +0 -10
- package/dist/types/router/runtime/tanstack/basepathRewrite.d.ts +0 -8
- package/dist/types/router/runtime/tanstack/dataMutation.d.ts +0 -29
- package/dist/types/router/runtime/tanstack/hydrationBoundary.d.ts +0 -2
- package/dist/types/router/runtime/tanstack/outlet.d.ts +0 -2
- package/dist/types/router/runtime/tanstack/plugin.d.ts +0 -6
- package/dist/types/router/runtime/tanstack/plugin.node.d.ts +0 -6
- package/dist/types/router/runtime/tanstack/prefetchLink.d.ts +0 -11
- package/dist/types/router/runtime/tanstack/routeTree.d.ts +0 -8
- package/dist/types/router/runtime/tanstack/rsc/ClientSlot.d.ts +0 -5
- package/dist/types/router/runtime/tanstack/rsc/CompositeComponent.d.ts +0 -3
- package/dist/types/router/runtime/tanstack/rsc/ReplayableStream.d.ts +0 -24
- package/dist/types/router/runtime/tanstack/rsc/RscNodeRenderer.d.ts +0 -5
- package/dist/types/router/runtime/tanstack/rsc/SlotContext.d.ts +0 -11
- package/dist/types/router/runtime/tanstack/rsc/client.d.ts +0 -11
- package/dist/types/router/runtime/tanstack/rsc/createRscProxy.d.ts +0 -7
- package/dist/types/router/runtime/tanstack/rsc/index.d.ts +0 -2
- package/dist/types/router/runtime/tanstack/rsc/server.d.ts +0 -14
- package/dist/types/router/runtime/tanstack/rsc/slotUsageSanitizer.d.ts +0 -2
- package/dist/types/router/runtime/tanstack/rsc/symbols.d.ts +0 -46
|
@@ -2,13 +2,14 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { storage } from "@modern-js/runtime-utils/node";
|
|
3
3
|
import { getPathname, parseCookie, parseHeaders, parseQuery } from "@modern-js/runtime-utils/universal/request";
|
|
4
4
|
import react, { Fragment } from "react";
|
|
5
|
-
import {
|
|
5
|
+
import { getRouterServerSnapshot } from "../../router/runtime/lifecycle.mjs";
|
|
6
6
|
import { handleRSCRedirect } from "../../router/runtime/rsc-router.mjs";
|
|
7
7
|
import { getGlobalInternalRuntimeContext, getGlobalRSCRoot } from "../context/index.mjs";
|
|
8
8
|
import { getInitialContext } from "../context/runtime.mjs";
|
|
9
9
|
import { getServerPayload } from "../context/serverPayload/index.mjs";
|
|
10
10
|
import { createRoot } from "../react/index.mjs";
|
|
11
11
|
import { CHUNK_CSS_PLACEHOLDER } from "./constants.mjs";
|
|
12
|
+
import { withRouterCleanup } from "./routerCleanup.mjs";
|
|
12
13
|
import { SSRErrors } from "./tracer.mjs";
|
|
13
14
|
import { getSSRConfigByEntry, getSSRMode } from "./utils.mjs";
|
|
14
15
|
async function handleRSCRequest(request, Root, context, options, handleRequest) {
|
|
@@ -37,6 +38,39 @@ const processRedirect = (headers, status, ctx)=>{
|
|
|
37
38
|
headers
|
|
38
39
|
});
|
|
39
40
|
};
|
|
41
|
+
const applyRouterSnapshotResult = (context, onError)=>{
|
|
42
|
+
const routerServerSnapshot = getRouterServerSnapshot(context);
|
|
43
|
+
const routerStatusCode = routerServerSnapshot?.statusCode ?? context.routerContext?.statusCode;
|
|
44
|
+
if (routerStatusCode && 200 !== routerStatusCode) context.ssrContext?.response.status(routerStatusCode);
|
|
45
|
+
const errors = Object.values(routerServerSnapshot?.errors || context.routerContext?.errors || {});
|
|
46
|
+
if (errors.length > 0) onError(errors[0], SSRErrors.LOADER_ERROR);
|
|
47
|
+
};
|
|
48
|
+
const createLoaderRedirectResponse = (beforeRenderResult, redirectCtx)=>{
|
|
49
|
+
if (!beforeRenderResult || !isRedirectStatus(beforeRenderResult.status)) return;
|
|
50
|
+
if (beforeRenderResult.headers.has('X-Modernjs-Redirect')) return beforeRenderResult;
|
|
51
|
+
const redirectUrl = beforeRenderResult.headers.get('Location') || '/';
|
|
52
|
+
return processRedirect(new Headers({
|
|
53
|
+
Location: redirectUrl
|
|
54
|
+
}), beforeRenderResult.status, redirectCtx);
|
|
55
|
+
};
|
|
56
|
+
const renderRequest = async (request, Root, context, options, handleRequest, enableRsc)=>{
|
|
57
|
+
if (enableRsc) return handleRSCRequest(request, Root, context, options, handleRequest);
|
|
58
|
+
return handleRequest(request, Root, {
|
|
59
|
+
...options,
|
|
60
|
+
runtimeContext: context
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
const finalizeRenderResponse = (response, responseProxy, redirectCtx, routerCleanup)=>{
|
|
64
|
+
if (-1 !== responseProxy.status && isRedirectStatus(responseProxy.status) && responseProxy.headers.Location) return processRedirect(new Headers(responseProxy.headers), responseProxy.status, redirectCtx);
|
|
65
|
+
Object.entries(responseProxy.headers).forEach(([key, value])=>{
|
|
66
|
+
response.headers.set(key, value);
|
|
67
|
+
});
|
|
68
|
+
if (-1 !== responseProxy.status) return routerCleanup.deferUntilBodyDone(new Response(response.body, {
|
|
69
|
+
status: responseProxy.status,
|
|
70
|
+
headers: response.headers
|
|
71
|
+
}));
|
|
72
|
+
return routerCleanup.deferUntilBodyDone(response);
|
|
73
|
+
};
|
|
40
74
|
function createSSRContext(request, options) {
|
|
41
75
|
const { config, loaderContext, onError, onTiming, locals, resource, params, responseProxy, reporter } = options;
|
|
42
76
|
const { nonce, useJsonScript } = config;
|
|
@@ -132,41 +166,20 @@ const createRequestHandler = async (handleRequest, createRequestOptions)=>{
|
|
|
132
166
|
isRSCNavigation: 'true' === request.headers.get('x-rsc-tree'),
|
|
133
167
|
basename: ssrContext.baseUrl || '/'
|
|
134
168
|
};
|
|
135
|
-
|
|
169
|
+
return withRouterCleanup(context, options.onError, async (routerCleanup)=>{
|
|
136
170
|
const beforeRenderResult = await runBeforeRender(context);
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (errors.length > 0) options.onError(errors[0], SSRErrors.LOADER_ERROR);
|
|
142
|
-
if ("u" > typeof Response && beforeRenderResult instanceof Response && isRedirectStatus(beforeRenderResult.status)) {
|
|
143
|
-
if (beforeRenderResult.headers.has('X-Modernjs-Redirect')) return beforeRenderResult;
|
|
144
|
-
const redirectUrl = beforeRenderResult.headers.get('Location') || '/';
|
|
145
|
-
return processRedirect(new Headers({
|
|
146
|
-
Location: redirectUrl
|
|
147
|
-
}), beforeRenderResult.status, redirectCtx);
|
|
171
|
+
applyRouterSnapshotResult(context, options.onError);
|
|
172
|
+
if ("u" > typeof Response) {
|
|
173
|
+
const redirectResponse = createLoaderRedirectResponse(beforeRenderResult, redirectCtx);
|
|
174
|
+
if (redirectResponse) return redirectResponse;
|
|
148
175
|
}
|
|
149
176
|
if (!createRequestOptions?.enableRsc) {
|
|
150
177
|
const { htmlTemplate } = options.resource;
|
|
151
178
|
options.resource.htmlTemplate = htmlTemplate.replace('</head>', `${CHUNK_CSS_PLACEHOLDER}</head>`);
|
|
152
179
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
runtimeContext: context
|
|
157
|
-
});
|
|
158
|
-
if (-1 !== responseProxy.status && isRedirectStatus(responseProxy.status) && responseProxy.headers.Location) return processRedirect(new Headers(responseProxy.headers), responseProxy.status, redirectCtx);
|
|
159
|
-
Object.entries(responseProxy.headers).forEach(([key, value])=>{
|
|
160
|
-
response.headers.set(key, value);
|
|
161
|
-
});
|
|
162
|
-
if (-1 !== responseProxy.status) return new Response(response.body, {
|
|
163
|
-
status: responseProxy.status,
|
|
164
|
-
headers: response.headers
|
|
165
|
-
});
|
|
166
|
-
return response;
|
|
167
|
-
} finally{
|
|
168
|
-
await cleanupRouterRuntimeState(context);
|
|
169
|
-
}
|
|
180
|
+
const response = await renderRequest(request, Root, context, options, handleRequest, !!createRequestOptions?.enableRsc);
|
|
181
|
+
return finalizeRenderResponse(response, responseProxy, redirectCtx, routerCleanup);
|
|
182
|
+
});
|
|
170
183
|
});
|
|
171
184
|
};
|
|
172
185
|
return requestHandler;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { getRouterRuntimeState } from "../../router/runtime/lifecycle.mjs";
|
|
2
|
+
const ROUTER_CLEANUP_ERROR = 'An error occurs during router runtime cleanup';
|
|
3
|
+
async function withRouterCleanup(runtimeContext, onError, callback) {
|
|
4
|
+
const routerCleanup = createRouterCleanup(runtimeContext, onError);
|
|
5
|
+
try {
|
|
6
|
+
return await callback(routerCleanup);
|
|
7
|
+
} finally{
|
|
8
|
+
if (!routerCleanup.deferred) await routerCleanup.run();
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function createRouterCleanup(runtimeContext, onError) {
|
|
12
|
+
let deferred = false;
|
|
13
|
+
let finished = false;
|
|
14
|
+
const run = async ()=>{
|
|
15
|
+
if (finished) return;
|
|
16
|
+
finished = true;
|
|
17
|
+
try {
|
|
18
|
+
await getRouterRuntimeState(runtimeContext)?.cleanup?.();
|
|
19
|
+
} catch (error) {
|
|
20
|
+
onError(error, ROUTER_CLEANUP_ERROR);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const deferUntilBodyDone = (response)=>{
|
|
24
|
+
const { body } = response;
|
|
25
|
+
if (!body || body.locked) return response;
|
|
26
|
+
deferred = true;
|
|
27
|
+
const reader = body.getReader();
|
|
28
|
+
const wrappedBody = new ReadableStream({
|
|
29
|
+
async pull (controller) {
|
|
30
|
+
let result;
|
|
31
|
+
try {
|
|
32
|
+
result = await reader.read();
|
|
33
|
+
} catch (error) {
|
|
34
|
+
controller.error(error);
|
|
35
|
+
await run();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (result.done) {
|
|
39
|
+
controller.close();
|
|
40
|
+
await run();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
controller.enqueue(result.value);
|
|
44
|
+
},
|
|
45
|
+
async cancel (reason) {
|
|
46
|
+
try {
|
|
47
|
+
await reader.cancel(reason);
|
|
48
|
+
} catch {}
|
|
49
|
+
await run();
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return new Response(wrappedBody, {
|
|
53
|
+
status: response.status,
|
|
54
|
+
statusText: response.statusText,
|
|
55
|
+
headers: response.headers
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
return {
|
|
59
|
+
get deferred () {
|
|
60
|
+
return deferred;
|
|
61
|
+
},
|
|
62
|
+
run,
|
|
63
|
+
deferUntilBodyDone
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export { ROUTER_CLEANUP_ERROR, createRouterCleanup, withRouterCleanup };
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { getRouterMatchedRouteIds } from "../../router/runtime/lifecycle.mjs";
|
|
2
|
+
import { CHUNK_JS_PLACEHOLDER } from "./constants.mjs";
|
|
3
|
+
import { safeReplace } from "./utils.mjs";
|
|
1
4
|
function getScriptTags(template) {
|
|
2
5
|
const scriptRegExp = /<script\b[^>]*\bsrc=(["'])(.*?)\1[^>]*><\/script>/g;
|
|
3
6
|
return Array.from(template.matchAll(scriptRegExp)).map((match)=>({
|
|
@@ -15,6 +18,42 @@ function isEntryScript(src, entryName, asyncEntry) {
|
|
|
15
18
|
const prefix = asyncEntry ? `async-${entryName}` : entryName;
|
|
16
19
|
return basename === `${prefix}.js` || basename.startsWith(`${prefix}.`) || basename.startsWith(`${prefix}-`);
|
|
17
20
|
}
|
|
21
|
+
const dedupeByUrl = (chunks)=>{
|
|
22
|
+
const seen = new Set();
|
|
23
|
+
return chunks.filter((chunk)=>{
|
|
24
|
+
if (void 0 === chunk.url || '' === chunk.url || seen.has(chunk.url)) return false;
|
|
25
|
+
seen.add(chunk.url);
|
|
26
|
+
return true;
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
const isAsyncEntryScriptChunk = (chunk, entryName)=>{
|
|
30
|
+
if (void 0 === chunk.url || !chunk.url.endsWith('.js')) return false;
|
|
31
|
+
const asyncEntryName = `async-${entryName}`;
|
|
32
|
+
const filename = chunk.filename ?? chunk.url;
|
|
33
|
+
const basename = filename.split('/').pop() ?? filename;
|
|
34
|
+
return basename === `${asyncEntryName}.js` || basename.startsWith(`${asyncEntryName}.`) || basename.startsWith(`${asyncEntryName}-`);
|
|
35
|
+
};
|
|
36
|
+
function getRouteAssets(runtimeContext, routeManifest = runtimeContext.routeManifest) {
|
|
37
|
+
return routeManifest?.routeAssets;
|
|
38
|
+
}
|
|
39
|
+
function getMatchedRouteAssets(runtimeContext, routeManifest) {
|
|
40
|
+
const routeAssets = getRouteAssets(runtimeContext, routeManifest);
|
|
41
|
+
if (void 0 === routeAssets) return [];
|
|
42
|
+
const matchedRouteIds = getRouterMatchedRouteIds(runtimeContext) ?? [];
|
|
43
|
+
return matchedRouteIds.flatMap((routeId)=>routeAssets[routeId]?.assets ?? []);
|
|
44
|
+
}
|
|
45
|
+
const orderHydrationScriptChunks = ({ asyncEntryChunks, collectedChunks, matchedRouteChunks, entryName })=>{
|
|
46
|
+
const asyncEntryScriptChunks = [];
|
|
47
|
+
const asyncEntryDependencyChunks = [];
|
|
48
|
+
for (const chunk of asyncEntryChunks)if (isAsyncEntryScriptChunk(chunk, entryName)) asyncEntryScriptChunks.push(chunk);
|
|
49
|
+
else asyncEntryDependencyChunks.push(chunk);
|
|
50
|
+
return dedupeByUrl([
|
|
51
|
+
...asyncEntryDependencyChunks,
|
|
52
|
+
...collectedChunks,
|
|
53
|
+
...matchedRouteChunks,
|
|
54
|
+
...asyncEntryScriptChunks
|
|
55
|
+
]);
|
|
56
|
+
};
|
|
18
57
|
function injectBeforeHydrationEntryScript(template, scripts, entryName = 'index') {
|
|
19
58
|
if ('' === scripts) return template;
|
|
20
59
|
const scriptTags = getScriptTags(template);
|
|
@@ -22,4 +61,24 @@ function injectBeforeHydrationEntryScript(template, scripts, entryName = 'index'
|
|
|
22
61
|
if (void 0 === target) return template;
|
|
23
62
|
return `${template.slice(0, target.index)}${scripts}${template.slice(target.index)}`;
|
|
24
63
|
}
|
|
25
|
-
|
|
64
|
+
function replaceChunkJsPlaceholder(template, scripts, entryName, placeholder = CHUNK_JS_PLACEHOLDER) {
|
|
65
|
+
if ('' === scripts) return safeReplace(template, placeholder, '');
|
|
66
|
+
const withoutPlaceholder = safeReplace(template, placeholder, '');
|
|
67
|
+
const withEarlyScripts = injectBeforeHydrationEntryScript(withoutPlaceholder, scripts, entryName);
|
|
68
|
+
if (withEarlyScripts !== withoutPlaceholder) return withEarlyScripts;
|
|
69
|
+
return safeReplace(template, placeholder, scripts);
|
|
70
|
+
}
|
|
71
|
+
function createRouteHydrationScriptTags(runtimeContext, entryName, options = {}) {
|
|
72
|
+
const { nonce, template } = options;
|
|
73
|
+
const routeAssets = getRouteAssets(runtimeContext);
|
|
74
|
+
if (void 0 === routeAssets) return '';
|
|
75
|
+
const matchedRouteIds = getRouterMatchedRouteIds(runtimeContext) ?? [];
|
|
76
|
+
const assetEntries = [
|
|
77
|
+
...matchedRouteIds.map((routeId)=>routeAssets[routeId]),
|
|
78
|
+
routeAssets[`async-${entryName}`]
|
|
79
|
+
].filter((entry)=>void 0 !== entry);
|
|
80
|
+
const jsAssets = Array.from(new Set(assetEntries.flatMap((entry)=>(entry.assets ?? []).filter((asset)=>asset.endsWith('.js')))));
|
|
81
|
+
const nonceAttr = void 0 === nonce || '' === nonce ? '' : ` nonce="${nonce}"`;
|
|
82
|
+
return jsAssets.filter((asset)=>template?.includes(asset) !== true).map((asset)=>`<script src=${asset}${nonceAttr}></script>`).join(' ');
|
|
83
|
+
}
|
|
84
|
+
export { createRouteHydrationScriptTags, getMatchedRouteAssets, injectBeforeHydrationEntryScript, orderHydrationScriptChunks, replaceChunkJsPlaceholder };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { serializeJson } from "@modern-js/runtime-utils/node";
|
|
2
|
-
import { getRouterHydrationScripts
|
|
2
|
+
import { getRouterHydrationScripts } from "../../../router/runtime/lifecycle.mjs";
|
|
3
3
|
import { SSR_DATA_JSON_ID } from "../../constants.mjs";
|
|
4
4
|
import { SSR_DATA_PLACEHOLDER } from "../constants.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { createRouteHydrationScriptTags, replaceChunkJsPlaceholder } from "../scriptOrder.mjs";
|
|
6
6
|
import { buildHtml } from "../shared.mjs";
|
|
7
7
|
import { attributesToString, safeReplace } from "../utils.mjs";
|
|
8
8
|
function buildShellAfterTemplate(afterAppTemplate, options) {
|
|
@@ -19,24 +19,12 @@ function buildShellAfterTemplate(afterAppTemplate, options) {
|
|
|
19
19
|
(template)=>injectJs(template, entryName, config.nonce)
|
|
20
20
|
];
|
|
21
21
|
async function injectJs(template, entryName, nonce) {
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
...matchedRouteIds.map((routeId)=>routeAssets[routeId]),
|
|
29
|
-
routeAssets[`async-${entryName}`]
|
|
30
|
-
].filter(Boolean);
|
|
31
|
-
const jsAssets = Array.from(new Set(assetEntries.flatMap((entry)=>(entry.assets ?? []).filter((asset)=>asset.endsWith('.js')))));
|
|
32
|
-
const nonceAttr = nonce ? ` nonce="${nonce}"` : '';
|
|
33
|
-
const jsChunkStr = jsAssets.filter((asset)=>!template.includes(asset)).map((asset)=>`<script src=${asset}${nonceAttr}></script>`).join(' ');
|
|
34
|
-
if (jsChunkStr) {
|
|
35
|
-
const withoutPlaceholder = safeReplace(template, '<!--<?- chunksMap.js ?>-->', '');
|
|
36
|
-
const withEarlyScripts = injectBeforeHydrationEntryScript(withoutPlaceholder, jsChunkStr, entryName);
|
|
37
|
-
return withEarlyScripts !== withoutPlaceholder ? withEarlyScripts : safeReplace(template, '<!--<?- chunksMap.js ?>-->', jsChunkStr);
|
|
38
|
-
}
|
|
39
|
-
return template;
|
|
22
|
+
const jsChunkStr = createRouteHydrationScriptTags(runtimeContext, entryName, {
|
|
23
|
+
nonce,
|
|
24
|
+
template
|
|
25
|
+
});
|
|
26
|
+
if (!jsChunkStr) return template;
|
|
27
|
+
return replaceChunkJsPlaceholder(template, jsChunkStr, entryName);
|
|
40
28
|
}
|
|
41
29
|
return buildHtml(afterAppTemplate, callbacks);
|
|
42
30
|
}
|
|
@@ -22,12 +22,15 @@ function isPromiseLike(value) {
|
|
|
22
22
|
return !!value && 'function' == typeof value.then;
|
|
23
23
|
}
|
|
24
24
|
function toErrorInfo(error) {
|
|
25
|
+
if ('production' === process.env.NODE_ENV) return {
|
|
26
|
+
message: 'Unexpected Server Error'
|
|
27
|
+
};
|
|
25
28
|
if (error && 'object' == typeof error) {
|
|
26
29
|
const maybeMsg = error.message;
|
|
27
30
|
const maybeStack = error.stack;
|
|
28
31
|
return {
|
|
29
32
|
message: 'string' == typeof maybeMsg ? maybeMsg : String(maybeMsg ?? error),
|
|
30
|
-
stack:
|
|
33
|
+
stack: maybeStack
|
|
31
34
|
};
|
|
32
35
|
}
|
|
33
36
|
return {
|
|
@@ -4,9 +4,9 @@ import server from "react-dom/server";
|
|
|
4
4
|
import { RenderLevel } from "../../constants.mjs";
|
|
5
5
|
import { getGlobalInternalRuntimeContext } from "../../context/index.mjs";
|
|
6
6
|
import { wrapRuntimeContextProvider } from "../../react/wrapper.mjs";
|
|
7
|
-
import { CHUNK_CSS_PLACEHOLDER,
|
|
7
|
+
import { CHUNK_CSS_PLACEHOLDER, HTML_PLACEHOLDER, SSR_DATA_PLACEHOLDER } from "../constants.mjs";
|
|
8
8
|
import { createReplaceHelemt, getHelmetData } from "../helmet.mjs";
|
|
9
|
-
import {
|
|
9
|
+
import { replaceChunkJsPlaceholder } from "../scriptOrder.mjs";
|
|
10
10
|
import { buildHtml } from "../shared.mjs";
|
|
11
11
|
import { SSRErrors, SSRTimings } from "../tracer.mjs";
|
|
12
12
|
import { getSSRConfigByEntry, safeReplace } from "../utils.mjs";
|
|
@@ -98,13 +98,7 @@ function createReplaceSSRDataScript(data) {
|
|
|
98
98
|
return (template)=>safeReplace(template, SSR_DATA_PLACEHOLDER, data);
|
|
99
99
|
}
|
|
100
100
|
function createReplaceChunkJs(js, entryName) {
|
|
101
|
-
return (template)=>
|
|
102
|
-
if (!js) return safeReplace(template, CHUNK_JS_PLACEHOLDER, '');
|
|
103
|
-
const withoutPlaceholder = safeReplace(template, CHUNK_JS_PLACEHOLDER, '');
|
|
104
|
-
const withEarlyScripts = injectBeforeHydrationEntryScript(withoutPlaceholder, js, entryName);
|
|
105
|
-
if (withEarlyScripts !== withoutPlaceholder) return withEarlyScripts;
|
|
106
|
-
return safeReplace(template, CHUNK_JS_PLACEHOLDER, js);
|
|
107
|
-
};
|
|
101
|
+
return (template)=>replaceChunkJsPlaceholder(template, js, entryName);
|
|
108
102
|
}
|
|
109
103
|
function createReplaceChunkCss(css) {
|
|
110
104
|
return (template)=>safeReplace(template, CHUNK_CSS_PLACEHOLDER, css);
|
|
@@ -1,39 +1,21 @@
|
|
|
1
1
|
import { ChunkExtractor } from "@loadable/server";
|
|
2
|
-
import { getRouterMatchedRouteIds } from "../../../router/runtime/lifecycle.mjs";
|
|
3
2
|
import { createFederatedCssLinks } from "../federatedCss.mjs";
|
|
3
|
+
import { getMatchedRouteAssets, orderHydrationScriptChunks } from "../scriptOrder.mjs";
|
|
4
4
|
import { attributesToString, checkIsNode } from "../utils.mjs";
|
|
5
5
|
const extname = (uri)=>{
|
|
6
6
|
if ('string' != typeof uri || !uri.includes('.')) return '';
|
|
7
7
|
return `.${uri?.split('.').pop()}` || '';
|
|
8
8
|
};
|
|
9
9
|
const generateChunks = (chunks, ext)=>chunks.filter((chunk)=>Boolean(chunk.url)).filter((chunk)=>extname(chunk.url).slice(1) === ext);
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
const routeAssetToChunk = (asset)=>({
|
|
11
|
+
chunk: asset,
|
|
12
|
+
filename: asset.replace(/^\//, ''),
|
|
13
|
+
linkType: 'preload',
|
|
14
|
+
path: asset,
|
|
15
|
+
scriptType: asset.endsWith('.css') ? 'style' : "script",
|
|
16
|
+
type: 'routeAsset',
|
|
17
|
+
url: asset
|
|
16
18
|
});
|
|
17
|
-
};
|
|
18
|
-
const isAsyncEntryScriptChunk = (chunk, entryName)=>{
|
|
19
|
-
if (!chunk.url?.endsWith('.js')) return false;
|
|
20
|
-
const asyncEntryName = `async-${entryName}`;
|
|
21
|
-
const filename = chunk.filename || chunk.url;
|
|
22
|
-
const basename = filename.split('/').pop() || filename;
|
|
23
|
-
return basename === `${asyncEntryName}.js` || basename.startsWith(`${asyncEntryName}.`) || basename.startsWith(`${asyncEntryName}-`);
|
|
24
|
-
};
|
|
25
|
-
const orderHydrationScriptChunks = ({ asyncEntryChunks, collectedChunks, matchedRouteChunks, entryName })=>{
|
|
26
|
-
const asyncEntryScriptChunks = [];
|
|
27
|
-
const asyncEntryDependencyChunks = [];
|
|
28
|
-
for (const chunk of asyncEntryChunks)if (isAsyncEntryScriptChunk(chunk, entryName)) asyncEntryScriptChunks.push(chunk);
|
|
29
|
-
else asyncEntryDependencyChunks.push(chunk);
|
|
30
|
-
return dedupeChunksByUrl([
|
|
31
|
-
...asyncEntryDependencyChunks,
|
|
32
|
-
...collectedChunks,
|
|
33
|
-
...matchedRouteChunks,
|
|
34
|
-
...asyncEntryScriptChunks
|
|
35
|
-
]);
|
|
36
|
-
};
|
|
37
19
|
const checkIsInline = (chunk, enableInline)=>{
|
|
38
20
|
if ('production' !== process.env.NODE_ENV) return false;
|
|
39
21
|
if (enableInline instanceof RegExp) return enableInline.test(chunk.url);
|
|
@@ -52,17 +34,8 @@ class LoadableCollector {
|
|
|
52
34
|
}
|
|
53
35
|
getMatchedRouteChunks() {
|
|
54
36
|
const { routeManifest, runtimeContext } = this.options;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const matchedRouteIds = getRouterMatchedRouteIds(runtimeContext) ?? [];
|
|
58
|
-
return matchedRouteIds.flatMap((routeId)=>{
|
|
59
|
-
const routeAsset = routeAssets[routeId];
|
|
60
|
-
return (routeAsset?.assets ?? []).map((asset)=>({
|
|
61
|
-
filename: asset.replace(/^\//, ''),
|
|
62
|
-
path: asset,
|
|
63
|
-
url: asset
|
|
64
|
-
}));
|
|
65
|
-
});
|
|
37
|
+
if (!routeManifest) return [];
|
|
38
|
+
return getMatchedRouteAssets(runtimeContext, routeManifest).map(routeAssetToChunk);
|
|
66
39
|
}
|
|
67
40
|
collect(comopnent) {
|
|
68
41
|
const { stats, entryName } = this.options;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { serializeJson } from "@modern-js/runtime-utils/node";
|
|
2
|
-
import { getRouterHydrationScripts } from "../../../router/runtime/lifecycle.mjs";
|
|
2
|
+
import { getRouterHydrationScripts, getRouterServerSnapshot } from "../../../router/runtime/lifecycle.mjs";
|
|
3
3
|
import { ROUTER_DATA_JSON_ID, SSR_DATA_JSON_ID } from "../../constants.mjs";
|
|
4
4
|
import { attributesToString, serializeErrors } from "../utils.mjs";
|
|
5
5
|
function _check_private_redeclaration(obj, privateCollection) {
|
|
@@ -89,7 +89,7 @@ function getSSRData() {
|
|
|
89
89
|
}
|
|
90
90
|
function getRouterData() {
|
|
91
91
|
const { routerContext, runtimeContext } = _class_private_field_get(this, _options);
|
|
92
|
-
const snapshotRouterData = runtimeContext
|
|
92
|
+
const snapshotRouterData = getRouterServerSnapshot(runtimeContext)?.routerData;
|
|
93
93
|
if (snapshotRouterData) return {
|
|
94
94
|
loaderData: snapshotRouterData.loaderData,
|
|
95
95
|
errors: serializeErrors(snapshotRouterData.errors || null)
|
|
@@ -12,17 +12,40 @@ function serializeErrors(errors) {
|
|
|
12
12
|
if (!errors) return null;
|
|
13
13
|
const entries = Object.entries(errors);
|
|
14
14
|
const serialized = {};
|
|
15
|
-
for (const [key, val] of entries)if (isRouteErrorResponse(val)) serialized[key] =
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
for (const [key, val] of entries)if (isRouteErrorResponse(val)) serialized[key] = serializeRouteErrorResponse(val);
|
|
16
|
+
else if (val instanceof Error) serialized[key] = serializeError(val);
|
|
17
|
+
else serialized[key] = val;
|
|
18
|
+
return serialized;
|
|
19
|
+
}
|
|
20
|
+
function shouldRedactServerError() {
|
|
21
|
+
return 'development' !== process.env.NODE_ENV && 'test' !== process.env.NODE_ENV;
|
|
22
|
+
}
|
|
23
|
+
function serializeError(error) {
|
|
24
|
+
if (shouldRedactServerError()) return {
|
|
25
|
+
message: 'Unexpected Server Error',
|
|
26
|
+
stack: void 0,
|
|
27
|
+
__type: 'Error'
|
|
18
28
|
};
|
|
19
|
-
|
|
20
|
-
message:
|
|
21
|
-
stack:
|
|
29
|
+
return {
|
|
30
|
+
message: error.message,
|
|
31
|
+
stack: error.stack,
|
|
22
32
|
__type: 'Error'
|
|
23
33
|
};
|
|
24
|
-
|
|
25
|
-
|
|
34
|
+
}
|
|
35
|
+
function serializeRouteErrorResponse(error) {
|
|
36
|
+
if (!isRouteErrorResponse(error)) return error;
|
|
37
|
+
if (error.status >= 500 && shouldRedactServerError()) return {
|
|
38
|
+
status: error.status,
|
|
39
|
+
statusText: 'Internal Server Error',
|
|
40
|
+
data: 'Unexpected Server Error',
|
|
41
|
+
__type: 'RouteErrorResponse'
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
status: error.status,
|
|
45
|
+
statusText: error.statusText,
|
|
46
|
+
data: error.data,
|
|
47
|
+
__type: 'RouteErrorResponse'
|
|
48
|
+
};
|
|
26
49
|
}
|
|
27
50
|
function getSSRConfigByEntry(entryName, ssr, ssrByEntries) {
|
|
28
51
|
if (ssrByEntries?.[entryName]) return ssrByEntries[entryName];
|