@bleedingdev/modern-js-runtime 3.2.0-ultramodern.9 → 3.2.0-ultramodern.90
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 +299 -0
- package/dist/cjs/cli/ssr/index.js +5 -15
- package/dist/cjs/cli/template.server.js +1 -0
- package/dist/cjs/core/react/wrapper.js +9 -3
- package/dist/cjs/core/server/federatedCss.js +47 -0
- package/dist/cjs/core/server/helmet.js +8 -2
- package/dist/cjs/core/server/stream/afterTemplate.js +9 -6
- package/dist/cjs/core/server/stream/beforeTemplate.js +13 -20
- package/dist/cjs/core/server/stream/beforeTemplate.worker.js +98 -0
- package/dist/cjs/core/server/stream/createReadableStream.js +7 -2
- package/dist/cjs/core/server/stream/createReadableStream.worker.js +4 -2
- package/dist/cjs/core/server/stream/shared.js +3 -1
- package/dist/cjs/core/server/string/index.js +6 -6
- package/dist/cjs/core/server/string/loadable.js +33 -7
- package/dist/cjs/exports/head.js +196 -5
- package/dist/cjs/router/cli/code/tanstackTypes.js +116 -51
- package/dist/cjs/router/cli/code/templates.js +1 -8
- package/dist/cjs/router/runtime/tanstack/plugin.js +4 -5
- package/dist/cjs/router/runtime/tanstack/plugin.node.js +2 -13
- package/dist/cjs/router/runtime/tanstack/routeTree.js +47 -4
- package/dist/cjs/rsc/server.worker.js +58 -0
- package/dist/cjs/ssr/serverRender/renderToString/entry.js +9 -8
- package/dist/esm/boundary-debugger/index.mjs +263 -0
- package/dist/esm/cli/ssr/index.mjs +5 -15
- package/dist/esm/cli/template.server.mjs +1 -0
- package/dist/esm/core/react/wrapper.mjs +9 -3
- package/dist/esm/core/server/federatedCss.mjs +13 -0
- package/dist/esm/core/server/helmet.mjs +5 -2
- package/dist/esm/core/server/stream/afterTemplate.mjs +10 -7
- package/dist/esm/core/server/stream/beforeTemplate.mjs +14 -11
- package/dist/esm/core/server/stream/beforeTemplate.worker.mjs +64 -0
- package/dist/esm/core/server/stream/createReadableStream.mjs +7 -2
- package/dist/esm/core/server/stream/createReadableStream.worker.mjs +4 -2
- package/dist/esm/core/server/stream/shared.mjs +3 -1
- package/dist/esm/core/server/string/index.mjs +7 -6
- package/dist/esm/core/server/string/loadable.mjs +33 -7
- package/dist/esm/exports/head.mjs +189 -4
- package/dist/esm/router/cli/code/tanstackTypes.mjs +116 -51
- package/dist/esm/router/cli/code/templates.mjs +1 -8
- package/dist/esm/router/runtime/tanstack/plugin.mjs +8 -9
- package/dist/esm/router/runtime/tanstack/plugin.node.mjs +3 -14
- package/dist/esm/router/runtime/tanstack/routeTree.mjs +47 -4
- package/dist/esm/rsc/server.worker.mjs +1 -0
- package/dist/esm/ssr/serverRender/renderToString/entry.mjs +9 -6
- package/dist/esm-node/boundary-debugger/index.mjs +264 -0
- package/dist/esm-node/cli/ssr/index.mjs +5 -15
- package/dist/esm-node/cli/template.server.mjs +1 -0
- package/dist/esm-node/core/react/wrapper.mjs +9 -3
- package/dist/esm-node/core/server/federatedCss.mjs +14 -0
- package/dist/esm-node/core/server/helmet.mjs +5 -2
- package/dist/esm-node/core/server/stream/afterTemplate.mjs +10 -7
- package/dist/esm-node/core/server/stream/beforeTemplate.mjs +14 -11
- package/dist/esm-node/core/server/stream/beforeTemplate.worker.mjs +65 -0
- package/dist/esm-node/core/server/stream/createReadableStream.mjs +7 -2
- package/dist/esm-node/core/server/stream/createReadableStream.worker.mjs +4 -2
- package/dist/esm-node/core/server/stream/shared.mjs +3 -1
- package/dist/esm-node/core/server/string/index.mjs +7 -6
- package/dist/esm-node/core/server/string/loadable.mjs +33 -7
- package/dist/esm-node/exports/head.mjs +189 -4
- package/dist/esm-node/router/cli/code/tanstackTypes.mjs +116 -51
- package/dist/esm-node/router/cli/code/templates.mjs +1 -8
- package/dist/esm-node/router/runtime/tanstack/plugin.mjs +8 -9
- package/dist/esm-node/router/runtime/tanstack/plugin.node.mjs +3 -14
- package/dist/esm-node/router/runtime/tanstack/routeTree.mjs +47 -4
- package/dist/esm-node/rsc/server.worker.mjs +2 -0
- package/dist/esm-node/ssr/serverRender/renderToString/entry.mjs +9 -6
- package/dist/types/boundary-debugger/index.d.ts +28 -0
- package/dist/types/core/context/runtime.d.ts +4 -0
- package/dist/types/core/server/federatedCss.d.ts +5 -0
- package/dist/types/core/server/helmet.d.ts +5 -3
- package/dist/types/core/server/stream/beforeTemplate.d.ts +1 -0
- package/dist/types/core/server/stream/beforeTemplate.worker.d.ts +10 -0
- package/dist/types/core/server/stream/shared.d.ts +8 -0
- package/dist/types/core/server/string/loadable.d.ts +4 -0
- package/dist/types/exports/head.d.ts +10 -3
- package/dist/types/rsc/server.worker.d.ts +1 -0
- package/package.json +25 -19
|
@@ -78,9 +78,21 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
78
78
|
const topLevel = rootModern ? rootModern.children || [] : routes;
|
|
79
79
|
const imports = [];
|
|
80
80
|
const statements = [];
|
|
81
|
+
const componentImportMap = new Map();
|
|
81
82
|
const loaderImportMap = new Map();
|
|
83
|
+
const usedRouteVarNames = new Set();
|
|
84
|
+
let componentIndex = 0;
|
|
82
85
|
let loaderIndex = 0;
|
|
83
86
|
let routeIndex = 0;
|
|
87
|
+
const getImportNameForComponent = (componentPath)=>{
|
|
88
|
+
if ('string' != typeof componentPath || 0 === componentPath.length) return null;
|
|
89
|
+
const existing = componentImportMap.get(componentPath);
|
|
90
|
+
if (existing) return existing;
|
|
91
|
+
const componentName = `component_${componentIndex++}`;
|
|
92
|
+
imports.push(`import ${componentName} from ${quote(componentPath)};`);
|
|
93
|
+
componentImportMap.set(componentPath, componentName);
|
|
94
|
+
return componentName;
|
|
95
|
+
};
|
|
84
96
|
const getImportNamesForLoader = async (aliasedNoExtPath, inline, hasAction)=>{
|
|
85
97
|
const key = `${inline ? 'inline' : 'default'}:${hasAction ? 'action' : 'loader'}:${aliasedNoExtPath}`;
|
|
86
98
|
const existing = loaderImportMap.get(key);
|
|
@@ -112,10 +124,17 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
112
124
|
actionName
|
|
113
125
|
};
|
|
114
126
|
};
|
|
127
|
+
const reserveRouteVarName = (preferred)=>{
|
|
128
|
+
let candidate = preferred;
|
|
129
|
+
let suffix = 1;
|
|
130
|
+
while(usedRouteVarNames.has(candidate))candidate = `${preferred}_${suffix++}`;
|
|
131
|
+
usedRouteVarNames.add(candidate);
|
|
132
|
+
return candidate;
|
|
133
|
+
};
|
|
115
134
|
const createRouteVarName = (route)=>{
|
|
116
135
|
const id = route.id;
|
|
117
136
|
const base = id ? makeLegalIdentifier(id) : `r_${routeIndex++}`;
|
|
118
|
-
return `route_${base}
|
|
137
|
+
return reserveRouteVarName(`route_${base}`);
|
|
119
138
|
};
|
|
120
139
|
const buildRoute = async (opts)=>{
|
|
121
140
|
const { parentVar, route } = opts;
|
|
@@ -130,6 +149,8 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
130
149
|
const routeOpts = [
|
|
131
150
|
`getParentRoute: () => ${parentVar},`
|
|
132
151
|
];
|
|
152
|
+
const componentName = getImportNameForComponent(route._component);
|
|
153
|
+
if (componentName) routeOpts.push(`component: ${componentName},`);
|
|
133
154
|
if (isPathlessLayout(route)) {
|
|
134
155
|
const id = route.id;
|
|
135
156
|
routeOpts.push(`id: ${quote(id || 'pathless')},`);
|
|
@@ -144,14 +165,16 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
144
165
|
actionName
|
|
145
166
|
});
|
|
146
167
|
if (staticDataSnippet) routeOpts.push(staticDataSnippet);
|
|
147
|
-
statements.push(`const ${varName} = createRoute({\n ${routeOpts.join('\n ')}\n});`);
|
|
148
168
|
const children = route.children;
|
|
169
|
+
const hasChildren = Boolean(children && children.length > 0);
|
|
170
|
+
const routeCtorVarName = hasChildren ? reserveRouteVarName(`${varName}__base`) : varName;
|
|
171
|
+
statements.push(`const ${routeCtorVarName} = createRoute({\n ${routeOpts.join('\n ')}\n});`);
|
|
149
172
|
if (children && children.length > 0) {
|
|
150
173
|
const childVars = await Promise.all(children.map((child)=>buildRoute({
|
|
151
|
-
parentVar:
|
|
174
|
+
parentVar: routeCtorVarName,
|
|
152
175
|
route: child
|
|
153
176
|
})));
|
|
154
|
-
statements.push(
|
|
177
|
+
statements.push(`const ${varName} = ${routeCtorVarName}.addChildren([${childVars.join(', ')}]);`);
|
|
155
178
|
}
|
|
156
179
|
return varName;
|
|
157
180
|
};
|
|
@@ -165,6 +188,8 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
165
188
|
route
|
|
166
189
|
})));
|
|
167
190
|
const rootOpts = [];
|
|
191
|
+
const rootComponentName = getImportNameForComponent(rootModern?._component);
|
|
192
|
+
if (rootComponentName) rootOpts.push(`component: ${rootComponentName},`);
|
|
168
193
|
if (rootLoaderName) rootOpts.push(`loader: modernLoaderToTanstack({ hasSplat: false }, ${rootLoaderName}),`);
|
|
169
194
|
const routerGenTs = `/* eslint-disable */
|
|
170
195
|
// This file is auto-generated by Modern.js. Do not edit manually.
|
|
@@ -198,7 +223,7 @@ function isRedirectResponse(res: Response) {
|
|
|
198
223
|
}
|
|
199
224
|
|
|
200
225
|
function throwTanstackRedirect(location: string) {
|
|
201
|
-
const target = location
|
|
226
|
+
const target = location.length > 0 ? location : '/';
|
|
202
227
|
try {
|
|
203
228
|
void new URL(target);
|
|
204
229
|
throw redirect({ href: target });
|
|
@@ -224,21 +249,87 @@ function createRouteStaticData(opts: {
|
|
|
224
249
|
modernRouteAction?: unknown;
|
|
225
250
|
modernRouteLoader?: unknown;
|
|
226
251
|
}) {
|
|
227
|
-
const staticData:
|
|
252
|
+
const staticData: {
|
|
253
|
+
modernRouteId?: string;
|
|
254
|
+
modernRouteAction?: unknown;
|
|
255
|
+
modernRouteLoader?: unknown;
|
|
256
|
+
} = {};
|
|
228
257
|
|
|
229
|
-
if (opts.modernRouteId) {
|
|
258
|
+
if (typeof opts.modernRouteId === 'string' && opts.modernRouteId.length > 0) {
|
|
230
259
|
staticData.modernRouteId = opts.modernRouteId;
|
|
231
260
|
}
|
|
232
261
|
|
|
233
|
-
if (opts.modernRouteLoader) {
|
|
262
|
+
if (typeof opts.modernRouteLoader !== 'undefined') {
|
|
234
263
|
staticData.modernRouteLoader = opts.modernRouteLoader;
|
|
235
264
|
}
|
|
236
265
|
|
|
237
|
-
if (opts.modernRouteAction) {
|
|
266
|
+
if (typeof opts.modernRouteAction !== 'undefined') {
|
|
238
267
|
staticData.modernRouteAction = opts.modernRouteAction;
|
|
239
268
|
}
|
|
240
269
|
|
|
241
|
-
return
|
|
270
|
+
return staticData;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function getLoaderSignal(ctx: any): AbortSignal {
|
|
274
|
+
const abortSignal = ctx?.abortController?.signal;
|
|
275
|
+
if (abortSignal instanceof AbortSignal) {
|
|
276
|
+
return abortSignal;
|
|
277
|
+
}
|
|
278
|
+
if (ctx?.signal instanceof AbortSignal) {
|
|
279
|
+
return ctx.signal;
|
|
280
|
+
}
|
|
281
|
+
return new AbortController().signal;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function getLoaderHref(ctx: any): string {
|
|
285
|
+
if (typeof ctx?.location === 'string') {
|
|
286
|
+
return ctx.location;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const publicHref = ctx?.location?.publicHref;
|
|
290
|
+
if (typeof publicHref === 'string') {
|
|
291
|
+
return publicHref;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const href = ctx?.location?.href;
|
|
295
|
+
if (typeof href === 'string') {
|
|
296
|
+
return href;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const urlHref = ctx?.location?.url?.href;
|
|
300
|
+
return typeof urlHref === 'string' ? urlHref : '';
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function getLoaderParams(ctx: any): Record<string, string> {
|
|
304
|
+
return typeof ctx?.params === 'object' && ctx.params !== null ? ctx.params : {};
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function handleModernLoaderResult<LoaderResult>(result: LoaderResult): LoaderResult {
|
|
308
|
+
if (isResponse(result)) {
|
|
309
|
+
if (isRedirectResponse(result)) {
|
|
310
|
+
const location = result.headers.get('Location') ?? '/';
|
|
311
|
+
throwTanstackRedirect(location);
|
|
312
|
+
}
|
|
313
|
+
if (result.status === 404) {
|
|
314
|
+
throw notFound();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return result;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function handleModernLoaderError(err: unknown): never {
|
|
322
|
+
if (isResponse(err)) {
|
|
323
|
+
if (isRedirectResponse(err)) {
|
|
324
|
+
const location = err.headers.get('Location') ?? '/';
|
|
325
|
+
throwTanstackRedirect(location);
|
|
326
|
+
}
|
|
327
|
+
if (err.status === 404) {
|
|
328
|
+
throw notFound();
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
throw err;
|
|
242
333
|
}
|
|
243
334
|
|
|
244
335
|
function modernLoaderToTanstack<TLoader extends (args: any) => any>(
|
|
@@ -247,57 +338,31 @@ function modernLoaderToTanstack<TLoader extends (args: any) => any>(
|
|
|
247
338
|
) {
|
|
248
339
|
type LoaderResult = Awaited<ReturnType<TLoader>>;
|
|
249
340
|
|
|
250
|
-
return
|
|
341
|
+
return (ctx: any): Promise<LoaderResult> => {
|
|
251
342
|
try {
|
|
252
|
-
const signal
|
|
253
|
-
ctx?.abortController?.signal ||
|
|
254
|
-
ctx?.signal ||
|
|
255
|
-
new AbortController().signal;
|
|
343
|
+
const signal = getLoaderSignal(ctx);
|
|
256
344
|
const baseRequest: Request | undefined =
|
|
257
345
|
ctx?.context?.request instanceof Request ? ctx.context.request : undefined;
|
|
258
346
|
|
|
259
|
-
const href =
|
|
260
|
-
typeof ctx?.location === 'string'
|
|
261
|
-
? ctx.location
|
|
262
|
-
: ctx?.location?.publicHref ||
|
|
263
|
-
ctx?.location?.href ||
|
|
264
|
-
ctx?.location?.url?.href ||
|
|
265
|
-
'';
|
|
347
|
+
const href = getLoaderHref(ctx);
|
|
266
348
|
|
|
267
|
-
const request = baseRequest
|
|
349
|
+
const request = baseRequest !== undefined
|
|
268
350
|
? new Request(baseRequest, { signal })
|
|
269
351
|
: new Request(href, { signal });
|
|
270
352
|
|
|
271
|
-
const params = mapParamsForModernLoader(ctx
|
|
272
|
-
|
|
273
|
-
const result = await (modernLoader as any)({
|
|
274
|
-
request,
|
|
275
|
-
params,
|
|
276
|
-
context: ctx?.context?.requestContext,
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
if (isResponse(result)) {
|
|
280
|
-
if (isRedirectResponse(result)) {
|
|
281
|
-
const location = result.headers.get('Location') || '/';
|
|
282
|
-
throwTanstackRedirect(location);
|
|
283
|
-
}
|
|
284
|
-
if (result.status === 404) {
|
|
285
|
-
throw notFound();
|
|
286
|
-
}
|
|
287
|
-
}
|
|
353
|
+
const params = mapParamsForModernLoader(getLoaderParams(ctx), opts.hasSplat);
|
|
288
354
|
|
|
289
|
-
return
|
|
355
|
+
return Promise.resolve(
|
|
356
|
+
(modernLoader as any)({
|
|
357
|
+
request,
|
|
358
|
+
params,
|
|
359
|
+
context: ctx?.context?.requestContext,
|
|
360
|
+
}),
|
|
361
|
+
)
|
|
362
|
+
.then((result: LoaderResult) => handleModernLoaderResult(result))
|
|
363
|
+
.catch(handleModernLoaderError);
|
|
290
364
|
} catch (err) {
|
|
291
|
-
|
|
292
|
-
if (isRedirectResponse(err)) {
|
|
293
|
-
const location = err.headers.get('Location') || '/';
|
|
294
|
-
throwTanstackRedirect(location);
|
|
295
|
-
}
|
|
296
|
-
if (err.status === 404) {
|
|
297
|
-
throw notFound();
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
throw err;
|
|
365
|
+
handleModernLoaderError(err);
|
|
301
366
|
}
|
|
302
367
|
};
|
|
303
368
|
}
|
|
@@ -172,16 +172,9 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
|
|
|
172
172
|
webpackChunkName: true
|
|
173
173
|
});
|
|
174
174
|
component = 'string' === ssrMode ? `loadable(${lazyImport})` : `lazy(${lazyImport})`;
|
|
175
|
-
} else
|
|
175
|
+
} else {
|
|
176
176
|
components.push(route._component);
|
|
177
177
|
component = `component_${components.length - 1}`;
|
|
178
|
-
} else {
|
|
179
|
-
lazyImport = createLazyImport({
|
|
180
|
-
componentPath: route._component,
|
|
181
|
-
routeId: route.id,
|
|
182
|
-
eager: true
|
|
183
|
-
});
|
|
184
|
-
component = `lazy(${lazyImport})`;
|
|
185
178
|
}
|
|
186
179
|
} else if (route._component) if (splitRouteChunks) {
|
|
187
180
|
lazyImport = `() => import('${route._component}')`;
|
|
@@ -4,14 +4,15 @@ import { merge } from "@modern-js/runtime-utils/merge";
|
|
|
4
4
|
import { normalizePathname } from "@modern-js/runtime-utils/url";
|
|
5
5
|
import { RouterProvider, createBrowserHistory, createHashHistory, createRouter, useLocation, useMatches, useNavigate, useRouter } from "@tanstack/react-router";
|
|
6
6
|
import { RouterClient } from "@tanstack/react-router/ssr/client";
|
|
7
|
+
import { useContext, useMemo } from "react";
|
|
7
8
|
import { InternalRuntimeContext, getGlobalEnableRsc, getGlobalLayoutApp, getGlobalRoutes } from "../../../core/context/index.mjs";
|
|
8
9
|
import { onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeHydrateRouter } from "../hooks.mjs";
|
|
9
10
|
import { applyRouterRuntimeState } from "../lifecycle.mjs";
|
|
10
11
|
import { createRouteObjectsFromConfig, urlJoin } from "../utils.mjs";
|
|
11
12
|
import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
|
|
13
|
+
import { Link } from "./prefetchLink.mjs";
|
|
12
14
|
import { createRouteTreeFromRouteObjects } from "./routeTree.mjs";
|
|
13
15
|
import { getTanstackRscSerializationAdapters } from "./rsc/client.mjs";
|
|
14
|
-
import * as __rspack_external_react from "react";
|
|
15
16
|
const BLOCKING_SUBSCRIBE_SYMBOL = Symbol.for('@modern-js/plugin-runtime:tanstack-blocking-subscribe');
|
|
16
17
|
const BLOCKING_STATE_SYMBOL = Symbol.for('@modern-js/plugin-runtime:tanstack-blocking-state');
|
|
17
18
|
function normalizeBase(b) {
|
|
@@ -71,6 +72,7 @@ const tanstackRouterPlugin = (userConfig = {})=>({
|
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
74
|
context.router = {
|
|
75
|
+
Link: Link,
|
|
74
76
|
useMatches: useMatches,
|
|
75
77
|
useLocation: useLocation,
|
|
76
78
|
useNavigate: useNavigate,
|
|
@@ -105,10 +107,10 @@ const tanstackRouterPlugin = (userConfig = {})=>({
|
|
|
105
107
|
let cachedRouter = null;
|
|
106
108
|
let cachedRouterBasepath = null;
|
|
107
109
|
const RouterWrapper = ()=>{
|
|
108
|
-
const runtimeContext =
|
|
110
|
+
const runtimeContext = useContext(InternalRuntimeContext);
|
|
109
111
|
const baseUrl = selectBasePath(location.pathname).replace(/^\/*/, '/');
|
|
110
112
|
const _basename = '/' === baseUrl ? urlJoin(baseUrl, runtimeContext._internalRouterBaseName || basename || '') : baseUrl;
|
|
111
|
-
const routeTree =
|
|
113
|
+
const routeTree = useMemo(()=>{
|
|
112
114
|
if (cachedRouteTree) return cachedRouteTree;
|
|
113
115
|
const routeObjects = getRouteObjects();
|
|
114
116
|
if (!routeObjects.length) return null;
|
|
@@ -116,7 +118,7 @@ const tanstackRouterPlugin = (userConfig = {})=>({
|
|
|
116
118
|
return cachedRouteTree;
|
|
117
119
|
}, []);
|
|
118
120
|
if (!routeTree) return App ? /*#__PURE__*/ jsx(App, {}) : null;
|
|
119
|
-
const router =
|
|
121
|
+
const router = useMemo(()=>{
|
|
120
122
|
const lifecycleContext = {
|
|
121
123
|
framework: 'tanstack',
|
|
122
124
|
phase: 'client-create',
|
|
@@ -181,11 +183,8 @@ const tanstackRouterPlugin = (userConfig = {})=>({
|
|
|
181
183
|
router,
|
|
182
184
|
runtimeContext: runtimeState
|
|
183
185
|
});
|
|
184
|
-
const RouterContent = hasSSRBootstrap ? /*#__PURE__*/ jsx(
|
|
185
|
-
|
|
186
|
-
children: /*#__PURE__*/ jsx(RouterClient, {
|
|
187
|
-
router: router
|
|
188
|
-
})
|
|
186
|
+
const RouterContent = hasSSRBootstrap ? /*#__PURE__*/ jsx(RouterClient, {
|
|
187
|
+
router: router
|
|
189
188
|
}) : /*#__PURE__*/ jsx(RouterProvider, {
|
|
190
189
|
router: router
|
|
191
190
|
});
|
|
@@ -6,7 +6,7 @@ import { time } from "@modern-js/runtime-utils/time";
|
|
|
6
6
|
import { LOADER_REPORTER_NAME } from "@modern-js/utils/universal/constants";
|
|
7
7
|
import { RouterProvider, createMemoryHistory, createRouter } from "@tanstack/react-router";
|
|
8
8
|
import { attachRouterServerSsrUtils } from "@tanstack/react-router/ssr/server";
|
|
9
|
-
import {
|
|
9
|
+
import { useContext } from "react";
|
|
10
10
|
import { InternalRuntimeContext, getGlobalEnableRsc, getGlobalLayoutApp, getGlobalRoutes } from "../../../core/context/index.mjs";
|
|
11
11
|
import { applyRouterServerPrepareResult, createRouterServerSnapshot } from "../lifecycle.mjs";
|
|
12
12
|
import { createRouteObjectsFromConfig, urlJoin } from "../utils.mjs";
|
|
@@ -38,13 +38,6 @@ async function preloadMatchedRouteComponents(tanstackRouter) {
|
|
|
38
38
|
]);
|
|
39
39
|
}));
|
|
40
40
|
}
|
|
41
|
-
async function waitForRouterSerialization(tanstackRouter) {
|
|
42
|
-
const serverSsr = tanstackRouter.serverSsr;
|
|
43
|
-
if (!serverSsr || 'function' != typeof serverSsr.onSerializationFinished || serverSsr.isSerializationFinished?.()) return;
|
|
44
|
-
await new Promise((resolve)=>{
|
|
45
|
-
serverSsr.onSerializationFinished?.(resolve);
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
41
|
function htmlEscapeAttr(value) {
|
|
49
42
|
return value.replace(/&/g, '&').replace(/"/g, '"');
|
|
50
43
|
}
|
|
@@ -190,7 +183,6 @@ const tanstackRouterPlugin = (userConfig = {})=>({
|
|
|
190
183
|
await preloadMatchedRouteComponents(serverRouter);
|
|
191
184
|
context.ssrContext?.response.status(tanstackRouter.state.statusCode);
|
|
192
185
|
await serverRouter.serverSsr?.dehydrate?.();
|
|
193
|
-
await waitForRouterSerialization(serverRouter);
|
|
194
186
|
const ssrScriptTags = serverRouter.serverSsr?.takeBufferedScripts?.();
|
|
195
187
|
const hydrationScripts = routerManagedTagsToHtml(ssrScriptTags);
|
|
196
188
|
const matchedRouteIds = getModernRouteIdsFromMatches(serverRouter);
|
|
@@ -228,11 +220,8 @@ const tanstackRouterPlugin = (userConfig = {})=>({
|
|
|
228
220
|
if (!router) return App ? /*#__PURE__*/ jsx(App, {
|
|
229
221
|
...props
|
|
230
222
|
}) : null;
|
|
231
|
-
const routerWrapper = /*#__PURE__*/ jsx(
|
|
232
|
-
|
|
233
|
-
children: /*#__PURE__*/ jsx(RouterProvider, {
|
|
234
|
-
router: router
|
|
235
|
-
})
|
|
223
|
+
const routerWrapper = /*#__PURE__*/ jsx(RouterProvider, {
|
|
224
|
+
router: router
|
|
236
225
|
});
|
|
237
226
|
return App ? /*#__PURE__*/ jsx(App, {
|
|
238
227
|
children: routerWrapper
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { createRootRoute, createRoute, notFound, redirect } from "@tanstack/react-router";
|
|
3
|
+
import { createElement } from "react";
|
|
3
4
|
import { DefaultNotFound } from "../DefaultNotFound.mjs";
|
|
4
5
|
function createTanstackRoute(options) {
|
|
5
6
|
return createRoute(options);
|
|
@@ -44,6 +45,40 @@ function isModernDeferredData(value) {
|
|
|
44
45
|
function normalizeModernLoaderResult(result) {
|
|
45
46
|
return isModernDeferredData(result) ? result.data : result;
|
|
46
47
|
}
|
|
48
|
+
function pickRouteModuleComponent(routeModule, seen = new Set()) {
|
|
49
|
+
if ('function' == typeof routeModule || routeModule && 'object' == typeof routeModule && '$$typeof' in routeModule) return routeModule;
|
|
50
|
+
if (!routeModule || 'object' != typeof routeModule) return;
|
|
51
|
+
if (seen.has(routeModule)) return;
|
|
52
|
+
seen.add(routeModule);
|
|
53
|
+
const module = routeModule;
|
|
54
|
+
for (const candidate of [
|
|
55
|
+
module.default,
|
|
56
|
+
module.Component
|
|
57
|
+
]){
|
|
58
|
+
const component = pickRouteModuleComponent(candidate, seen);
|
|
59
|
+
if (component) return component;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function createServerLazyImportComponent(lazyImport, fallbackComponent) {
|
|
63
|
+
if ("u" > typeof document) return fallbackComponent;
|
|
64
|
+
let resolvedComponent;
|
|
65
|
+
let pendingLoad;
|
|
66
|
+
const load = async ()=>{
|
|
67
|
+
if (resolvedComponent) return resolvedComponent;
|
|
68
|
+
const routeModule = await lazyImport();
|
|
69
|
+
const component = pickRouteModuleComponent(routeModule);
|
|
70
|
+
if (component) resolvedComponent = component;
|
|
71
|
+
return resolvedComponent;
|
|
72
|
+
};
|
|
73
|
+
const Component = (props)=>{
|
|
74
|
+
if (resolvedComponent) return createElement(resolvedComponent, props);
|
|
75
|
+
pendingLoad ||= load();
|
|
76
|
+
throw pendingLoad;
|
|
77
|
+
};
|
|
78
|
+
Component.load = load;
|
|
79
|
+
Component.preload = load;
|
|
80
|
+
return Component;
|
|
81
|
+
}
|
|
47
82
|
function throwTanstackRedirect(location) {
|
|
48
83
|
const target = location || '/';
|
|
49
84
|
try {
|
|
@@ -112,7 +147,7 @@ function wrapModernLoader(modernRoute, modernLoader, revalidationState) {
|
|
|
112
147
|
const signal = ctx?.abortController?.signal || ctx?.signal || new AbortController().signal;
|
|
113
148
|
const baseRequest = ctx?.context?.request instanceof Request ? ctx.context.request : void 0;
|
|
114
149
|
const href = 'string' == typeof ctx?.location ? ctx.location : ctx?.location?.publicHref || ctx?.location?.href || ctx?.location?.url?.href || '';
|
|
115
|
-
const request = baseRequest ? new Request(baseRequest, {
|
|
150
|
+
const request = void 0 !== baseRequest ? new Request(baseRequest, {
|
|
116
151
|
signal
|
|
117
152
|
}) : createModernRequest(href, signal);
|
|
118
153
|
const params = mapParamsForModernLoader({
|
|
@@ -175,7 +210,7 @@ function wrapRouteObjectLoader(route, revalidationState) {
|
|
|
175
210
|
const signal = ctx?.abortController?.signal || ctx?.signal || new AbortController().signal;
|
|
176
211
|
const baseRequest = ctx?.context?.request instanceof Request ? ctx.context.request : void 0;
|
|
177
212
|
const href = 'string' == typeof ctx?.location ? ctx.location : ctx?.location?.publicHref || ctx?.location?.href || ctx?.location?.url?.href || '';
|
|
178
|
-
const request = baseRequest ? new Request(baseRequest, {
|
|
213
|
+
const request = void 0 !== baseRequest ? new Request(baseRequest, {
|
|
179
214
|
signal
|
|
180
215
|
}) : createModernRequest(href, signal);
|
|
181
216
|
const params = mapParamsForRouteObjectLoader({
|
|
@@ -210,10 +245,18 @@ function wrapRouteObjectLoader(route, revalidationState) {
|
|
|
210
245
|
}
|
|
211
246
|
function toRouteComponent(routeObject) {
|
|
212
247
|
const route = routeObject;
|
|
248
|
+
const lazyImport = 'function' == typeof route.lazyImport ? route.lazyImport : void 0;
|
|
249
|
+
const fallbackComponent = route.Component ? route.Component : route.element ? ()=>route.element : void 0;
|
|
250
|
+
if (lazyImport && fallbackComponent) return createServerLazyImportComponent(lazyImport, fallbackComponent);
|
|
213
251
|
if (route.Component) return route.Component;
|
|
214
252
|
const element = route.element;
|
|
215
253
|
if (element) return ()=>element;
|
|
216
254
|
}
|
|
255
|
+
function toModernRouteComponent(route) {
|
|
256
|
+
const component = route.component || void 0;
|
|
257
|
+
if ('function' == typeof route.lazyImport && component) return createServerLazyImportComponent(route.lazyImport, component);
|
|
258
|
+
return component;
|
|
259
|
+
}
|
|
217
260
|
function toErrorComponent(routeObject) {
|
|
218
261
|
const route = routeObject;
|
|
219
262
|
if (route.ErrorBoundary) return route.ErrorBoundary;
|
|
@@ -293,7 +336,7 @@ function createRouteFromModernRoute(opts) {
|
|
|
293
336
|
const stableFallbackId = modernId || route._component || route.filename || route.data || ('function' == typeof route.loader ? route.id : void 0);
|
|
294
337
|
const pendingComponent = route.loading || route.pendingComponent;
|
|
295
338
|
const errorComponent = route.error || route.errorComponent;
|
|
296
|
-
const component = route
|
|
339
|
+
const component = toModernRouteComponent(route);
|
|
297
340
|
const modernLoader = route.loader;
|
|
298
341
|
const modernAction = route.action;
|
|
299
342
|
const modernShouldRevalidate = route.shouldRevalidate;
|
|
@@ -339,7 +382,7 @@ function createRouteFromModernRoute(opts) {
|
|
|
339
382
|
}
|
|
340
383
|
function createRouteTreeFromModernRoutes(routes) {
|
|
341
384
|
const rootModern = routes.find((r)=>r && 'nested' === r.type && r.isRoot);
|
|
342
|
-
const rootComponent = rootModern
|
|
385
|
+
const rootComponent = rootModern ? toModernRouteComponent(rootModern) : void 0;
|
|
343
386
|
const pendingComponent = rootModern?.loading;
|
|
344
387
|
const errorComponent = rootModern?.error;
|
|
345
388
|
const rootLoader = rootModern?.loader;
|
|
@@ -2,10 +2,10 @@ import "node:module";
|
|
|
2
2
|
import { sanitizeSSRPayload, serializeJson } from "@modern-js/runtime-utils/node";
|
|
3
3
|
import { time } from "@modern-js/runtime-utils/time";
|
|
4
4
|
import react from "react";
|
|
5
|
-
import
|
|
5
|
+
import { HelmetProvider } from "react-helmet-async";
|
|
6
|
+
import { getHelmetData, helmetReplace } from "../../../core/server/helmet.mjs";
|
|
6
7
|
import { serializeErrors } from "../../../router/runtime/utils.mjs";
|
|
7
8
|
import prefetch from "../../prefetch";
|
|
8
|
-
import helmet from "../helmet";
|
|
9
9
|
import { SSRErrors, SSRTimings } from "../tracker";
|
|
10
10
|
import { RenderLevel } from "../types.mjs";
|
|
11
11
|
import { ROUTER_DATA_JSON_ID, SSR_DATA_JSON_ID, attributesToString } from "../utils";
|
|
@@ -61,8 +61,8 @@ class Entry {
|
|
|
61
61
|
createReplaceSSRDataScript(ssrDataScripts),
|
|
62
62
|
...this.htmlModifiers
|
|
63
63
|
]);
|
|
64
|
-
const helmetData =
|
|
65
|
-
return helmetData ?
|
|
64
|
+
const helmetData = getHelmetData(context);
|
|
65
|
+
return helmetData ? helmetReplace(html, helmetData) : html;
|
|
66
66
|
}
|
|
67
67
|
async prefetch(context) {
|
|
68
68
|
let prefetchData;
|
|
@@ -83,11 +83,14 @@ class Entry {
|
|
|
83
83
|
const end = time();
|
|
84
84
|
const { ssrContext } = context;
|
|
85
85
|
try {
|
|
86
|
-
const
|
|
86
|
+
const helmetContext = context._helmetContext ??= {};
|
|
87
|
+
const App = react.createElement(HelmetProvider, {
|
|
88
|
+
context: helmetContext
|
|
89
|
+
}, react.createElement(this.App, {
|
|
87
90
|
context: Object.assign(context, {
|
|
88
91
|
ssr: true
|
|
89
92
|
})
|
|
90
|
-
});
|
|
93
|
+
}));
|
|
91
94
|
html = await createRender(App).addCollector(createStyledCollector(this.result)).addCollector(createLoadableCollector({
|
|
92
95
|
stats: ssrContext.loadableStats,
|
|
93
96
|
result: this.result,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { RuntimePlugin } from '../core';
|
|
2
|
+
export type BoundaryDebugEntry = {
|
|
3
|
+
appId: string;
|
|
4
|
+
color?: string;
|
|
5
|
+
label?: string;
|
|
6
|
+
mfName: string;
|
|
7
|
+
ownerTeam?: string;
|
|
8
|
+
packageName?: string;
|
|
9
|
+
role?: 'host' | 'vertical';
|
|
10
|
+
};
|
|
11
|
+
export type BoundaryDebugMetadata = {
|
|
12
|
+
appId: string;
|
|
13
|
+
boundaries: BoundaryDebugEntry[];
|
|
14
|
+
schemaVersion: 1;
|
|
15
|
+
};
|
|
16
|
+
export type BoundaryDebuggerControlMode = 'visible' | 'hidden-when-off' | 'hidden';
|
|
17
|
+
export type BoundaryDebuggerPluginOptions = {
|
|
18
|
+
controlMode?: BoundaryDebuggerControlMode;
|
|
19
|
+
enabledByDefault?: boolean;
|
|
20
|
+
labels?: Record<string, {
|
|
21
|
+
toggle: string;
|
|
22
|
+
}>;
|
|
23
|
+
legacySelector?: string;
|
|
24
|
+
metadata: BoundaryDebugMetadata;
|
|
25
|
+
storageKey?: string;
|
|
26
|
+
};
|
|
27
|
+
export declare const ultramodernBoundaryDebuggerPlugin: (options: BoundaryDebuggerPluginOptions) => RuntimePlugin;
|
|
28
|
+
export default ultramodernBoundaryDebuggerPlugin;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { RouteObject, StaticHandlerContext } from '@modern-js/runtime-utils/router';
|
|
2
|
+
import type { HelmetServerState } from 'react-helmet-async';
|
|
2
3
|
import type { InternalRouterRuntimeState, InternalRouterServerSnapshot, RouteManifest, RouterFramework } from '../../router/runtime/types';
|
|
3
4
|
import type { RequestContext, SSRServerContext } from '../types';
|
|
4
5
|
export interface TRuntimeContext {
|
|
@@ -28,6 +29,9 @@ export interface TInternalRuntimeContext extends TRuntimeContext {
|
|
|
28
29
|
ssrContext?: SSRServerContext;
|
|
29
30
|
_internalContext?: any;
|
|
30
31
|
_internalRouterBaseName?: any;
|
|
32
|
+
_helmetContext?: {
|
|
33
|
+
helmet?: HelmetServerState | null;
|
|
34
|
+
};
|
|
31
35
|
}
|
|
32
36
|
export declare const InternalRuntimeContext: import("react").Context<TInternalRuntimeContext>;
|
|
33
37
|
export declare const RuntimeContext: import("react").Context<TRuntimeContext>;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
export declare function
|
|
1
|
+
import type { HelmetServerState } from 'react-helmet-async';
|
|
2
|
+
import type { TInternalRuntimeContext } from '../context';
|
|
3
|
+
export declare function getHelmetData(runtimeContext: TInternalRuntimeContext): HelmetServerState | undefined;
|
|
4
|
+
export declare function createReplaceHelemt(helmetData?: HelmetServerState): (template: string) => string;
|
|
5
|
+
export declare function helmetReplace(content: string, helmetData: HelmetServerState): string;
|
|
@@ -5,5 +5,6 @@ export interface BuildShellBeforeTemplateOptions {
|
|
|
5
5
|
entryName: string;
|
|
6
6
|
config: HandleRequestConfig;
|
|
7
7
|
styledComponentsStyleTags?: string;
|
|
8
|
+
moduleFederationCssAssets?: string[];
|
|
8
9
|
}
|
|
9
10
|
export declare function buildShellBeforeTemplate(beforeAppTemplate: string, options: BuildShellBeforeTemplateOptions): Promise<string>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TInternalRuntimeContext } from '../../context';
|
|
2
|
+
import type { HandleRequestConfig } from '../requestHandler';
|
|
3
|
+
export interface BuildShellBeforeTemplateOptions {
|
|
4
|
+
runtimeContext: TInternalRuntimeContext;
|
|
5
|
+
entryName: string;
|
|
6
|
+
config: HandleRequestConfig;
|
|
7
|
+
styledComponentsStyleTags?: string;
|
|
8
|
+
moduleFederationCssAssets?: string[];
|
|
9
|
+
}
|
|
10
|
+
export declare function buildShellBeforeTemplate(beforeAppTemplate: string, options: BuildShellBeforeTemplateOptions): Promise<string>;
|
|
@@ -4,15 +4,23 @@ import type React from 'react';
|
|
|
4
4
|
import type { TRuntimeContext } from '../../context';
|
|
5
5
|
import type { HandleRequestConfig } from '../requestHandler';
|
|
6
6
|
import type { RenderStreaming, SSRConfig } from '../shared';
|
|
7
|
+
export type RscManifest = {
|
|
8
|
+
clientManifest?: RscClientManifest;
|
|
9
|
+
serverConsumerModuleMap?: unknown;
|
|
10
|
+
serverManifest?: RscServerManifest;
|
|
11
|
+
entryCssFiles?: Record<string, string[]>;
|
|
12
|
+
};
|
|
7
13
|
export type CreateReadableStreamFromElementOptions = {
|
|
8
14
|
runtimeContext: TRuntimeContext;
|
|
9
15
|
config: HandleRequestConfig;
|
|
10
16
|
ssrConfig: SSRConfig;
|
|
11
17
|
htmlTemplate: string;
|
|
12
18
|
entryName: string;
|
|
19
|
+
moduleFederationCssAssets?: string[];
|
|
13
20
|
rscClientManifest?: RscClientManifest;
|
|
14
21
|
rscSSRManifest?: RscSSRManifest;
|
|
15
22
|
rscServerManifest?: RscServerManifest;
|
|
23
|
+
rscManifest?: RscManifest;
|
|
16
24
|
rscRoot?: React.ReactElement;
|
|
17
25
|
onShellReady?: () => void;
|
|
18
26
|
onShellError?: (error: unknown) => void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReactElement } from 'react';
|
|
2
|
+
import type { TInternalRuntimeContext } from '../../context';
|
|
2
3
|
import type { ChunkSet, Collector } from './types';
|
|
3
4
|
declare module '@loadable/server' {
|
|
4
5
|
interface ChunkExtractor {
|
|
@@ -10,8 +11,10 @@ export interface LoadableCollectorOptions {
|
|
|
10
11
|
nonce?: string;
|
|
11
12
|
stats?: Record<string, any>;
|
|
12
13
|
routeManifest?: Record<string, any>;
|
|
14
|
+
runtimeContext: TInternalRuntimeContext;
|
|
13
15
|
template: string;
|
|
14
16
|
entryName: string;
|
|
17
|
+
moduleFederationCssAssets?: string[];
|
|
15
18
|
chunkSet: ChunkSet;
|
|
16
19
|
config: LoadableCollectorConfig;
|
|
17
20
|
}
|
|
@@ -27,6 +30,7 @@ export declare class LoadableCollector implements Collector {
|
|
|
27
30
|
private extractor?;
|
|
28
31
|
constructor(options: LoadableCollectorOptions);
|
|
29
32
|
private get existsAssets();
|
|
33
|
+
private getMatchedRouteChunks;
|
|
30
34
|
collect(comopnent: ReactElement): ReactElement;
|
|
31
35
|
effect(): Promise<void>;
|
|
32
36
|
private emitLoadableScripts;
|