@bleedingdev/modern-js-runtime 3.5.0-ultramodern.102 → 3.5.0-ultramodern.103
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/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 +13 -7
- package/dist/cjs/router/cli/code/templates.js +33 -24
- package/dist/cjs/router/cli/handler.js +2 -0
- package/dist/cjs/router/runtime/plugin.js +11 -6
- 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/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 +13 -7
- package/dist/esm/router/cli/code/templates.mjs +33 -24
- package/dist/esm/router/cli/handler.mjs +2 -0
- package/dist/esm/router/runtime/plugin.mjs +13 -8
- 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/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 +13 -7
- package/dist/esm-node/router/cli/code/templates.mjs +33 -24
- package/dist/esm-node/router/cli/handler.mjs +2 -0
- package/dist/esm-node/router/runtime/plugin.mjs +13 -8
- 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/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 +2 -0
- package/dist/types/router/cli/code/templates.d.ts +5 -2
- package/dist/types/router/cli/handler.d.ts +2 -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,3 +1,4 @@
|
|
|
1
|
+
import { wait } from "@modern-js/utils/universal";
|
|
1
2
|
const DEFAULT_ATTEMPTS = 3;
|
|
2
3
|
const DEFAULT_RETRY_DELAY_MS = 100;
|
|
3
4
|
const DEFAULT_TIMEOUT_MS = 1000;
|
|
@@ -43,7 +44,7 @@ const isRetryableError = (error)=>{
|
|
|
43
44
|
return error instanceof TypeError || /(?:fetch failed|network|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EAI_AGAIN)/i.test(message);
|
|
44
45
|
};
|
|
45
46
|
const isHttpManifestUrl = (id)=>{
|
|
46
|
-
if (
|
|
47
|
+
if (void 0 === id || 0 === id.length) return false;
|
|
47
48
|
try {
|
|
48
49
|
const url = new URL(id);
|
|
49
50
|
return ('http:' === url.protocol || 'https:' === url.protocol) && url.pathname.endsWith('.json');
|
|
@@ -51,47 +52,35 @@ const isHttpManifestUrl = (id)=>{
|
|
|
51
52
|
return false;
|
|
52
53
|
}
|
|
53
54
|
};
|
|
54
|
-
const defaultWait = (milliseconds)=>
|
|
55
|
-
|
|
55
|
+
const defaultWait = (milliseconds)=>wait(milliseconds).then(()=>void 0);
|
|
56
|
+
const fetchWithTimeout = (fetchImpl, url, timeoutMs)=>fetchImpl(url, {
|
|
57
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
56
58
|
});
|
|
57
|
-
const fetchWithTimeout = async (fetchImpl, url, timeoutMs)=>{
|
|
58
|
-
const controller = new AbortController();
|
|
59
|
-
const timeout = setTimeout(()=>controller.abort(), timeoutMs);
|
|
60
|
-
try {
|
|
61
|
-
return await fetchImpl(url, {
|
|
62
|
-
signal: controller.signal
|
|
63
|
-
});
|
|
64
|
-
} finally{
|
|
65
|
-
clearTimeout(timeout);
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
59
|
const createModuleFederationManifestRecoveryPlugin = (options = {})=>{
|
|
69
60
|
const attempts = clampInteger(options.attempts, DEFAULT_ATTEMPTS, 1, MAX_ATTEMPTS);
|
|
70
61
|
const retryDelayMs = clampInteger(options.retryDelayMs, DEFAULT_RETRY_DELAY_MS, 0, MAX_RETRY_DELAY_MS);
|
|
71
62
|
const timeoutMs = clampInteger(options.timeoutMs, DEFAULT_TIMEOUT_MS, 1, MAX_TIMEOUT_MS);
|
|
72
63
|
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
73
64
|
const waitImpl = options.waitImpl ?? defaultWait;
|
|
65
|
+
const recoverManifest = (url, attempt)=>{
|
|
66
|
+
const fetchManifest = ()=>Promise.resolve().then(()=>fetchWithTimeout(fetchImpl, url, timeoutMs)).then((response)=>{
|
|
67
|
+
if (!response.ok) {
|
|
68
|
+
if (!RETRYABLE_HTTP_STATUSES.has(response.status) || attempt === attempts - 1) return;
|
|
69
|
+
return recoverManifest(url, attempt + 1);
|
|
70
|
+
}
|
|
71
|
+
return Promise.resolve().then(()=>response.json()).then((manifest)=>manifest, ()=>void 0);
|
|
72
|
+
}, (error)=>{
|
|
73
|
+
if (!isRetryableError(error) || attempt === attempts - 1) return;
|
|
74
|
+
return recoverManifest(url, attempt + 1);
|
|
75
|
+
});
|
|
76
|
+
if (attempt > 0 && retryDelayMs > 0) return waitImpl(retryDelayMs).then(fetchManifest);
|
|
77
|
+
return fetchManifest();
|
|
78
|
+
};
|
|
74
79
|
return {
|
|
75
80
|
name: 'modern-js-manifest-recovery-plugin',
|
|
76
|
-
|
|
77
|
-
if ('afterResolve' !== args.lifecycle || !isHttpManifestUrl(args.id) || !isRetryableError(args.error) || 'function' != typeof fetchImpl) return;
|
|
78
|
-
|
|
79
|
-
if (attempt > 0 && retryDelayMs > 0) await waitImpl(retryDelayMs);
|
|
80
|
-
try {
|
|
81
|
-
const response = await fetchWithTimeout(fetchImpl, args.id, timeoutMs);
|
|
82
|
-
if (!response.ok) {
|
|
83
|
-
if (!RETRYABLE_HTTP_STATUSES.has(response.status) || attempt === attempts - 1) return;
|
|
84
|
-
continue;
|
|
85
|
-
}
|
|
86
|
-
try {
|
|
87
|
-
return await response.json();
|
|
88
|
-
} catch {
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
} catch (error) {
|
|
92
|
-
if (!isRetryableError(error) || attempt === attempts - 1) break;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
81
|
+
errorLoadRemote (args) {
|
|
82
|
+
if ('afterResolve' !== args.lifecycle || !isHttpManifestUrl(args.id) || !isRetryableError(args.error) || 'function' != typeof fetchImpl) return Promise.resolve(void 0);
|
|
83
|
+
return recoverManifest(args.id, 0);
|
|
95
84
|
}
|
|
96
85
|
};
|
|
97
86
|
};
|
|
@@ -41,6 +41,7 @@ async function generateRoutesForEntry(entrypoint, appContext) {
|
|
|
41
41
|
}
|
|
42
42
|
const generateCode = async (appContext, config, entrypoints, api, options = {})=>{
|
|
43
43
|
const { internalDirectory, srcDirectory, internalSrcAlias, packageName } = appContext;
|
|
44
|
+
const includeRouteServerLoadersInSsrEntry = false !== options.includeRouteServerLoadersInSsrEntry || !isUseRsc(config);
|
|
44
45
|
const hooks = api.getHooks();
|
|
45
46
|
const generatedRoutesByEntry = {};
|
|
46
47
|
const eagerRouteComponentFilesByEntry = new Map();
|
|
@@ -106,12 +107,14 @@ const generateCode = async (appContext, config, entrypoints, api, options = {})=
|
|
|
106
107
|
if (entrypoint.nestedRoutesEntry && (isUseSSRBundle(config) || isUseRsc(config))) {
|
|
107
108
|
const routesServerFile = getServerLoadersFile(internalDirectory, entryName);
|
|
108
109
|
const filtedRoutesForServer = filterRoutesForServer(routes);
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
110
|
+
if (includeRouteServerLoadersInSsrEntry) {
|
|
111
|
+
const routesForServerLoaderMatches = filterRoutesLoader(routes);
|
|
112
|
+
const code = __rspack_external__templates_mjs_ab577925.routesForServer({
|
|
113
|
+
routesForServerLoaderMatches
|
|
114
|
+
});
|
|
115
|
+
await fs.ensureFile(routesServerFile);
|
|
116
|
+
await fs.writeFile(routesServerFile, code);
|
|
117
|
+
} else await fs.remove(routesServerFile);
|
|
115
118
|
const serverRoutesCode = await __rspack_external__templates_mjs_ab577925.fileSystemRoutes({
|
|
116
119
|
metaName,
|
|
117
120
|
routes: filtedRoutesForServer,
|
|
@@ -121,12 +124,15 @@ const generateCode = async (appContext, config, entrypoints, api, options = {})=
|
|
|
121
124
|
internalDirectory,
|
|
122
125
|
splitRouteChunks: config?.output?.splitRouteChunks,
|
|
123
126
|
isRscClientBundle: false,
|
|
127
|
+
isolateRouteDataInRscLayer: isUseRsc(config) && options.isolateRouteDataInRscLayer,
|
|
124
128
|
srcDirectory,
|
|
125
129
|
internalSrcAlias: appContext.internalSrcAlias
|
|
126
130
|
});
|
|
127
131
|
await fs.outputFile(path.resolve(internalDirectory, `./${entryName}/${options.serverRoutesFileName || 'routes.server.js'}`), serverRoutesCode, 'utf8');
|
|
128
132
|
}
|
|
129
|
-
const serverLoaderCombined = __rspack_external__templates_mjs_ab577925.ssrLoaderCombinedModule(entrypoints, entrypoint, config, appContext
|
|
133
|
+
const serverLoaderCombined = __rspack_external__templates_mjs_ab577925.ssrLoaderCombinedModule(entrypoints, entrypoint, config, appContext, {
|
|
134
|
+
includeRouteServerLoaders: includeRouteServerLoadersInSsrEntry
|
|
135
|
+
});
|
|
130
136
|
if (serverLoaderCombined) {
|
|
131
137
|
const serverLoaderFile = getServerCombinedModuleFile(internalDirectory, entryName);
|
|
132
138
|
await fs.outputFile(serverLoaderFile, serverLoaderCombined);
|
|
@@ -89,7 +89,7 @@ async function hasUseClientDirective(componentPath, srcDirectory, internalSrcAli
|
|
|
89
89
|
await fh?.close();
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
-
const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry, entryName, internalDirectory, splitRouteChunks = true, isRscClientBundle = false, hydrateRscClientRoutes = false, srcDirectory, internalSrcAlias })=>{
|
|
92
|
+
const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry, entryName, internalDirectory, splitRouteChunks = true, isRscClientBundle = false, hydrateRscClientRoutes = false, isolateRouteDataInRscLayer = false, srcDirectory, internalSrcAlias })=>{
|
|
93
93
|
const components = [];
|
|
94
94
|
const loadings = [];
|
|
95
95
|
const errors = [];
|
|
@@ -181,9 +181,9 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
|
|
|
181
181
|
component = `component_${components.length - 1}`;
|
|
182
182
|
}
|
|
183
183
|
const isClientComponent = 'nested' === route.type && Boolean(route._component) && Boolean(srcDirectory) && Boolean(internalSrcAlias) && await hasUseClientDirective(route._component, srcDirectory, internalSrcAlias);
|
|
184
|
-
const shouldHydrateRscRoute = hydrateRscClientRoutes && isRscClientBundle && !isClientComponent && !route.loader && !route.data;
|
|
184
|
+
const shouldHydrateRscRoute = hydrateRscClientRoutes && isRscClientBundle && !isClientComponent && ('nested' !== route.type || !route.loader && !route.data);
|
|
185
185
|
const shouldIncludeClientBundle = !isRscClientBundle || isClientComponent || shouldHydrateRscRoute;
|
|
186
|
-
if (route.isRoot && route._component && shouldIncludeClientBundle) rootLayoutCode = `import RootLayout from '${route._component}'`;
|
|
186
|
+
if ('nested' === route.type && route.isRoot && route._component && shouldIncludeClientBundle) rootLayoutCode = `import RootLayout from '${route._component}'`;
|
|
187
187
|
const finalRoute = {
|
|
188
188
|
...route,
|
|
189
189
|
loading,
|
|
@@ -244,32 +244,30 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
|
|
|
244
244
|
const importComponentsCode = components.map((component, index)=>`import component_${index} from '${component}';\n`).join('');
|
|
245
245
|
const importErrorComponentsCode = errors.map((error, index)=>`import error_${index} from '${error}';\n`).join('');
|
|
246
246
|
let importLoadersCode = '';
|
|
247
|
-
|
|
247
|
+
const isolatedRouteDataDirectory = path.join(internalDirectory, entryName, '__rsc_route_data__');
|
|
248
|
+
await fs.remove(isolatedRouteDataDirectory);
|
|
249
|
+
if (isolateRouteDataInRscLayer) await fs.ensureDir(isolatedRouteDataDirectory);
|
|
250
|
+
for (const [key, loaderInfo] of Object.entries(loadersMap)){
|
|
248
251
|
const { route } = loaderInfo;
|
|
249
|
-
|
|
252
|
+
const loaderRequest = `${slash(loaderInfo.filePath)}${getDataLoaderPath({
|
|
250
253
|
loaderId: key,
|
|
251
254
|
clientData: loaderInfo.clientData,
|
|
252
|
-
action: route.action,
|
|
255
|
+
action: route.action || false,
|
|
253
256
|
inline: loaderInfo.inline,
|
|
254
257
|
routeId: loaderInfo.routeId,
|
|
255
258
|
inValidSSRRoute: loaderInfo.inValidSSRRoute
|
|
256
|
-
})}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
action:
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
action: false,
|
|
269
|
-
inline: loaderInfo.inline,
|
|
270
|
-
routeId: loaderInfo.routeId,
|
|
271
|
-
inValidSSRRoute: loaderInfo.inValidSSRRoute
|
|
272
|
-
})}";\n`;
|
|
259
|
+
})}`;
|
|
260
|
+
let loaderImport = loaderRequest;
|
|
261
|
+
if (isolateRouteDataInRscLayer) {
|
|
262
|
+
const isolatedLoaderFile = path.join(isolatedRouteDataDirectory, `${key}.js`);
|
|
263
|
+
const isolatedLoaderCode = loaderInfo.inline ? route.action ? `export { loader, action } from ${JSON.stringify(loaderRequest)};` : `export { loader } from ${JSON.stringify(loaderRequest)};` : `export { default } from ${JSON.stringify(loaderRequest)};`;
|
|
264
|
+
await fs.outputFile(isolatedLoaderFile, isolatedLoaderCode, 'utf8');
|
|
265
|
+
loaderImport = `./__rsc_route_data__/${key}.js`;
|
|
266
|
+
}
|
|
267
|
+
if (loaderInfo.inline) if (route.action) importLoadersCode += `import { loader as ${key}, action as action_${loaderInfo.loaderId} } from "${loaderImport}";\n`;
|
|
268
|
+
else importLoadersCode += `import { loader as ${key} } from "${loaderImport}";\n`;
|
|
269
|
+
else importLoadersCode += `import ${key} from "${loaderImport}";\n`;
|
|
270
|
+
}
|
|
273
271
|
let importConfigsCode = '';
|
|
274
272
|
for (const [key, configPath] of Object.entries(configsMap))importConfigsCode += `import * as ${key} from "${slash(configPath)}";\n`;
|
|
275
273
|
await fs.ensureFile(loadersMapFile);
|
|
@@ -295,7 +293,7 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
|
|
|
295
293
|
${routeComponentsCode}
|
|
296
294
|
`;
|
|
297
295
|
};
|
|
298
|
-
function ssrLoaderCombinedModule(entrypoints, entrypoint, config, appContext) {
|
|
296
|
+
function ssrLoaderCombinedModule(entrypoints, entrypoint, config, appContext, options = {}) {
|
|
299
297
|
const { entryName, isMainEntry } = entrypoint;
|
|
300
298
|
const { packageName } = appContext;
|
|
301
299
|
const ssr = getEntryOptions(entryName, isMainEntry, config.server.ssr, config.server.ssrByEntries, packageName);
|
|
@@ -303,6 +301,17 @@ function ssrLoaderCombinedModule(entrypoints, entrypoint, config, appContext) {
|
|
|
303
301
|
if (entrypoint.nestedRoutesEntry && (ssr || ssg)) {
|
|
304
302
|
const serverLoaderRuntime = require.resolve('@modern-js/plugin-data-loader/runtime');
|
|
305
303
|
const serverLoadersFile = './route-server-loaders.js';
|
|
304
|
+
const includeRouteServerLoaders = false !== options.includeRouteServerLoaders;
|
|
305
|
+
if (!includeRouteServerLoaders) {
|
|
306
|
+
if (!config.source.enableAsyncEntry) return `export * from "${slash(serverLoaderRuntime)}"`;
|
|
307
|
+
return `
|
|
308
|
+
async function loadModules() {
|
|
309
|
+
return import("${slash(serverLoaderRuntime)}");
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export { loadModules };
|
|
313
|
+
`;
|
|
314
|
+
}
|
|
306
315
|
const combinedModule = `export * from "${slash(serverLoaderRuntime)}"; export * from "${serverLoadersFile}"`;
|
|
307
316
|
if (!config.source.enableAsyncEntry) return combinedModule;
|
|
308
317
|
return `
|
|
@@ -22,6 +22,8 @@ async function handleGeneratorEntryCode(api, entrypoints, options = {}) {
|
|
|
22
22
|
const enableRsc = resolvedConfig?.server?.rsc;
|
|
23
23
|
const routesByEntry = await generateCode(appContext, resolvedConfig, entrypoints, api, {
|
|
24
24
|
hydrateRscClientRoutes: normalizedOptions.hydrateRscClientRoutes,
|
|
25
|
+
includeRouteServerLoadersInSsrEntry: normalizedOptions.includeRouteServerLoadersInSsrEntry,
|
|
26
|
+
isolateRouteDataInRscLayer: normalizedOptions.isolateRouteDataInRscLayer,
|
|
25
27
|
serverRoutesFileName: normalizedOptions.serverRoutesFileName
|
|
26
28
|
});
|
|
27
29
|
await Promise.all(entrypoints.map(async (entrypoint)=>{
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { merge } from "@modern-js/runtime-utils/merge";
|
|
3
|
-
import { RouterProvider, createBrowserRouter, createHashRouter, createRoutesFromElements, useHref, useLocation, useMatches } from "@modern-js/runtime-utils/router";
|
|
3
|
+
import { RouterProvider, createBrowserRouter, createHashRouter, createRoutesFromElements, useHref, useInRouterContext, useLocation, useMatches, useNavigate, useParams } from "@modern-js/runtime-utils/router";
|
|
4
4
|
import { normalizePathname } from "@modern-js/runtime-utils/url";
|
|
5
5
|
import * as __rspack_external_react from "react";
|
|
6
|
-
import { InternalRuntimeContext, getGlobalIsRscClient, getGlobalLayoutApp, getGlobalRoutes } from "../../core/context/index.mjs";
|
|
6
|
+
import { InternalRuntimeContext, getGlobalEnableRsc, getGlobalIsRscClient, getGlobalLayoutApp, getGlobalRoutes } from "../../core/context/index.mjs";
|
|
7
7
|
import { applyRouterRuntimeState } from "./lifecycle.mjs";
|
|
8
|
+
import { Link } from "./PrefetchLink.mjs";
|
|
8
9
|
import { routerProviderRegistryHooks } from "./provider.mjs";
|
|
9
10
|
import { createClientRouterFromPayload } from "./rsc-router.mjs";
|
|
10
11
|
import { createRouteObjectsFromConfig, deserializeErrors, renderRoutes, urlJoin } from "./utils.mjs";
|
|
@@ -38,9 +39,13 @@ const routerPlugin = (userConfig = {})=>({
|
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
context.router = {
|
|
42
|
+
Link: Link,
|
|
41
43
|
useMatches: useMatches,
|
|
42
44
|
useLocation: useLocation,
|
|
43
|
-
useHref: useHref
|
|
45
|
+
useHref: useHref,
|
|
46
|
+
useInRouterContext: useInRouterContext,
|
|
47
|
+
useNavigate: useNavigate,
|
|
48
|
+
useParams: useParams
|
|
44
49
|
};
|
|
45
50
|
Object.defineProperty(context, 'routes', {
|
|
46
51
|
get () {
|
|
@@ -64,7 +69,7 @@ const routerPlugin = (userConfig = {})=>({
|
|
|
64
69
|
};
|
|
65
70
|
let cachedRouter = null;
|
|
66
71
|
const RouterWrapper = (props)=>{
|
|
67
|
-
const routerResult = useRouterCreation(
|
|
72
|
+
const routerResult = useRouterCreation(("u" > typeof __MODERN_ENABLE_RSC__ ? __MODERN_ENABLE_RSC__ : true === getGlobalEnableRsc()) ? {
|
|
68
73
|
...props,
|
|
69
74
|
rscPayload: props?.rscPayload
|
|
70
75
|
} : props, {
|
|
@@ -121,15 +126,15 @@ function useRouterCreation(props, options) {
|
|
|
121
126
|
const baseUrl = selectBasePath(location.pathname).replace(/^\/*/, '/');
|
|
122
127
|
const _basename = '/' === baseUrl ? urlJoin(baseUrl, runtimeContext._internalRouterBaseName || basename || '') : baseUrl;
|
|
123
128
|
const { unstable_getBlockNavState: getBlockNavState } = runtimeContext;
|
|
124
|
-
const rscPayload =
|
|
125
|
-
let hydrationData =
|
|
129
|
+
const rscPayload = ("u" > typeof __MODERN_ENABLE_RSC__ ? __MODERN_ENABLE_RSC__ : true === getGlobalEnableRsc()) && props?.rscPayload ? safeUse(props.rscPayload) : null;
|
|
130
|
+
let hydrationData = "u" > typeof __MODERN_ENABLE_RSC__ ? __MODERN_ENABLE_RSC__ ? window._ROUTER_DATA || rscPayload : window._ROUTER_DATA : true === getGlobalEnableRsc() ? window._ROUTER_DATA || rscPayload : window._ROUTER_DATA;
|
|
126
131
|
return (0, __rspack_external_react.useMemo)(()=>{
|
|
127
132
|
if (hydrationData?.errors) hydrationData = {
|
|
128
133
|
...hydrationData,
|
|
129
134
|
errors: deserializeErrors(hydrationData.errors)
|
|
130
135
|
};
|
|
131
136
|
let routes = null;
|
|
132
|
-
routes =
|
|
137
|
+
routes = ("u" > typeof __MODERN_ENABLE_RSC__ ? __MODERN_ENABLE_RSC__ : true === getGlobalEnableRsc()) && getGlobalIsRscClient() ? createRoutes ? createRoutes() : createRouteObjectsFromConfig({
|
|
133
138
|
routesConfig: finalRouteConfig
|
|
134
139
|
}) : createRoutes ? createRoutes() : createRoutesFromElements(renderRoutes({
|
|
135
140
|
routesConfig: finalRouteConfig,
|
|
@@ -137,7 +142,7 @@ function useRouterCreation(props, options) {
|
|
|
137
142
|
}));
|
|
138
143
|
if (!routes) routes = [];
|
|
139
144
|
const hooks = api.getHooks();
|
|
140
|
-
if (
|
|
145
|
+
if (("u" > typeof __MODERN_ENABLE_RSC__ ? __MODERN_ENABLE_RSC__ : true === getGlobalEnableRsc()) && rscPayload) try {
|
|
141
146
|
const router = createClientRouterFromPayload(rscPayload, routes, _basename);
|
|
142
147
|
return {
|
|
143
148
|
router,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { merge } from "@modern-js/runtime-utils/merge";
|
|
3
3
|
import { createRequestContext } from "@modern-js/runtime-utils/node";
|
|
4
|
-
import { StaticRouterProvider, createRoutesFromElements, createStaticHandler, createStaticRouter } from "@modern-js/runtime-utils/router";
|
|
4
|
+
import { StaticRouterProvider, createRoutesFromElements, createStaticHandler, createStaticRouter, useInRouterContext, useLocation, useNavigate, useParams } from "@modern-js/runtime-utils/router";
|
|
5
5
|
import { time } from "@modern-js/runtime-utils/time";
|
|
6
6
|
import { LOADER_REPORTER_NAME } from "@modern-js/utils/universal/constants";
|
|
7
7
|
import { useContext } from "react";
|
|
@@ -9,6 +9,7 @@ import { InternalRuntimeContext, getGlobalEnableRsc, getGlobalLayoutApp, getGlob
|
|
|
9
9
|
import { setServerPayload } from "../../core/context/serverPayload/index.server.mjs";
|
|
10
10
|
import DeferredDataScripts_node from "./DeferredDataScripts.node.mjs";
|
|
11
11
|
import { applyRouterRuntimeState, createRouterServerSnapshot } from "./lifecycle.mjs";
|
|
12
|
+
import { Link } from "./PrefetchLink.mjs";
|
|
12
13
|
import { routerProviderRegistryHooks } from "./provider.mjs";
|
|
13
14
|
import { RSCStaticRouter, createServerPayload, handleRSCRedirect, prepareRSCRoutes } from "./rsc-router.mjs";
|
|
14
15
|
import { createRouteObjectsFromConfig, renderRoutes, urlJoin } from "./utils.mjs";
|
|
@@ -46,6 +47,13 @@ const routerPlugin = (userConfig = {})=>({
|
|
|
46
47
|
setup: (api)=>{
|
|
47
48
|
let finalRouteConfig = {};
|
|
48
49
|
api.onBeforeRender(async (context, interrupt)=>{
|
|
50
|
+
context.router = {
|
|
51
|
+
Link: Link,
|
|
52
|
+
useInRouterContext: useInRouterContext,
|
|
53
|
+
useLocation: useLocation,
|
|
54
|
+
useNavigate: useNavigate,
|
|
55
|
+
useParams: useParams
|
|
56
|
+
};
|
|
49
57
|
const pluginConfig = api.getRuntimeConfig();
|
|
50
58
|
const { basename = '', routesConfig, createRoutes } = merge(pluginConfig.router || {}, userConfig);
|
|
51
59
|
finalRouteConfig = {
|
|
@@ -134,10 +142,8 @@ const routerPlugin = (userConfig = {})=>({
|
|
|
134
142
|
const enableRsc = getGlobalEnableRsc();
|
|
135
143
|
return (props)=>{
|
|
136
144
|
const context = useContext(InternalRuntimeContext);
|
|
137
|
-
const { routerContext,
|
|
138
|
-
const { nonce, mode, useJsonScript } = ssrContext;
|
|
145
|
+
const { routerContext, routes } = context;
|
|
139
146
|
const { basename } = routerContext;
|
|
140
|
-
const remixRouter = createStaticRouter(routes, routerContext);
|
|
141
147
|
if (enableRsc) return App ? /*#__PURE__*/ jsx(App, {
|
|
142
148
|
children: /*#__PURE__*/ jsx(RSCStaticRouter, {
|
|
143
149
|
basename: basename
|
|
@@ -146,6 +152,8 @@ const routerPlugin = (userConfig = {})=>({
|
|
|
146
152
|
basename: basename
|
|
147
153
|
});
|
|
148
154
|
{
|
|
155
|
+
const { nonce, mode, useJsonScript } = context.ssrContext;
|
|
156
|
+
const remixRouter = createStaticRouter(routes, routerContext);
|
|
149
157
|
const routerWrapper = /*#__PURE__*/ jsxs(Fragment, {
|
|
150
158
|
children: [
|
|
151
159
|
/*#__PURE__*/ jsx(StaticRouterProvider, {
|
|
@@ -16,7 +16,7 @@ function createRouterProviderRealm(registrations) {
|
|
|
16
16
|
const providers = new Map();
|
|
17
17
|
let defaultProvider;
|
|
18
18
|
for (const registration of registrations){
|
|
19
|
-
if (
|
|
19
|
+
if (0 === registration.name.length) throw new Error('[@modern-js/runtime] A router provider realm cannot contain an unnamed provider.');
|
|
20
20
|
if (providers.has(registration.name)) throw new Error(`[@modern-js/runtime] Router provider "${registration.name}" is declared more than once in the same runtime realm.`);
|
|
21
21
|
if (true === registration.isDefault && void 0 !== defaultProvider && defaultProvider !== registration.name) throw new Error(`[@modern-js/runtime] Router provider realm declares both "${defaultProvider}" and "${registration.name}" as defaults.`);
|
|
22
22
|
providers.set(registration.name, registration.factory);
|
|
@@ -26,7 +26,7 @@ function createRouterProviderRealm(registrations) {
|
|
|
26
26
|
...providers.keys()
|
|
27
27
|
]);
|
|
28
28
|
return Object.freeze({
|
|
29
|
-
...defaultProvider ? {
|
|
29
|
+
...void 0 !== defaultProvider ? {
|
|
30
30
|
defaultProvider
|
|
31
31
|
} : {},
|
|
32
32
|
get: (name)=>providers.get(name),
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const handleRSCRedirect = (headers, basename, status)=>{
|
|
2
|
+
const newHeaders = new Headers(headers);
|
|
3
|
+
let redirectUrl = headers.get('Location');
|
|
4
|
+
if ('/' !== basename) redirectUrl = redirectUrl.replace(basename, '');
|
|
5
|
+
newHeaders.set('X-Modernjs-Redirect', redirectUrl);
|
|
6
|
+
newHeaders.set('X-Modernjs-BaseUrl', basename);
|
|
7
|
+
newHeaders.delete('Location');
|
|
8
|
+
return new Response(null, {
|
|
9
|
+
status,
|
|
10
|
+
headers: newHeaders
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
export { handleRSCRedirect };
|
|
@@ -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,
|