rasengan 1.1.3 → 1.2.0-beta.0
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/CHANGELOG.md +2 -0
- package/lib/esm/core/config/vite/defaults.js +1 -17
- package/lib/esm/core/dynamic/index.js +32 -0
- package/lib/esm/core/plugins/index.js +1 -1
- package/lib/esm/entries/client/render.js +45 -16
- package/lib/esm/entries/server/entry.server.js +1 -0
- package/lib/esm/entries/server/index.js +3 -3
- package/lib/esm/routing/components/fallback.js +8 -0
- package/lib/esm/routing/components/index.js +7 -4
- package/lib/esm/routing/components/template.js +8 -7
- package/lib/esm/routing/providers/metadata.js +23 -13
- package/lib/esm/routing/utils/define-router.js +10 -6
- package/lib/esm/routing/utils/flat-routes.js +46 -75
- package/lib/esm/routing/utils/generate-routes.js +279 -178
- package/lib/esm/server/build/manifest.js +19 -7
- package/lib/esm/server/dev/handlers.js +1 -1
- package/lib/esm/server/dev/server.js +19 -1
- package/lib/esm/server/node/index.js +8 -2
- package/lib/tsconfig.esm.tsbuildinfo +1 -1
- package/lib/tsconfig.types.tsbuildinfo +1 -1
- package/lib/types/core/dynamic/index.d.ts +15 -0
- package/lib/types/core/types.d.ts +1 -1
- package/lib/types/entries/client/render.d.ts +3 -2
- package/lib/types/routing/components/fallback.d.ts +5 -0
- package/lib/types/routing/components/template.d.ts +1 -1
- package/lib/types/routing/interfaces.d.ts +5 -4
- package/lib/types/routing/providers/metadata.d.ts +1 -3
- package/lib/types/routing/types.d.ts +21 -3
- package/lib/types/routing/utils/define-routes-group.d.ts +1 -1
- package/lib/types/routing/utils/flat-routes.d.ts +21 -3
- package/lib/types/routing/utils/generate-routes.d.ts +6 -6
- package/lib/types/server/build/manifest.d.ts +4 -4
- package/package.json +1 -1
|
@@ -1,23 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { Outlet, matchRoutes, useLoaderData, useParams } from 'react-router';
|
|
3
3
|
import { ErrorBoundary, NotFoundPageComponent, RasenganPageComponent, } from '../components/index.js';
|
|
4
|
-
import { Suspense } from 'react';
|
|
5
4
|
import MetadataProvider from '../providers/metadata.js';
|
|
5
|
+
import { convertMDXPageToPageComponent, isMDXPage, } from './index.js';
|
|
6
6
|
const defaultMetadata = {
|
|
7
7
|
title: 'Not Found',
|
|
8
8
|
description: 'Page not found',
|
|
9
9
|
};
|
|
10
|
-
/**
|
|
11
|
-
* This function receives a router component and get a formated router first
|
|
12
|
-
* and then return a router.
|
|
13
|
-
*/
|
|
14
|
-
export const getRouter = (routerInstance) => {
|
|
15
|
-
const routes = generateRoutes(routerInstance);
|
|
16
|
-
let router = createBrowserRouter(routes, {
|
|
17
|
-
hydrationData: window.__staticRouterHydrationData,
|
|
18
|
-
});
|
|
19
|
-
return () => _jsx(RouterProvider, { router: router });
|
|
20
|
-
};
|
|
21
10
|
/**
|
|
22
11
|
* This function merge the metadata, giving priority to the ones comming from loader
|
|
23
12
|
*/
|
|
@@ -112,7 +101,7 @@ const mergeMetaData = (responseMeta, meta, isLayout = false) => {
|
|
|
112
101
|
/**
|
|
113
102
|
* This function create a loader function
|
|
114
103
|
*/
|
|
115
|
-
const createLoaderFunction = ({ loader, metadata, isLayout = false, }) => {
|
|
104
|
+
const createLoaderFunction = ({ loader, metadata, isLayout = false, source, }) => {
|
|
116
105
|
return async ({ params, request }) => {
|
|
117
106
|
try {
|
|
118
107
|
// Check if the loader is defined
|
|
@@ -120,6 +109,7 @@ const createLoaderFunction = ({ loader, metadata, isLayout = false, }) => {
|
|
|
120
109
|
return {
|
|
121
110
|
props: {},
|
|
122
111
|
meta: metadata,
|
|
112
|
+
source,
|
|
123
113
|
};
|
|
124
114
|
}
|
|
125
115
|
// Get the response from the loader
|
|
@@ -138,6 +128,7 @@ const createLoaderFunction = ({ loader, metadata, isLayout = false, }) => {
|
|
|
138
128
|
return {
|
|
139
129
|
props: response.props,
|
|
140
130
|
meta: mergeMetaData(response.meta ?? {}, metadata, isLayout),
|
|
131
|
+
source,
|
|
141
132
|
};
|
|
142
133
|
}
|
|
143
134
|
catch (error) {
|
|
@@ -157,75 +148,163 @@ const createLoaderFunction = ({ loader, metadata, isLayout = false, }) => {
|
|
|
157
148
|
metaTags: [],
|
|
158
149
|
links: [],
|
|
159
150
|
},
|
|
151
|
+
source,
|
|
160
152
|
};
|
|
161
153
|
}
|
|
162
154
|
};
|
|
163
155
|
};
|
|
156
|
+
/**
|
|
157
|
+
* This function preload the matching lazy routes
|
|
158
|
+
* @param url
|
|
159
|
+
* @param routes
|
|
160
|
+
*/
|
|
161
|
+
export const preloadMatches = async (url, routes) => {
|
|
162
|
+
const matches = matchRoutes(routes, url);
|
|
163
|
+
if (!matches)
|
|
164
|
+
return;
|
|
165
|
+
await Promise.all(matches.map(async (match) => {
|
|
166
|
+
if (match.route.lazy) {
|
|
167
|
+
const resolved = await match.route.lazy();
|
|
168
|
+
Object.assign(match.route, resolved);
|
|
169
|
+
// Strip lazy so Router never tries to suspend again
|
|
170
|
+
delete match.route.lazy;
|
|
171
|
+
}
|
|
172
|
+
}));
|
|
173
|
+
};
|
|
164
174
|
/**
|
|
165
175
|
* This function receives a router component and return a formated router for static routing
|
|
166
176
|
* @param router Represents the router component
|
|
167
177
|
* @returns
|
|
168
178
|
*/
|
|
169
|
-
export const generateRoutes = (router, isRoot = true,
|
|
179
|
+
export const generateRoutes = (router, isRoot = true, parentLayoutPath = undefined) => {
|
|
170
180
|
// Initialization of the list of routes
|
|
171
181
|
const routes = [];
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
:
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
182
|
+
let route;
|
|
183
|
+
let layoutPath;
|
|
184
|
+
// Check if the layout is coming from the file-based routing system
|
|
185
|
+
if ('source' in router.layout) {
|
|
186
|
+
const layoutNode = router.layout;
|
|
187
|
+
layoutPath = layoutNode.path;
|
|
188
|
+
route = {
|
|
189
|
+
path: !isRoot
|
|
190
|
+
? router.useParentLayout
|
|
191
|
+
? layoutNode.path.replace(parentLayoutPath + '/', '')
|
|
192
|
+
: layoutNode.path
|
|
193
|
+
: layoutNode.path,
|
|
194
|
+
errorElement: _jsx(ErrorBoundary, {}),
|
|
195
|
+
lazy: async () => {
|
|
196
|
+
const Layout = (await layoutNode.module()).default;
|
|
197
|
+
if (!Layout) {
|
|
198
|
+
console.warn(`Layout component is not exported by default from: ${layoutNode.source}}`);
|
|
199
|
+
return {
|
|
200
|
+
Component() {
|
|
201
|
+
return _jsx(Outlet, {});
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
Component() {
|
|
207
|
+
// Default data
|
|
208
|
+
const defaultData = {
|
|
209
|
+
props: {},
|
|
210
|
+
};
|
|
211
|
+
// Get SSR data
|
|
212
|
+
let { props } = useLoaderData() || defaultData;
|
|
213
|
+
// get params
|
|
214
|
+
const params = useParams();
|
|
215
|
+
const layoutProps = {
|
|
216
|
+
...props,
|
|
217
|
+
params,
|
|
218
|
+
};
|
|
219
|
+
// Check if the layout is the root layout and wrap it in a MetadataProvider
|
|
220
|
+
if (isRoot || !router.useParentLayout) {
|
|
221
|
+
// Generate metadata mapping
|
|
222
|
+
// const metadataMapping = generateMetadataMapping(router);
|
|
223
|
+
return (_jsx(MetadataProvider, { children: _jsx(Layout, { ...layoutProps }) }));
|
|
224
|
+
}
|
|
225
|
+
return _jsx(Layout, { ...layoutProps });
|
|
226
|
+
},
|
|
227
|
+
async loader({ params, request }) {
|
|
228
|
+
// Extract metadata from the layout
|
|
229
|
+
const metadata = {
|
|
230
|
+
...Layout.metadata,
|
|
231
|
+
};
|
|
232
|
+
return createLoaderFunction({
|
|
233
|
+
loader: Layout.loader,
|
|
234
|
+
metadata,
|
|
235
|
+
isLayout: true,
|
|
236
|
+
source: layoutNode.source,
|
|
237
|
+
})({
|
|
238
|
+
params,
|
|
239
|
+
request,
|
|
240
|
+
});
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
},
|
|
244
|
+
children: [],
|
|
245
|
+
nested: router.useParentLayout,
|
|
246
|
+
hydrateFallbackElement: _jsx(_Fragment, {}),
|
|
247
|
+
// shouldRevalidate: ({ currentUrl, nextUrl, defaultShouldRevalidate }) => {
|
|
248
|
+
// // Only revalidate if navigating to a different route
|
|
249
|
+
// return currentUrl.pathname !== nextUrl.pathname;
|
|
250
|
+
// },
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
const Layout = router.layout;
|
|
255
|
+
layoutPath = Layout.path;
|
|
256
|
+
route = {
|
|
257
|
+
path: !isRoot
|
|
258
|
+
? router.useParentLayout
|
|
259
|
+
? layoutPath.replace(parentLayoutPath + '/', '')
|
|
260
|
+
: layoutPath
|
|
261
|
+
: layoutPath,
|
|
262
|
+
errorElement: _jsx(ErrorBoundary, {}),
|
|
263
|
+
Component() {
|
|
264
|
+
// Default data
|
|
265
|
+
const defaultData = {
|
|
266
|
+
props: {},
|
|
267
|
+
};
|
|
268
|
+
// Get SSR data
|
|
269
|
+
let { props } = useLoaderData() || defaultData;
|
|
270
|
+
// get params
|
|
271
|
+
const params = useParams();
|
|
272
|
+
const layoutProps = {
|
|
273
|
+
...props,
|
|
274
|
+
params,
|
|
275
|
+
};
|
|
276
|
+
// Check if the layout is the root layout and wrap it in a MetadataProvider
|
|
277
|
+
if (isRoot || !router.useParentLayout) {
|
|
278
|
+
// Generate metadata mapping
|
|
279
|
+
// const metadataMapping = generateMetadataMapping(router);
|
|
280
|
+
return (_jsx(MetadataProvider, { children: _jsx(Layout, { ...layoutProps }) }));
|
|
281
|
+
}
|
|
282
|
+
return _jsx(Layout, { ...layoutProps });
|
|
283
|
+
},
|
|
284
|
+
async loader({ params, request }) {
|
|
285
|
+
// Extract metadata from the layout
|
|
286
|
+
const metadata = {
|
|
287
|
+
...Layout.metadata,
|
|
288
|
+
};
|
|
289
|
+
return createLoaderFunction({
|
|
290
|
+
loader: Layout.loader,
|
|
291
|
+
metadata,
|
|
292
|
+
isLayout: true,
|
|
293
|
+
})({
|
|
294
|
+
params,
|
|
295
|
+
request,
|
|
296
|
+
});
|
|
297
|
+
},
|
|
298
|
+
children: [],
|
|
299
|
+
nested: router.useParentLayout,
|
|
300
|
+
hydrateFallbackElement: _jsx(_Fragment, {}),
|
|
301
|
+
// hydrateFallbackElement: <>Loading...</>, // TODO: enable override
|
|
302
|
+
// shouldRevalidate: ({ currentUrl, nextUrl, defaultShouldRevalidate }) => {
|
|
303
|
+
// // Only revalidate if navigating to a different route
|
|
304
|
+
// return currentUrl.pathname !== nextUrl.pathname;
|
|
305
|
+
// },
|
|
306
|
+
};
|
|
307
|
+
}
|
|
229
308
|
// Defining the page not found route
|
|
230
309
|
if (isRoot || router.notFoundComponent) {
|
|
231
310
|
route.children.push({
|
|
@@ -240,53 +319,134 @@ export const generateRoutes = (router, isRoot = true, parentLayout = undefined)
|
|
|
240
319
|
});
|
|
241
320
|
}
|
|
242
321
|
// Get informations about pages
|
|
243
|
-
const pages = router.pages.map((
|
|
244
|
-
//
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
322
|
+
const pages = router.pages.map((p) => {
|
|
323
|
+
// Check if the page is coming from file-based routing system
|
|
324
|
+
if ('source' in p) {
|
|
325
|
+
const pageNode = p;
|
|
326
|
+
// /home => home
|
|
327
|
+
// / => /
|
|
328
|
+
const pagePathFormated = pageNode.path.startsWith('/') && pageNode.path !== '/'
|
|
329
|
+
? pageNode.path.slice(1)
|
|
330
|
+
: pageNode.path;
|
|
331
|
+
// Get the path of the page
|
|
332
|
+
const path = pageNode.path === '/'
|
|
333
|
+
? layoutPath
|
|
334
|
+
: layoutPath.length > 1
|
|
335
|
+
? pagePathFormated
|
|
336
|
+
: pageNode.path;
|
|
337
|
+
return {
|
|
338
|
+
path: path === layoutPath ? undefined : path,
|
|
339
|
+
index: path === layoutPath,
|
|
340
|
+
async lazy() {
|
|
341
|
+
let Page = (await pageNode.module()).default;
|
|
342
|
+
if (!Page) {
|
|
343
|
+
console.warn(`Page component is not exported by default from: ${pageNode.source}}`);
|
|
344
|
+
return {
|
|
345
|
+
Component() {
|
|
346
|
+
return null;
|
|
347
|
+
},
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
// Detech if the page is a MDXPageComponent or not
|
|
351
|
+
if (isMDXPage(Page)) {
|
|
352
|
+
// Convert PageComponent to MDXPageComponent (to make ts happy)
|
|
353
|
+
const mdxPage = Page;
|
|
354
|
+
// mdxPage.metadata.path = node.path;
|
|
355
|
+
// mdxPage.metadata.metadata = Page.metadata;
|
|
356
|
+
Page = await convertMDXPageToPageComponent(mdxPage);
|
|
357
|
+
}
|
|
358
|
+
return {
|
|
359
|
+
Component() {
|
|
360
|
+
// Default data
|
|
361
|
+
const defaultData = {
|
|
362
|
+
props: {
|
|
363
|
+
params: {},
|
|
364
|
+
},
|
|
365
|
+
};
|
|
366
|
+
const loaderData = useLoaderData() || defaultData;
|
|
367
|
+
return (
|
|
368
|
+
// <Suspense fallback={<>Loading</>}>
|
|
369
|
+
_jsx(RasenganPageComponent, { page: Page, data: loaderData })
|
|
370
|
+
// </Suspense>
|
|
371
|
+
);
|
|
372
|
+
},
|
|
373
|
+
async loader({ params, request }) {
|
|
374
|
+
// Extracting metadata from the page
|
|
375
|
+
const metadata = {
|
|
376
|
+
...Page.metadata,
|
|
377
|
+
};
|
|
378
|
+
return createLoaderFunction({
|
|
379
|
+
loader: Page.loader,
|
|
380
|
+
metadata,
|
|
381
|
+
source: pageNode.source,
|
|
382
|
+
})({
|
|
383
|
+
params,
|
|
384
|
+
request,
|
|
385
|
+
});
|
|
386
|
+
},
|
|
387
|
+
};
|
|
388
|
+
},
|
|
389
|
+
errorElement: _jsx(ErrorBoundary, {}),
|
|
390
|
+
hydrateFallbackElement: _jsx(_Fragment, {}),
|
|
391
|
+
// hydrateFallbackElement: <>Loading...</>,
|
|
392
|
+
shouldRevalidate: ({ currentUrl, nextUrl, defaultShouldRevalidate, }) => {
|
|
393
|
+
// Only revalidate if navigating to a different route
|
|
394
|
+
return currentUrl.pathname !== nextUrl.pathname;
|
|
395
|
+
},
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
const Page = p;
|
|
400
|
+
// /home => home
|
|
401
|
+
// / => /
|
|
402
|
+
const pagePathFormated = Page.path.startsWith('/') && Page.path !== '/'
|
|
403
|
+
? Page.path.slice(1)
|
|
254
404
|
: Page.path;
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
405
|
+
// Get the path of the page
|
|
406
|
+
const path = Page.path === '/'
|
|
407
|
+
? layoutPath
|
|
408
|
+
: layoutPath.length > 1
|
|
409
|
+
? pagePathFormated
|
|
410
|
+
: Page.path;
|
|
411
|
+
return {
|
|
412
|
+
path: path === layoutPath ? undefined : path,
|
|
413
|
+
index: path === layoutPath,
|
|
414
|
+
async loader({ params, request }) {
|
|
415
|
+
// Extracting metadata from the page
|
|
416
|
+
const metadata = {
|
|
417
|
+
...Page.metadata,
|
|
418
|
+
};
|
|
419
|
+
return createLoaderFunction({
|
|
420
|
+
loader: Page.loader,
|
|
421
|
+
metadata,
|
|
422
|
+
})({
|
|
423
|
+
params,
|
|
424
|
+
request,
|
|
425
|
+
});
|
|
426
|
+
},
|
|
427
|
+
Component() {
|
|
428
|
+
// Default data
|
|
429
|
+
const defaultData = {
|
|
430
|
+
props: {
|
|
431
|
+
params: {},
|
|
432
|
+
},
|
|
433
|
+
};
|
|
434
|
+
const loaderData = useLoaderData() || defaultData;
|
|
435
|
+
return (
|
|
436
|
+
// <Suspense fallback={<>Loading</>}>
|
|
437
|
+
_jsx(RasenganPageComponent, { page: Page, data: loaderData })
|
|
438
|
+
// </Suspense>
|
|
439
|
+
);
|
|
440
|
+
},
|
|
441
|
+
errorElement: _jsx(ErrorBoundary, {}),
|
|
442
|
+
hydrateFallbackElement: _jsx(_Fragment, {}),
|
|
443
|
+
// hydrateFallbackElement: <>Loading...</>,
|
|
444
|
+
shouldRevalidate: ({ currentUrl, nextUrl, defaultShouldRevalidate, }) => {
|
|
445
|
+
// Only revalidate if navigating to a different route
|
|
446
|
+
return currentUrl.pathname !== nextUrl.pathname;
|
|
447
|
+
},
|
|
448
|
+
};
|
|
449
|
+
}
|
|
290
450
|
});
|
|
291
451
|
// Add pages into children of the current route
|
|
292
452
|
pages.forEach((page) => {
|
|
@@ -294,7 +454,7 @@ export const generateRoutes = (router, isRoot = true, parentLayout = undefined)
|
|
|
294
454
|
});
|
|
295
455
|
// Loop through imported routers in order to apply the same logic like above.
|
|
296
456
|
for (const importedRouter of router.routers) {
|
|
297
|
-
const importedRoutes = generateRoutes(importedRouter, false,
|
|
457
|
+
const importedRoutes = generateRoutes(importedRouter, false, layoutPath);
|
|
298
458
|
for (const importedRoute of importedRoutes) {
|
|
299
459
|
if (importedRoute.nested) {
|
|
300
460
|
route.children.push(importedRoute);
|
|
@@ -309,62 +469,3 @@ export const generateRoutes = (router, isRoot = true, parentLayout = undefined)
|
|
|
309
469
|
// Return the formated router
|
|
310
470
|
return routes;
|
|
311
471
|
};
|
|
312
|
-
/**
|
|
313
|
-
* This function receives a router component and return a mapping from path to metadata
|
|
314
|
-
* @param router Represents the router component
|
|
315
|
-
* @returns
|
|
316
|
-
*/
|
|
317
|
-
export const generateMetadataMapping = (router, isRoot = true, parentLayout = undefined) => {
|
|
318
|
-
const metadataMapping = {};
|
|
319
|
-
// Get information about the layout and the path
|
|
320
|
-
const Layout = router.layout;
|
|
321
|
-
// Set default path layout if not provided
|
|
322
|
-
if (!Layout.path) {
|
|
323
|
-
throw new Error(`[rasengan] Page path is required for ${Layout.name} layout component`);
|
|
324
|
-
}
|
|
325
|
-
const layoutPath = !isRoot
|
|
326
|
-
? router.useParentLayout
|
|
327
|
-
? parentLayout.path +
|
|
328
|
-
(Layout.path === '/'
|
|
329
|
-
? ''
|
|
330
|
-
: Layout.path.startsWith('/') && parentLayout.path === '/'
|
|
331
|
-
? Layout.path.slice(1)
|
|
332
|
-
: Layout.path)
|
|
333
|
-
: Layout.path
|
|
334
|
-
: Layout.path;
|
|
335
|
-
// Get informations about pages
|
|
336
|
-
router.pages.forEach((Page) => {
|
|
337
|
-
// Set default page path if not provided
|
|
338
|
-
if (!Page.path) {
|
|
339
|
-
throw new Error(`[rasengan] Page path is required for ${Page.name} page component`);
|
|
340
|
-
}
|
|
341
|
-
const pagePathFormated = Page.path.startsWith('/') && Page.path !== '/' && layoutPath.endsWith('/')
|
|
342
|
-
? Page.path.slice(1)
|
|
343
|
-
: Page.path;
|
|
344
|
-
// Get the path of the page
|
|
345
|
-
const path = Page.path === '/' ? layoutPath : layoutPath + pagePathFormated;
|
|
346
|
-
// Get metadata
|
|
347
|
-
metadataMapping[path] = {
|
|
348
|
-
openGraph: {
|
|
349
|
-
url: '',
|
|
350
|
-
image: '',
|
|
351
|
-
},
|
|
352
|
-
twitter: {
|
|
353
|
-
card: 'summary_large_image',
|
|
354
|
-
image: '',
|
|
355
|
-
title: '',
|
|
356
|
-
},
|
|
357
|
-
...Page.metadata,
|
|
358
|
-
};
|
|
359
|
-
});
|
|
360
|
-
// Loop through imported routers in order to apply the same logic like above.
|
|
361
|
-
for (const importedRouter of router.routers) {
|
|
362
|
-
const importedMetadataMapping = generateMetadataMapping(importedRouter, false, Layout);
|
|
363
|
-
Object.assign(metadataMapping, importedMetadataMapping);
|
|
364
|
-
// Add the metadata of the imported router's pages to the metadata mapping
|
|
365
|
-
for (const [path, metadata] of Object.entries(importedMetadataMapping)) {
|
|
366
|
-
metadataMapping[path] = metadata;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
return metadataMapping;
|
|
370
|
-
};
|
|
@@ -23,10 +23,10 @@ export class ManifestManager {
|
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
25
|
* Resolve all assets for a given page.
|
|
26
|
-
* @param
|
|
26
|
+
* @param source - The file path of the page to resolve.
|
|
27
27
|
* @returns Resolved assets with scripts and styles.
|
|
28
28
|
*/
|
|
29
|
-
resolveAssets(
|
|
29
|
+
resolveAssets(source) {
|
|
30
30
|
const visited = new Set();
|
|
31
31
|
const assets = {
|
|
32
32
|
scripts: [],
|
|
@@ -67,10 +67,22 @@ export class ManifestManager {
|
|
|
67
67
|
collectAssets(this._manifest[importName]);
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
-
// Collect dynamic imports
|
|
70
|
+
// // Collect dynamic imports
|
|
71
|
+
// if (entry.dynamicImports) {
|
|
72
|
+
// for (const dynamicImport of entry.dynamicImports) {
|
|
73
|
+
// collectAssets(this._manifest[dynamicImport]);
|
|
74
|
+
// }
|
|
75
|
+
// }
|
|
76
|
+
// Collect dynamic imports (filter by pageName)
|
|
71
77
|
if (entry.dynamicImports) {
|
|
72
78
|
for (const dynamicImport of entry.dynamicImports) {
|
|
73
|
-
|
|
79
|
+
const dynEntry = this._manifest[dynamicImport];
|
|
80
|
+
if (!dynEntry)
|
|
81
|
+
continue;
|
|
82
|
+
// Check if the dynamic import corresponds to the requested page
|
|
83
|
+
if (dynEntry.src?.includes(source)) {
|
|
84
|
+
collectAssets(dynEntry);
|
|
85
|
+
}
|
|
74
86
|
}
|
|
75
87
|
}
|
|
76
88
|
};
|
|
@@ -79,11 +91,11 @@ export class ManifestManager {
|
|
|
79
91
|
}
|
|
80
92
|
/**
|
|
81
93
|
* Generate meta tags for a given page.
|
|
82
|
-
* @param
|
|
94
|
+
* @param source - The file path of the page to generate meta tags for.
|
|
83
95
|
* @returns HTML string containing script and style tags.
|
|
84
96
|
*/
|
|
85
|
-
generateMetaTags(
|
|
86
|
-
const { scripts, styles } = this.resolveAssets(
|
|
97
|
+
generateMetaTags(source) {
|
|
98
|
+
const { scripts, styles } = this.resolveAssets(source);
|
|
87
99
|
const scriptTags = scripts.map((file) => (_jsx("script", { type: 'module', src: `/${file}` })));
|
|
88
100
|
const styleTags = styles.map((file) => (_jsx("link", { rel: 'stylesheet', href: `/${file}` })));
|
|
89
101
|
return [...scriptTags, ...styleTags];
|
|
@@ -77,7 +77,7 @@ export async function handleDocumentRequest(req, res, runner, options) {
|
|
|
77
77
|
res.writeHead(context.statusCode, {
|
|
78
78
|
...Object.fromEntries(headers),
|
|
79
79
|
});
|
|
80
|
-
const Router = _jsx(StaticRouterProvider, { router: router, context: context });
|
|
80
|
+
const Router = (_jsx(StaticRouterProvider, { router: router, context: context, hydrate: true }));
|
|
81
81
|
// If stream mode enabled, render the page as a plain text
|
|
82
82
|
return await render(Router, res, {
|
|
83
83
|
metadata,
|
|
@@ -11,7 +11,7 @@ import { getDirname, loadModuleSSR, } from '../../core/config/utils/load-modules
|
|
|
11
11
|
import { ServerMode } from '../runtime/mode.js';
|
|
12
12
|
import { handleDataRequest, handleDocumentRequest, handleSpaModeRequest, } from './handlers.js';
|
|
13
13
|
import { createStaticHandler } from 'react-router';
|
|
14
|
-
import { generateRoutes } from '../../routing/utils/generate-routes.js';
|
|
14
|
+
import { generateRoutes, preloadMatches, } from '../../routing/utils/generate-routes.js';
|
|
15
15
|
/**
|
|
16
16
|
* Handle the request for the development environment
|
|
17
17
|
* @param req
|
|
@@ -28,8 +28,26 @@ async function devRequestHandler(req, res, viteDevServer, options) {
|
|
|
28
28
|
const AppRouter = await (await runner.import(join(`${options.rootPath}/src/app/app.router`))).default;
|
|
29
29
|
// Get static routes
|
|
30
30
|
const staticRoutes = generateRoutes(AppRouter);
|
|
31
|
+
await preloadMatches(req.originalUrl, staticRoutes);
|
|
31
32
|
// Create static handler
|
|
32
33
|
let handler = createStaticHandler(staticRoutes);
|
|
34
|
+
// Get matches for the current URL
|
|
35
|
+
// const matches = matchRoutes(staticRoutes, req.originalUrl);
|
|
36
|
+
// Resolve all lazy() modules for matched routes
|
|
37
|
+
// const resolvedMatches = await Promise.all(
|
|
38
|
+
// matches?.map(async (match) => {
|
|
39
|
+
// if (match.route.lazy) {
|
|
40
|
+
// const lazyFn = match.route.lazy as unknown as () => Promise<any>;
|
|
41
|
+
// const resolved = await lazyFn();
|
|
42
|
+
// Object.assign(match.route, resolved);
|
|
43
|
+
// }
|
|
44
|
+
// return match;
|
|
45
|
+
// }) ?? []
|
|
46
|
+
// );
|
|
47
|
+
// console.log({
|
|
48
|
+
// resolvedMatches: JSON.stringify(resolvedMatches),
|
|
49
|
+
// url: req.originalUrl,
|
|
50
|
+
// });
|
|
33
51
|
if (isDataRequest(req)) {
|
|
34
52
|
// Handle data request
|
|
35
53
|
return await handleDataRequest(req, handler);
|
|
@@ -2,7 +2,9 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { ManifestManager } from '../build/manifest.js';
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import { generateRoutes
|
|
5
|
+
import { generateRoutes, preloadMatches,
|
|
6
|
+
// generateSSRRoutes,
|
|
7
|
+
} from '../../routing/utils/index.js';
|
|
6
8
|
import { createStaticHandler, createStaticRouter, StaticRouterProvider, } from 'react-router';
|
|
7
9
|
import createRasenganRequest from './utils.js';
|
|
8
10
|
import { extractHeadersFromRRContext, extractMetaFromRRContext, isRedirectResponse, isStaticRedirectFromConfig, } from '../dev/utils.js';
|
|
@@ -31,6 +33,8 @@ export function createRequestHandler(options) {
|
|
|
31
33
|
const { render, } = entry;
|
|
32
34
|
// Get static routes
|
|
33
35
|
const staticRoutes = generateRoutes(AppRouter);
|
|
36
|
+
// Preload matches
|
|
37
|
+
await preloadMatches(req.originalUrl, staticRoutes);
|
|
34
38
|
// Create static handler
|
|
35
39
|
let handler = createStaticHandler(staticRoutes);
|
|
36
40
|
// Create rasengan request for static routing
|
|
@@ -46,8 +50,10 @@ export function createRequestHandler(options) {
|
|
|
46
50
|
if (!(context instanceof Response)) {
|
|
47
51
|
// Extract meta from context
|
|
48
52
|
const metadata = extractMetaFromRRContext(context);
|
|
53
|
+
// Get the source file from the context
|
|
54
|
+
const source = context.loaderData.source;
|
|
49
55
|
// Get assets tags
|
|
50
|
-
const assets = manifest.generateMetaTags(
|
|
56
|
+
const assets = manifest.generateMetaTags(source);
|
|
51
57
|
// Create static router
|
|
52
58
|
let router = createStaticRouter(handler.dataRoutes, context);
|
|
53
59
|
const headers = extractHeadersFromRRContext(context);
|