@bleedingdev/modern-js-runtime 3.5.0-ultramodern.99 → 3.8.1-ultramodern.1
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/cli/ssr/index.js +1 -0
- package/dist/cjs/core/browser/hydrate.js +31 -27
- package/dist/cjs/core/react/wrapper.js +23 -28
- package/dist/cjs/core/server/requestResponse.js +5 -5
- package/dist/cjs/core/server/scriptOrder.js +1 -1
- package/dist/cjs/core/server/stream/beforeTemplate.worker.js +1 -10
- package/dist/cjs/core/server/utils.js +3 -3
- package/dist/cjs/document/cli/index.js +5 -2
- package/dist/cjs/module-federation/distributed-ssr.js +13 -12
- package/dist/cjs/module-federation/last-known-good.js +1 -1
- package/dist/cjs/module-federation/manifest-recovery-runtime-plugin.js +27 -38
- package/dist/cjs/router/cli/code/index.js +16 -9
- package/dist/cjs/router/cli/code/templates.js +36 -27
- package/dist/cjs/router/cli/handler.js +7 -1
- package/dist/cjs/router/runtime/plugin.js +22 -17
- package/dist/cjs/router/runtime/plugin.node.js +11 -3
- package/dist/cjs/router/runtime/provider.js +2 -2
- package/dist/cjs/router/runtime/redirect.js +51 -0
- package/dist/cjs/router/runtime/routerHelper.js +4 -0
- package/dist/cjs/router/runtime/rsc-router.js +2 -13
- package/dist/cjs/router/runtime/utils.js +3 -2
- package/dist/esm/cli/ssr/index.mjs +1 -0
- package/dist/esm/core/browser/hydrate.mjs +30 -22
- package/dist/esm/core/react/wrapper.mjs +23 -28
- package/dist/esm/core/server/requestResponse.mjs +4 -4
- package/dist/esm/core/server/scriptOrder.mjs +1 -1
- package/dist/esm/core/server/stream/beforeTemplate.worker.mjs +1 -10
- package/dist/esm/core/server/utils.mjs +1 -1
- package/dist/esm/document/cli/index.mjs +1 -1
- package/dist/esm/module-federation/distributed-ssr.mjs +13 -12
- package/dist/esm/module-federation/last-known-good.mjs +1 -1
- package/dist/esm/module-federation/manifest-recovery-runtime-plugin.mjs +22 -33
- package/dist/esm/router/cli/code/index.mjs +16 -9
- package/dist/esm/router/cli/code/templates.mjs +36 -27
- package/dist/esm/router/cli/handler.mjs +7 -1
- package/dist/esm/router/runtime/plugin.mjs +24 -19
- package/dist/esm/router/runtime/plugin.node.mjs +12 -4
- package/dist/esm/router/runtime/provider.mjs +2 -2
- package/dist/esm/router/runtime/redirect.mjs +13 -0
- package/dist/esm/router/runtime/routerHelper.mjs +2 -1
- package/dist/esm/router/runtime/rsc-router.mjs +2 -13
- package/dist/esm/router/runtime/utils.mjs +2 -1
- package/dist/esm-node/cli/ssr/index.mjs +1 -0
- package/dist/esm-node/core/browser/hydrate.mjs +30 -22
- package/dist/esm-node/core/react/wrapper.mjs +23 -28
- package/dist/esm-node/core/server/requestResponse.mjs +4 -4
- package/dist/esm-node/core/server/scriptOrder.mjs +1 -1
- package/dist/esm-node/core/server/stream/beforeTemplate.worker.mjs +1 -10
- package/dist/esm-node/core/server/utils.mjs +1 -1
- package/dist/esm-node/document/cli/index.mjs +1 -1
- package/dist/esm-node/module-federation/distributed-ssr.mjs +13 -12
- package/dist/esm-node/module-federation/last-known-good.mjs +1 -1
- package/dist/esm-node/module-federation/manifest-recovery-runtime-plugin.mjs +22 -33
- package/dist/esm-node/router/cli/code/index.mjs +16 -9
- package/dist/esm-node/router/cli/code/templates.mjs +36 -27
- package/dist/esm-node/router/cli/handler.mjs +7 -1
- package/dist/esm-node/router/runtime/plugin.mjs +24 -19
- package/dist/esm-node/router/runtime/plugin.node.mjs +12 -4
- package/dist/esm-node/router/runtime/provider.mjs +2 -2
- package/dist/esm-node/router/runtime/redirect.mjs +14 -0
- package/dist/esm-node/router/runtime/routerHelper.mjs +2 -1
- package/dist/esm-node/router/runtime/rsc-router.mjs +2 -13
- package/dist/esm-node/router/runtime/utils.mjs +2 -1
- package/dist/types/core/browser/hydrate.d.ts +0 -1
- package/dist/types/core/server/utils.d.ts +1 -1
- package/dist/types/document/cli/index.d.ts +1 -0
- package/dist/types/module-federation/distributed-ssr.d.ts +3 -3
- package/dist/types/module-federation/manifest-recovery-runtime-plugin.d.ts +1 -1
- package/dist/types/router/cli/code/index.d.ts +6 -1
- package/dist/types/router/cli/code/templates.d.ts +8 -3
- package/dist/types/router/cli/handler.d.ts +4 -0
- package/dist/types/router/runtime/redirect.d.ts +1 -0
- package/dist/types/router/runtime/routerHelper.d.ts +7 -0
- package/dist/types/router/runtime/rsc-router.d.ts +1 -2
- package/package.json +14 -14
- package/rstest.config.mts +2 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ROUTE_MODULES } from "@modern-js/utils/universal/constants";
|
|
2
|
+
const isRouteErrorResponse = (error)=>null !== error && 'object' == typeof error && 'number' == typeof error.status && 'string' == typeof error.statusText && 'boolean' == typeof error.internal && 'data' in error;
|
|
2
3
|
const isObjectLike = (value)=>'object' == typeof value && null !== value || 'function' == typeof value;
|
|
3
4
|
const isRouteComponent = (value)=>'function' == typeof value || isObjectLike(value) && '$$typeof' in value;
|
|
4
5
|
const getRouteModules = ()=>{
|
|
@@ -51,4 +52,4 @@ const handleRouteModuleError = (error)=>{
|
|
|
51
52
|
console.error(error);
|
|
52
53
|
return null;
|
|
53
54
|
};
|
|
54
|
-
export { createShouldRevalidate, handleRouteModule, handleRouteModuleError, resolveRouteComponent };
|
|
55
|
+
export { createShouldRevalidate, handleRouteModule, handleRouteModuleError, isRouteErrorResponse, resolveRouteComponent };
|
|
@@ -85,18 +85,6 @@ const createServerPayload = (routerContext, routes)=>{
|
|
|
85
85
|
})
|
|
86
86
|
};
|
|
87
87
|
};
|
|
88
|
-
const handleRSCRedirect = (headers, basename, status)=>{
|
|
89
|
-
const newHeaders = new Headers(headers);
|
|
90
|
-
let redirectUrl = headers.get('Location');
|
|
91
|
-
if ('/' !== basename) redirectUrl = redirectUrl.replace(basename, '');
|
|
92
|
-
newHeaders.set('X-Modernjs-Redirect', redirectUrl);
|
|
93
|
-
newHeaders.set('X-Modernjs-BaseUrl', basename);
|
|
94
|
-
newHeaders.delete('Location');
|
|
95
|
-
return new Response(null, {
|
|
96
|
-
status: status,
|
|
97
|
-
headers: newHeaders
|
|
98
|
-
});
|
|
99
|
-
};
|
|
100
88
|
const prepareRSCRoutes = async (routes)=>{
|
|
101
89
|
const isLazyComponent = (component)=>null != component && 'object' == typeof component && '_init' in component && '_payload' in component;
|
|
102
90
|
const processRoutes = async (routesList)=>{
|
|
@@ -325,4 +313,5 @@ const RSCStaticRouter = ({ basename })=>{
|
|
|
325
313
|
children: createRSCStaticRouterComponent(payload, basename)
|
|
326
314
|
});
|
|
327
315
|
};
|
|
328
|
-
export {
|
|
316
|
+
export { handleRSCRedirect } from "./redirect.mjs";
|
|
317
|
+
export { RSCStaticRouter, createClientRouterFromPayload, createServerPayload, prepareRSCRoutes };
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { renderNestedRoute } from "@modern-js/runtime-utils/browser";
|
|
3
|
-
import { Route, UNSAFE_ErrorResponseImpl
|
|
3
|
+
import { Route, UNSAFE_ErrorResponseImpl } from "@modern-js/runtime-utils/router";
|
|
4
4
|
import react from "react";
|
|
5
5
|
import { DefaultNotFound } from "./DefaultNotFound.mjs";
|
|
6
6
|
import DeferredDataScripts from "./DeferredDataScripts.mjs";
|
|
7
|
+
import { isRouteErrorResponse } from "./routerHelper.mjs";
|
|
7
8
|
function getRouteComponents(routes, { globalApp, ssrMode, props }) {
|
|
8
9
|
const Layout = ({ Component, ...props })=>{
|
|
9
10
|
const GlobalLayout = globalApp;
|
|
@@ -108,6 +108,7 @@ const ssrBuilderPlugin = (modernAPI, outputModule, exportLoadablePath)=>({
|
|
|
108
108
|
'process.env.MODERN_SSR_ENV': JSON.stringify(ssrEnv),
|
|
109
109
|
'process.env.MODERN_ENABLE_HYDRATION': JSON.stringify(isUseSSRBundle(userConfig)),
|
|
110
110
|
'process.env.MODERN_ENABLE_RSC': JSON.stringify(Boolean(userConfig.server?.rsc)),
|
|
111
|
+
__MODERN_ENABLE_RSC__: JSON.stringify(Boolean(userConfig.server?.rsc)),
|
|
111
112
|
'process.env.MODERN_MF_APP_SSR': JSON.stringify(isModuleFederationAppSSR)
|
|
112
113
|
}
|
|
113
114
|
},
|
|
@@ -6,15 +6,23 @@ import { hydrateRoot } from "react-dom/client";
|
|
|
6
6
|
import { RenderLevel } from "../constants.mjs";
|
|
7
7
|
import { wrapRuntimeContextProvider } from "../react/wrapper.mjs";
|
|
8
8
|
import { WithCallback } from "./withCallback.mjs";
|
|
9
|
-
const isReact18 = ()=>'true' === process.env.IS_REACT18;
|
|
10
9
|
const runtimeProcess = Reflect.get(globalThis, 'process');
|
|
10
|
+
const runtimeEnvironment = null !== runtimeProcess && 'object' == typeof runtimeProcess ? Reflect.get(runtimeProcess, 'env') : void 0;
|
|
11
|
+
const readRuntimeEnvironment = (name)=>{
|
|
12
|
+
if (null === runtimeEnvironment || 'object' != typeof runtimeEnvironment) return;
|
|
13
|
+
const value = Reflect.get(runtimeEnvironment, name);
|
|
14
|
+
return 'string' == typeof value ? value : void 0;
|
|
15
|
+
};
|
|
11
16
|
const loadableReadyOptions = {
|
|
12
|
-
chunkLoadingGlobal:
|
|
17
|
+
chunkLoadingGlobal: (()=>{
|
|
18
|
+
const configured = readRuntimeEnvironment('MODERN_CHUNK_LOADING_GLOBAL');
|
|
19
|
+
return void 0 === configured || '' === configured ? '__LOADABLE_LOADED_CHUNKS__' : configured;
|
|
20
|
+
})()
|
|
13
21
|
};
|
|
14
|
-
|
|
15
|
-
return hydrateRoot(rootElement, App, {
|
|
22
|
+
function hydrateWithReact(App, rootElement) {
|
|
23
|
+
return Promise.resolve(hydrateRoot(rootElement, App, {
|
|
16
24
|
identifierPrefix: SSR_HYDRATION_ID_PREFIX
|
|
17
|
-
});
|
|
25
|
+
}));
|
|
18
26
|
}
|
|
19
27
|
function hydrate_hydrateRoot(App, context, ModernRender, ModernHydrate) {
|
|
20
28
|
const hydrateContext = {
|
|
@@ -27,9 +35,9 @@ function hydrate_hydrateRoot(App, context, ModernRender, ModernHydrate) {
|
|
|
27
35
|
const callback = ()=>{
|
|
28
36
|
delete hydrateContext._hydration;
|
|
29
37
|
};
|
|
30
|
-
const renderLevel = window?._SSR_DATA?.renderLevel
|
|
31
|
-
const renderMode = window?._SSR_DATA?.mode
|
|
32
|
-
if (
|
|
38
|
+
const renderLevel = window?._SSR_DATA?.renderLevel ?? RenderLevel.CLIENT_RENDER;
|
|
39
|
+
const renderMode = window?._SSR_DATA?.mode ?? 'string';
|
|
40
|
+
if ('stream' === renderMode) return streamSSRHydrate();
|
|
33
41
|
function streamSSRHydrate() {
|
|
34
42
|
if (renderLevel !== RenderLevel.SERVER_RENDER) return ModernRender(wrapRuntimeContextProvider(App, context));
|
|
35
43
|
{
|
|
@@ -43,23 +51,23 @@ function hydrate_hydrateRoot(App, context, ModernRender, ModernHydrate) {
|
|
|
43
51
|
return stringSSRHydrate();
|
|
44
52
|
function stringSSRHydrate() {
|
|
45
53
|
if (renderLevel === RenderLevel.CLIENT_RENDER) return ModernRender(wrapRuntimeContextProvider(App, context));
|
|
46
|
-
|
|
47
|
-
|
|
54
|
+
{
|
|
55
|
+
if (renderLevel === RenderLevel.SERVER_RENDER) return loadableReady(()=>void 0, loadableReadyOptions).then(()=>{
|
|
48
56
|
const SSRApp = ()=>/*#__PURE__*/ jsx(WithCallback, {
|
|
49
57
|
callback: callback,
|
|
50
58
|
children: App
|
|
51
59
|
});
|
|
52
|
-
ModernHydrate(wrapRuntimeContextProvider(/*#__PURE__*/ jsx(SSRApp, {}), hydrateContext))
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
return ModernHydrate(wrapRuntimeContextProvider(/*#__PURE__*/ jsx(SSRApp, {}), hydrateContext));
|
|
61
|
+
});
|
|
62
|
+
const runtimeConsole = Reflect.get(globalThis, 'console');
|
|
63
|
+
if (null !== runtimeConsole && 'object' == typeof runtimeConsole) {
|
|
64
|
+
const warn = Reflect.get(runtimeConsole, 'warn');
|
|
65
|
+
if ('function' == typeof warn) Reflect.apply(warn, runtimeConsole, [
|
|
66
|
+
`unknow render level: ${renderLevel}, execute render()`
|
|
67
|
+
]);
|
|
68
|
+
}
|
|
69
|
+
return ModernRender(wrapRuntimeContextProvider(App, context));
|
|
70
|
+
}
|
|
63
71
|
}
|
|
64
72
|
}
|
|
65
|
-
export { hydrateWithReact, hydrate_hydrateRoot as hydrateRoot
|
|
73
|
+
export { hydrateWithReact, hydrate_hydrateRoot as hydrateRoot };
|
|
@@ -4,39 +4,34 @@ import { HelmetProvider } from "react-helmet-async";
|
|
|
4
4
|
import { InternalRuntimeContext, RuntimeContext, getGlobalEnableRsc } from "../context/index.mjs";
|
|
5
5
|
import { stripRuntimeContextExtensions } from "../context/extensions.mjs";
|
|
6
6
|
import { ensureHelmetContext } from "../context/helmetContext.mjs";
|
|
7
|
-
function
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
function createRscSafeRequestContext(ssrContext) {
|
|
8
|
+
if (void 0 === ssrContext) return {
|
|
9
|
+
request: {},
|
|
10
|
+
response: {
|
|
11
|
+
locals: {}
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const { request, response } = ssrContext;
|
|
14
15
|
return {
|
|
15
|
-
|
|
16
|
-
useJsonScript: ssrContext.useJsonScript,
|
|
17
|
-
htmlModifiers: [],
|
|
18
|
-
baseUrl: ssrContext.baseUrl,
|
|
19
|
-
request: request ? {
|
|
16
|
+
request: {
|
|
20
17
|
url: request.url,
|
|
21
18
|
userAgent: request.userAgent,
|
|
22
19
|
cookie: request.cookie,
|
|
23
20
|
pathname: request.pathname,
|
|
24
|
-
query:
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
query: {
|
|
22
|
+
...request.query
|
|
23
|
+
},
|
|
24
|
+
params: {
|
|
25
|
+
...request.params
|
|
26
|
+
},
|
|
27
|
+
headers: {
|
|
28
|
+
...request.headers
|
|
29
|
+
},
|
|
27
30
|
host: request.host,
|
|
28
31
|
referer: request.referer
|
|
29
|
-
}
|
|
30
|
-
mode: ssrContext.mode,
|
|
31
|
-
loaderFailureMode: ssrContext.loaderFailureMode
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
function createRscSafeRequestContext(ssrContext) {
|
|
35
|
-
const safeSsrContext = createRscSafeSsrContext(ssrContext);
|
|
36
|
-
return {
|
|
37
|
-
request: safeSsrContext?.request || {},
|
|
32
|
+
},
|
|
38
33
|
response: {
|
|
39
|
-
locals:
|
|
34
|
+
locals: response.locals ?? {}
|
|
40
35
|
}
|
|
41
36
|
};
|
|
42
37
|
}
|
|
@@ -52,14 +47,14 @@ function wrapRuntimeContextProvider(App, contextValue) {
|
|
|
52
47
|
...rest
|
|
53
48
|
};
|
|
54
49
|
stripRuntimeContextExtensions(runtimeContextValue);
|
|
55
|
-
if (getGlobalEnableRsc() &&
|
|
50
|
+
if (true === getGlobalEnableRsc() && false === isBrowser) {
|
|
56
51
|
const rscSafeRequestContext = createRscSafeRequestContext(ssrContext);
|
|
57
52
|
const rscInternalContextValue = {
|
|
58
53
|
...internalContextValue,
|
|
59
54
|
context: rscSafeRequestContext,
|
|
60
|
-
requestContext: rscSafeRequestContext
|
|
61
|
-
ssrContext: createRscSafeSsrContext(ssrContext)
|
|
55
|
+
requestContext: rscSafeRequestContext
|
|
62
56
|
};
|
|
57
|
+
delete rscInternalContextValue.ssrContext;
|
|
63
58
|
const rscRuntimeContextValue = {
|
|
64
59
|
...runtimeContextValue,
|
|
65
60
|
context: rscSafeRequestContext,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { getRouterServerSnapshot } from "../../router/runtime/lifecycle.mjs";
|
|
3
|
-
import { handleRSCRedirect } from "../../router/runtime/
|
|
3
|
+
import { handleRSCRedirect } from "../../router/runtime/redirect.mjs";
|
|
4
4
|
import { SSRErrors } from "./tracer.mjs";
|
|
5
5
|
const isRedirectStatus = (status)=>status >= 300 && status <= 399;
|
|
6
6
|
const isNullBodyStatus = (status)=>204 === status || 205 === status || 304 === status;
|
|
@@ -14,12 +14,12 @@ const processRedirect = (headers, status, ctx)=>{
|
|
|
14
14
|
const applyRouterSnapshotResult = (context, onError)=>{
|
|
15
15
|
const routerServerSnapshot = getRouterServerSnapshot(context);
|
|
16
16
|
const routerStatusCode = routerServerSnapshot?.statusCode ?? context.routerContext?.statusCode;
|
|
17
|
-
if (routerStatusCode && 200 !== routerStatusCode) context.ssrContext?.response.status(routerStatusCode);
|
|
17
|
+
if (void 0 !== routerStatusCode && 0 !== routerStatusCode && !Number.isNaN(routerStatusCode) && 200 !== routerStatusCode) context.ssrContext?.response.status(routerStatusCode);
|
|
18
18
|
const errors = Object.values(routerServerSnapshot?.errors || context.routerContext?.errors || {});
|
|
19
19
|
if (errors.length > 0) onError(errors[0], SSRErrors.LOADER_ERROR);
|
|
20
20
|
};
|
|
21
21
|
const createLoaderRedirectResponse = (beforeRenderResult, redirectCtx)=>{
|
|
22
|
-
if (
|
|
22
|
+
if (void 0 === beforeRenderResult || !isRedirectStatus(beforeRenderResult.status)) return;
|
|
23
23
|
if (beforeRenderResult.headers.has('X-Modernjs-Redirect')) return beforeRenderResult;
|
|
24
24
|
const redirectUrl = beforeRenderResult.headers.get('Location') || '/';
|
|
25
25
|
return processRedirect(new Headers({
|
|
@@ -27,7 +27,7 @@ const createLoaderRedirectResponse = (beforeRenderResult, redirectCtx)=>{
|
|
|
27
27
|
}), beforeRenderResult.status, redirectCtx);
|
|
28
28
|
};
|
|
29
29
|
const finalizeRenderResponse = (response, responseProxy, redirectCtx, routerCleanup)=>{
|
|
30
|
-
if (-1 !== responseProxy.status && isRedirectStatus(responseProxy.status) && responseProxy.headers.Location) return processRedirect(new Headers(responseProxy.headers), responseProxy.status, redirectCtx);
|
|
30
|
+
if (-1 !== responseProxy.status && isRedirectStatus(responseProxy.status) && void 0 !== responseProxy.headers.Location && '' !== responseProxy.headers.Location) return processRedirect(new Headers(responseProxy.headers), responseProxy.status, redirectCtx);
|
|
31
31
|
Object.entries(responseProxy.headers).forEach(([key, value])=>{
|
|
32
32
|
response.headers.set(key, value);
|
|
33
33
|
});
|
|
@@ -44,7 +44,7 @@ function getMatchedRouteAssets(runtimeContext, routeManifest) {
|
|
|
44
44
|
return matchedRouteIds.flatMap((routeId)=>routeAssets[routeId]?.assets ?? []);
|
|
45
45
|
}
|
|
46
46
|
function getMatchedRouteChunks(runtimeContext, routeManifest, routeAssetToChunk) {
|
|
47
|
-
if (
|
|
47
|
+
if (void 0 === routeManifest) return [];
|
|
48
48
|
return getMatchedRouteAssets(runtimeContext, routeManifest).map(routeAssetToChunk);
|
|
49
49
|
}
|
|
50
50
|
const orderHydrationScriptChunks = ({ asyncEntryChunks, collectedChunks, matchedRouteChunks, entryName })=>{
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
-
import { matchRoutes } from "@modern-js/runtime-utils/router";
|
|
3
2
|
import { getRouterMatchedRouteIds } from "../../../router/runtime/lifecycle.mjs";
|
|
4
3
|
import { CHUNK_CSS_PLACEHOLDER } from "../constants.mjs";
|
|
5
4
|
import { createFederatedCssLinks } from "../federatedCss.mjs";
|
|
@@ -28,20 +27,12 @@ async function buildShellBeforeTemplate(beforeAppTemplate, options) {
|
|
|
28
27
|
});
|
|
29
28
|
return safeReplace(template, CHUNK_CSS_PLACEHOLDER, css);
|
|
30
29
|
async function getCssChunks() {
|
|
31
|
-
const { routeManifest
|
|
30
|
+
const { routeManifest } = runtimeContext;
|
|
32
31
|
const routeAssets = routeManifest?.routeAssets;
|
|
33
32
|
if (!routeAssets) return '';
|
|
34
33
|
let matchedRouteManifests = [];
|
|
35
34
|
const matchedRouteIds = getRouterMatchedRouteIds(runtimeContext);
|
|
36
35
|
if (matchedRouteIds?.length) matchedRouteManifests = matchedRouteIds.map((routeId)=>routeAssets[routeId]).filter(Boolean);
|
|
37
|
-
else if (routerContext && routes) {
|
|
38
|
-
const matches = matchRoutes(routes, routerContext.location, routerContext.basename);
|
|
39
|
-
matchedRouteManifests = matches?.map((match, index)=>{
|
|
40
|
-
if (!index) return;
|
|
41
|
-
const routeId = match.route.id;
|
|
42
|
-
if (routeId) return routeAssets[routeId];
|
|
43
|
-
}).filter((routeManifest)=>void 0 !== routeManifest) ?? [];
|
|
44
|
-
}
|
|
45
36
|
const asyncEntry = routeAssets[`async-${entryName}`];
|
|
46
37
|
if (asyncEntry) matchedRouteManifests.push(asyncEntry);
|
|
47
38
|
const cssChunks = matchedRouteManifests.reduce((chunks, routeManifest)=>{
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
-
import { isRouteErrorResponse } from "
|
|
2
|
+
import { isRouteErrorResponse } from "../../router/runtime/routerHelper.mjs";
|
|
3
3
|
function attributesToString(attributes) {
|
|
4
4
|
return Object.entries(attributes).reduce((str, [key, value])=>void 0 === value ? str : `${str} ${key}="${value}"`, '');
|
|
5
5
|
}
|
|
@@ -8,24 +8,24 @@ function distributedSsrFragmentKey(remote, expose) {
|
|
|
8
8
|
}
|
|
9
9
|
function getDistributedSsrFragmentContext(response) {
|
|
10
10
|
const locals = response?.locals;
|
|
11
|
-
if (
|
|
12
|
-
const context = locals[DISTRIBUTED_SSR_FRAGMENTS_LOCALS_KEY];
|
|
13
|
-
if (
|
|
11
|
+
if ('object' != typeof locals || null === locals) return;
|
|
12
|
+
const context = DISTRIBUTED_SSR_FRAGMENTS_LOCALS_KEY in locals ? locals[DISTRIBUTED_SSR_FRAGMENTS_LOCALS_KEY] : void 0;
|
|
13
|
+
if ('object' != typeof context || null === context) return;
|
|
14
14
|
return context;
|
|
15
15
|
}
|
|
16
16
|
function useDistributedSsrFragmentProps({ boundaryId, expose }) {
|
|
17
17
|
const runtimeContext = useRuntimeContext();
|
|
18
18
|
const locals = runtimeContext.requestContext?.response?.locals;
|
|
19
|
-
const request =
|
|
20
|
-
if (
|
|
21
|
-
const props = request.props;
|
|
22
|
-
if (
|
|
19
|
+
const request = 'object' == typeof locals && null !== locals && DISTRIBUTED_SSR_FRAGMENT_REQUEST_LOCALS_KEY in locals ? locals[DISTRIBUTED_SSR_FRAGMENT_REQUEST_LOCALS_KEY] : void 0;
|
|
20
|
+
if ('object' != typeof request || null === request || !('boundaryId' in request) || request.boundaryId !== boundaryId || !('expose' in request) || request.expose !== expose) throw new Error(`Distributed SSR fragment request contract mismatch for ${boundaryId} ${expose}.`);
|
|
21
|
+
const props = 'props' in request ? request.props : void 0;
|
|
22
|
+
if ('object' != typeof props || null === props || Array.isArray(props)) throw new Error(`Distributed SSR fragment request props must be an object for ${boundaryId} ${expose}.`);
|
|
23
23
|
return props;
|
|
24
24
|
}
|
|
25
25
|
function isThenable(value) {
|
|
26
|
-
return 'function' == typeof value.then;
|
|
26
|
+
return void 0 !== value && 'then' in value && 'function' == typeof value.then;
|
|
27
27
|
}
|
|
28
|
-
function DistributedSsrBoundary({ children, expose, fallback, fragmentProps
|
|
28
|
+
function DistributedSsrBoundary({ children, expose, fallback, fragmentProps, remote }) {
|
|
29
29
|
const runtimeContext = useRuntimeContext();
|
|
30
30
|
const key = distributedSsrFragmentKey(remote, expose);
|
|
31
31
|
const attributes = {
|
|
@@ -36,12 +36,13 @@ function DistributedSsrBoundary({ children, expose, fallback, fragmentProps = {}
|
|
|
36
36
|
children: children
|
|
37
37
|
});
|
|
38
38
|
const fragmentContext = getDistributedSsrFragmentContext(runtimeContext.requestContext?.response);
|
|
39
|
-
if (
|
|
39
|
+
if (void 0 === fragmentContext) return /*#__PURE__*/ jsx("div", {
|
|
40
40
|
...attributes,
|
|
41
41
|
children: children
|
|
42
42
|
});
|
|
43
|
-
const
|
|
44
|
-
|
|
43
|
+
const resolverFragmentProps = void 0 === fragmentProps ? {} : Object.fromEntries(Object.entries(fragmentProps));
|
|
44
|
+
const fragmentOrPromise = fragmentContext.resolve?.(remote, expose, resolverFragmentProps) ?? fragmentContext.fragments?.[key];
|
|
45
|
+
if (isThenable(fragmentOrPromise)) throw fragmentOrPromise;
|
|
45
46
|
const fragment = fragmentOrPromise;
|
|
46
47
|
if (fragment?.status === 'ready') return /*#__PURE__*/ jsx("div", {
|
|
47
48
|
...attributes,
|
|
@@ -34,7 +34,7 @@ function staleRecordResult(ref, env, ageMs, maxStaleMs) {
|
|
|
34
34
|
}
|
|
35
35
|
function createLastKnownGoodProvider(options) {
|
|
36
36
|
const storage = options.storage ?? createInMemoryLkgStorage();
|
|
37
|
-
const now = options.now ?? (()=>
|
|
37
|
+
const now = options.now ?? (()=>Math.floor(performance.timeOrigin + performance.now()));
|
|
38
38
|
const maxStaleMs = options.freshness?.maxStaleMs;
|
|
39
39
|
async function serveFromCache(ref, env, fallback) {
|
|
40
40
|
const key = deliveryUnitResolutionKey(ref.unitId, env);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
+
import { wait } from "@modern-js/utils/universal";
|
|
2
3
|
const DEFAULT_ATTEMPTS = 3;
|
|
3
4
|
const DEFAULT_RETRY_DELAY_MS = 100;
|
|
4
5
|
const DEFAULT_TIMEOUT_MS = 1000;
|
|
@@ -44,7 +45,7 @@ const isRetryableError = (error)=>{
|
|
|
44
45
|
return error instanceof TypeError || /(?:fetch failed|network|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EAI_AGAIN)/i.test(message);
|
|
45
46
|
};
|
|
46
47
|
const isHttpManifestUrl = (id)=>{
|
|
47
|
-
if (
|
|
48
|
+
if (void 0 === id || 0 === id.length) return false;
|
|
48
49
|
try {
|
|
49
50
|
const url = new URL(id);
|
|
50
51
|
return ('http:' === url.protocol || 'https:' === url.protocol) && url.pathname.endsWith('.json');
|
|
@@ -52,47 +53,35 @@ const isHttpManifestUrl = (id)=>{
|
|
|
52
53
|
return false;
|
|
53
54
|
}
|
|
54
55
|
};
|
|
55
|
-
const defaultWait = (milliseconds)=>
|
|
56
|
-
|
|
56
|
+
const defaultWait = (milliseconds)=>wait(milliseconds).then(()=>void 0);
|
|
57
|
+
const fetchWithTimeout = (fetchImpl, url, timeoutMs)=>fetchImpl(url, {
|
|
58
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
57
59
|
});
|
|
58
|
-
const fetchWithTimeout = async (fetchImpl, url, timeoutMs)=>{
|
|
59
|
-
const controller = new AbortController();
|
|
60
|
-
const timeout = setTimeout(()=>controller.abort(), timeoutMs);
|
|
61
|
-
try {
|
|
62
|
-
return await fetchImpl(url, {
|
|
63
|
-
signal: controller.signal
|
|
64
|
-
});
|
|
65
|
-
} finally{
|
|
66
|
-
clearTimeout(timeout);
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
60
|
const createModuleFederationManifestRecoveryPlugin = (options = {})=>{
|
|
70
61
|
const attempts = clampInteger(options.attempts, DEFAULT_ATTEMPTS, 1, MAX_ATTEMPTS);
|
|
71
62
|
const retryDelayMs = clampInteger(options.retryDelayMs, DEFAULT_RETRY_DELAY_MS, 0, MAX_RETRY_DELAY_MS);
|
|
72
63
|
const timeoutMs = clampInteger(options.timeoutMs, DEFAULT_TIMEOUT_MS, 1, MAX_TIMEOUT_MS);
|
|
73
64
|
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
74
65
|
const waitImpl = options.waitImpl ?? defaultWait;
|
|
66
|
+
const recoverManifest = (url, attempt)=>{
|
|
67
|
+
const fetchManifest = ()=>Promise.resolve().then(()=>fetchWithTimeout(fetchImpl, url, timeoutMs)).then((response)=>{
|
|
68
|
+
if (!response.ok) {
|
|
69
|
+
if (!RETRYABLE_HTTP_STATUSES.has(response.status) || attempt === attempts - 1) return;
|
|
70
|
+
return recoverManifest(url, attempt + 1);
|
|
71
|
+
}
|
|
72
|
+
return Promise.resolve().then(()=>response.json()).then((manifest)=>manifest, ()=>void 0);
|
|
73
|
+
}, (error)=>{
|
|
74
|
+
if (!isRetryableError(error) || attempt === attempts - 1) return;
|
|
75
|
+
return recoverManifest(url, attempt + 1);
|
|
76
|
+
});
|
|
77
|
+
if (attempt > 0 && retryDelayMs > 0) return waitImpl(retryDelayMs).then(fetchManifest);
|
|
78
|
+
return fetchManifest();
|
|
79
|
+
};
|
|
75
80
|
return {
|
|
76
81
|
name: 'modern-js-manifest-recovery-plugin',
|
|
77
|
-
|
|
78
|
-
if ('afterResolve' !== args.lifecycle || !isHttpManifestUrl(args.id) || !isRetryableError(args.error) || 'function' != typeof fetchImpl) return;
|
|
79
|
-
|
|
80
|
-
if (attempt > 0 && retryDelayMs > 0) await waitImpl(retryDelayMs);
|
|
81
|
-
try {
|
|
82
|
-
const response = await fetchWithTimeout(fetchImpl, args.id, timeoutMs);
|
|
83
|
-
if (!response.ok) {
|
|
84
|
-
if (!RETRYABLE_HTTP_STATUSES.has(response.status) || attempt === attempts - 1) return;
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
try {
|
|
88
|
-
return await response.json();
|
|
89
|
-
} catch {
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
} catch (error) {
|
|
93
|
-
if (!isRetryableError(error) || attempt === attempts - 1) break;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
82
|
+
errorLoadRemote (args) {
|
|
83
|
+
if ('afterResolve' !== args.lifecycle || !isHttpManifestUrl(args.id) || !isRetryableError(args.error) || 'function' != typeof fetchImpl) return Promise.resolve(void 0);
|
|
84
|
+
return recoverManifest(args.id, 0);
|
|
96
85
|
}
|
|
97
86
|
};
|
|
98
87
|
};
|
|
@@ -40,8 +40,9 @@ async function generateRoutesForEntry(entrypoint, appContext) {
|
|
|
40
40
|
}
|
|
41
41
|
return routes;
|
|
42
42
|
}
|
|
43
|
-
const generateCode = async (appContext, config, entrypoints, api)=>{
|
|
43
|
+
const generateCode = async (appContext, config, entrypoints, api, options = {})=>{
|
|
44
44
|
const { internalDirectory, srcDirectory, internalSrcAlias, packageName } = appContext;
|
|
45
|
+
const includeRouteServerLoadersInSsrEntry = false !== options.includeRouteServerLoadersInSsrEntry || !isUseRsc(config);
|
|
45
46
|
const hooks = api.getHooks();
|
|
46
47
|
const generatedRoutesByEntry = {};
|
|
47
48
|
const eagerRouteComponentFilesByEntry = new Map();
|
|
@@ -99,6 +100,7 @@ const generateCode = async (appContext, config, entrypoints, api)=>{
|
|
|
99
100
|
internalDirectory,
|
|
100
101
|
splitRouteChunks: config?.output?.splitRouteChunks,
|
|
101
102
|
isRscClientBundle: isUseRsc(config),
|
|
103
|
+
hydrateRscClientRoutes: options.hydrateRscClientRoutes,
|
|
102
104
|
srcDirectory,
|
|
103
105
|
internalSrcAlias: appContext.internalSrcAlias
|
|
104
106
|
})
|
|
@@ -106,12 +108,14 @@ const generateCode = async (appContext, config, entrypoints, api)=>{
|
|
|
106
108
|
if (entrypoint.nestedRoutesEntry && (isUseSSRBundle(config) || isUseRsc(config))) {
|
|
107
109
|
const routesServerFile = getServerLoadersFile(internalDirectory, entryName);
|
|
108
110
|
const filtedRoutesForServer = filterRoutesForServer(routes);
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
if (includeRouteServerLoadersInSsrEntry) {
|
|
112
|
+
const routesForServerLoaderMatches = filterRoutesLoader(routes);
|
|
113
|
+
const code = __rspack_external__templates_mjs_ab577925.routesForServer({
|
|
114
|
+
routesForServerLoaderMatches
|
|
115
|
+
});
|
|
116
|
+
await fs.ensureFile(routesServerFile);
|
|
117
|
+
await fs.writeFile(routesServerFile, code);
|
|
118
|
+
} else await fs.remove(routesServerFile);
|
|
115
119
|
const serverRoutesCode = await __rspack_external__templates_mjs_ab577925.fileSystemRoutes({
|
|
116
120
|
metaName,
|
|
117
121
|
routes: filtedRoutesForServer,
|
|
@@ -121,12 +125,15 @@ const generateCode = async (appContext, config, entrypoints, api)=>{
|
|
|
121
125
|
internalDirectory,
|
|
122
126
|
splitRouteChunks: config?.output?.splitRouteChunks,
|
|
123
127
|
isRscClientBundle: false,
|
|
128
|
+
isolateRouteDataInRscLayer: isUseRsc(config) && options.isolateRouteDataInRscLayer,
|
|
124
129
|
srcDirectory,
|
|
125
130
|
internalSrcAlias: appContext.internalSrcAlias
|
|
126
131
|
});
|
|
127
|
-
await fs.outputFile(path.resolve(internalDirectory, `./${entryName}
|
|
132
|
+
await fs.outputFile(path.resolve(internalDirectory, `./${entryName}/${options.serverRoutesFileName || 'routes.server.js'}`), serverRoutesCode, 'utf8');
|
|
128
133
|
}
|
|
129
|
-
const serverLoaderCombined = __rspack_external__templates_mjs_ab577925.ssrLoaderCombinedModule(entrypoints, entrypoint, config, appContext
|
|
134
|
+
const serverLoaderCombined = __rspack_external__templates_mjs_ab577925.ssrLoaderCombinedModule(entrypoints, entrypoint, config, appContext, {
|
|
135
|
+
includeRouteServerLoaders: includeRouteServerLoadersInSsrEntry
|
|
136
|
+
});
|
|
130
137
|
if (serverLoaderCombined) {
|
|
131
138
|
const serverLoaderFile = getServerCombinedModuleFile(internalDirectory, entryName);
|
|
132
139
|
await fs.outputFile(serverLoaderFile, serverLoaderCombined);
|