lincd-cli 1.2.4 → 1.2.5
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/defaults/app-with-backend/lincd.config.js +1 -1
- package/defaults/app-with-backend/src/backend.ts +2 -2
- package/defaults/app-with-backend/src/index.tsx +7 -3
- package/defaults/app-with-backend/src/routes.tsx +28 -16
- package/defaults/app-with-backend/src/utils/lazyWithPreload.tsx +42 -0
- package/defaults/app-with-backend/src/utils/preloadRoutes.ts +38 -0
- package/lib/cjs/package.json +2 -1
- package/lib/esm/package.json +2 -1
- package/package.json +2 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { AppContextProvider } from 'lincd-server-utils/components/AppContext';
|
|
1
2
|
import { initFrontend } from 'lincd-server-utils/utils/Frontend';
|
|
3
|
+
import React from 'react';
|
|
2
4
|
import { hydrateRoot } from 'react-dom/client';
|
|
3
5
|
import { BrowserRouter } from 'react-router-dom';
|
|
4
6
|
import App from './App';
|
|
5
|
-
import
|
|
6
|
-
import { AppContextProvider } from 'lincd-server-utils/components/AppContext';
|
|
7
|
+
import { preloadMatchedRoute } from './utils/preloadRoutes';
|
|
7
8
|
|
|
8
9
|
//import the storage & file configuration for the frontend
|
|
9
10
|
import './config-frontend';
|
|
@@ -12,7 +13,10 @@ import './config-frontend';
|
|
|
12
13
|
window['$RefreshReg$'] = () => {};
|
|
13
14
|
window['$RefreshSig$'] = () => () => {};
|
|
14
15
|
|
|
15
|
-
initFrontend().then(() => {
|
|
16
|
+
initFrontend().then(async () => {
|
|
17
|
+
// Preload matched route before hydration to avoid Suspense mismatch
|
|
18
|
+
await preloadMatchedRoute();
|
|
19
|
+
|
|
16
20
|
hydrateRoot(
|
|
17
21
|
document,
|
|
18
22
|
<React.StrictMode>
|
|
@@ -1,37 +1,49 @@
|
|
|
1
|
+
import { RequireAuth } from 'lincd-auth/components/RequireAuth';
|
|
2
|
+
import type { RoutesConfig } from 'lincd-server/types/RouteConfig';
|
|
1
3
|
import React, { lazy, Suspense } from 'react';
|
|
2
4
|
import { Route, Routes } from 'react-router-dom';
|
|
3
5
|
import { Spinner } from './components/Spinner';
|
|
4
|
-
import { RequireAuth } from 'lincd-auth/components/RequireAuth';
|
|
5
6
|
import PageNotFound from './pages/PageNotFound';
|
|
7
|
+
import { lazyWithPreload } from './utils/lazyWithPreload';
|
|
8
|
+
|
|
9
|
+
// Create preloadable lazy components for direct-entry routes
|
|
10
|
+
const HomePage = lazyWithPreload(
|
|
11
|
+
() => import(/* webpackChunkName: "home" */ './pages/Home')
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
const SigninPage = lazyWithPreload(
|
|
15
|
+
() => import(/* webpackChunkName: "signin" */ './pages/Signin')
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
// Export preloadable components for server-side preloading
|
|
19
|
+
export const PRELOADABLE_ROUTES = {
|
|
20
|
+
home: HomePage,
|
|
21
|
+
signin: SigninPage,
|
|
22
|
+
};
|
|
6
23
|
|
|
7
|
-
//From React 18 you can use 'lazy' to import pages only when you need them.
|
|
8
|
-
//This will cause webpack to create multiple bundles, and the right bundles are automatically loaded
|
|
9
|
-
interface RouteObj {
|
|
10
|
-
path: string;
|
|
11
|
-
component?: React.LazyExoticComponent<() => JSX.Element>;
|
|
12
|
-
render?: () => JSX.Element;
|
|
13
|
-
requireAuth?: boolean;
|
|
14
|
-
excludeFromMenu?: boolean;
|
|
15
|
-
label?: string;
|
|
16
|
-
}
|
|
17
24
|
|
|
18
|
-
export const ROUTES:
|
|
19
|
-
|
|
25
|
+
export const ROUTES: RoutesConfig = {
|
|
26
|
+
home: {
|
|
20
27
|
path: '/',
|
|
21
|
-
component:
|
|
28
|
+
component: HomePage.Component,
|
|
22
29
|
label: 'Home',
|
|
30
|
+
preloadChunks: ['home'],
|
|
23
31
|
},
|
|
24
32
|
page1: {
|
|
25
33
|
path: '/page1',
|
|
26
|
-
component: lazy(
|
|
34
|
+
component: lazy(
|
|
35
|
+
() => import(/* webpackChunkName: "page1" */ './pages/Page1')
|
|
36
|
+
),
|
|
27
37
|
label: 'Protected page',
|
|
28
38
|
requireAuth: true,
|
|
39
|
+
preloadChunks: ['page1'],
|
|
29
40
|
},
|
|
30
41
|
signin: {
|
|
31
42
|
path: '/signin',
|
|
32
|
-
component:
|
|
43
|
+
component: SigninPage.Component,
|
|
33
44
|
label: 'Sign In',
|
|
34
45
|
excludeFromMenu: true,
|
|
46
|
+
preloadChunks: ['signin'],
|
|
35
47
|
},
|
|
36
48
|
};
|
|
37
49
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ComponentType, lazy } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface PreloadableComponent<T extends ComponentType<any>> {
|
|
4
|
+
preload: () => Promise<{ default: T }>;
|
|
5
|
+
Component: React.LazyExoticComponent<T>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Creates a lazy-loaded component with a preload function
|
|
10
|
+
* This allows preloading the component before React needs it
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const SigninPage = lazyWithPreload(() => import('./pages/Signin'));
|
|
14
|
+
* // Later, before navigation or on server:
|
|
15
|
+
* SigninPage.preload();
|
|
16
|
+
*/
|
|
17
|
+
export function lazyWithPreload<T extends ComponentType<any>>(
|
|
18
|
+
importFunc: () => Promise<{ default: T }>
|
|
19
|
+
): PreloadableComponent<T> {
|
|
20
|
+
let modulePromise: Promise<{ default: T }> | null = null;
|
|
21
|
+
|
|
22
|
+
const preload = () => {
|
|
23
|
+
if (!modulePromise) {
|
|
24
|
+
modulePromise = importFunc();
|
|
25
|
+
}
|
|
26
|
+
return modulePromise;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const Component = lazy(() => {
|
|
30
|
+
// If preload was called, reuse the same promise
|
|
31
|
+
// This ensures React uses the already-loaded module
|
|
32
|
+
if (!modulePromise) {
|
|
33
|
+
modulePromise = importFunc();
|
|
34
|
+
}
|
|
35
|
+
return modulePromise;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
preload,
|
|
40
|
+
Component,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side script to preload lazy routes before hydration
|
|
3
|
+
* This should be called BEFORE React's hydrateRoot()
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// This will be populated by the server with the routes that need preloading
|
|
7
|
+
declare global {
|
|
8
|
+
interface Window {
|
|
9
|
+
__PRELOAD_ROUTES__?: string[];
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function preloadMatchedRoute() {
|
|
14
|
+
// Get the list of routes to preload from the server
|
|
15
|
+
const routesToPreload = window.__PRELOAD_ROUTES__ || [];
|
|
16
|
+
|
|
17
|
+
if (routesToPreload.length === 0) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Dynamically import the routes module to access PRELOADABLE_ROUTES
|
|
22
|
+
const routesModule = await import('../routes');
|
|
23
|
+
const { PRELOADABLE_ROUTES } = routesModule;
|
|
24
|
+
|
|
25
|
+
// Preload each route
|
|
26
|
+
const preloadPromises = routesToPreload
|
|
27
|
+
.map((routeKey) => {
|
|
28
|
+
const preloadableRoute = PRELOADABLE_ROUTES[routeKey];
|
|
29
|
+
if (preloadableRoute && preloadableRoute.preload) {
|
|
30
|
+
return preloadableRoute.preload();
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
})
|
|
34
|
+
.filter(Boolean);
|
|
35
|
+
|
|
36
|
+
// Wait for all preloads to complete
|
|
37
|
+
await Promise.all(preloadPromises);
|
|
38
|
+
}
|
package/lib/cjs/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lincd-cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"description": "Command line tools for the lincd.js library",
|
|
5
5
|
"typesVersions": {
|
|
6
6
|
"*": {
|
|
@@ -110,6 +110,7 @@
|
|
|
110
110
|
"postcss-reporter": "^7.1.0",
|
|
111
111
|
"postcss-strip-inline-comments": "^0.1.5",
|
|
112
112
|
"postcss-url": "^10.1.3",
|
|
113
|
+
"react-refresh": "^0.18.0",
|
|
113
114
|
"react-refresh-typescript": "^2.0.10",
|
|
114
115
|
"require-extensions": "^0.0.4",
|
|
115
116
|
"rimraf": "^5.0.7",
|
package/lib/esm/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lincd-cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"description": "Command line tools for the lincd.js library",
|
|
5
5
|
"typesVersions": {
|
|
6
6
|
"*": {
|
|
@@ -110,6 +110,7 @@
|
|
|
110
110
|
"postcss-reporter": "^7.1.0",
|
|
111
111
|
"postcss-strip-inline-comments": "^0.1.5",
|
|
112
112
|
"postcss-url": "^10.1.3",
|
|
113
|
+
"react-refresh": "^0.18.0",
|
|
113
114
|
"react-refresh-typescript": "^2.0.10",
|
|
114
115
|
"require-extensions": "^0.0.4",
|
|
115
116
|
"rimraf": "^5.0.7",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lincd-cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"description": "Command line tools for the lincd.js library",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -130,6 +130,7 @@
|
|
|
130
130
|
"postcss-reporter": "^7.1.0",
|
|
131
131
|
"postcss-strip-inline-comments": "^0.1.5",
|
|
132
132
|
"postcss-url": "^10.1.3",
|
|
133
|
+
"react-refresh": "^0.18.0",
|
|
133
134
|
"react-refresh-typescript": "^2.0.10",
|
|
134
135
|
"require-extensions": "^0.0.4",
|
|
135
136
|
"rimraf": "^5.0.7",
|