@umijs/renderer-react 4.0.0-rc.2 → 4.0.0-rc.22

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.
@@ -1,3 +1,16 @@
1
1
  import React from 'react';
2
- export declare const AppContext: React.Context<any>;
3
- export declare function useAppData(): any;
2
+ import { IClientRoute, ILoaderData, IRouteComponents, IRoutesById } from './types';
3
+ interface IAppCentextType {
4
+ routes: IRoutesById;
5
+ routeComponents: IRouteComponents;
6
+ clientRoutes: IClientRoute[];
7
+ pluginManager: any;
8
+ rootElement?: HTMLElement;
9
+ basename?: string;
10
+ clientLoaderData: ILoaderData;
11
+ preloadRoute: (to: string) => void;
12
+ }
13
+ export declare const AppContext: React.Context<IAppCentextType>;
14
+ export declare function useAppData(): IAppCentextType;
15
+ export declare function useClientLoaderData(): any;
16
+ export {};
@@ -1,5 +1,11 @@
1
1
  import React from 'react';
2
- export const AppContext = React.createContext(null);
2
+ import { useRouteData } from './routeContext';
3
+ export const AppContext = React.createContext({});
3
4
  export function useAppData() {
4
5
  return React.useContext(AppContext);
5
6
  }
7
+ export function useClientLoaderData() {
8
+ const route = useRouteData();
9
+ const appData = useAppData();
10
+ return appData.clientLoaderData[route.route.id];
11
+ }
package/dist/browser.d.ts CHANGED
@@ -2,6 +2,8 @@ import { History } from 'history';
2
2
  import React from 'react';
3
3
  import { IRouteComponents, IRoutesById } from './types';
4
4
  export declare function renderClient(opts: {
5
+ publicPath?: string;
6
+ runtimePublicPath?: boolean;
5
7
  rootElement?: HTMLElement;
6
8
  routes: IRoutesById;
7
9
  routeComponents: IRouteComponents;
package/dist/browser.js CHANGED
@@ -1,6 +1,7 @@
1
- import React from 'react';
2
- import ReactDOM from 'react-dom';
3
- import { Router, useRoutes } from 'react-router-dom';
1
+ import React, { useCallback, useEffect, useState } from 'react';
2
+ // compatible with < react@18 in @umijs/preset-umi/src/features/react
3
+ import ReactDOM from 'react-dom/client';
4
+ import { matchRoutes, Router, useRoutes } from 'react-router-dom';
4
5
  import { AppContext, useAppData } from './appContext';
5
6
  import { createClientRoutes } from './routes';
6
7
  function BrowserRoutes(props) {
@@ -10,18 +11,22 @@ function BrowserRoutes(props) {
10
11
  location: history.location,
11
12
  });
12
13
  React.useLayoutEffect(() => history.listen(setState), [history]);
13
- React.useLayoutEffect(() => history.listen((location, action) => {
14
- props.pluginManager.applyPlugins({
15
- key: 'onRouteChange',
16
- type: 'event',
17
- args: {
18
- routes: props.routes,
19
- clientRoutes: props.clientRoutes,
20
- location,
21
- action,
22
- },
23
- });
24
- }), [history, props.routes, props.clientRoutes]);
14
+ React.useLayoutEffect(() => {
15
+ function onRouteChange(opts) {
16
+ props.pluginManager.applyPlugins({
17
+ key: 'onRouteChange',
18
+ type: 'event',
19
+ args: {
20
+ routes: props.routes,
21
+ clientRoutes: props.clientRoutes,
22
+ location: opts.location,
23
+ action: opts.action,
24
+ },
25
+ });
26
+ }
27
+ history.listen(onRouteChange);
28
+ onRouteChange({ location: state.location, action: state.action });
29
+ }, [history, props.routes, props.clientRoutes]);
25
30
  return (React.createElement(Router, { navigator: history, location: state.location, basename: props.basename }, props.children));
26
31
  }
27
32
  function Routes() {
@@ -36,6 +41,13 @@ export function renderClient(opts) {
36
41
  routeComponents: opts.routeComponents,
37
42
  loadingComponent: opts.loadingComponent,
38
43
  });
44
+ opts.pluginManager.applyPlugins({
45
+ key: 'patchClientRoutes',
46
+ type: 'event',
47
+ args: {
48
+ routes: clientRoutes,
49
+ },
50
+ });
39
51
  let rootContainer = (React.createElement(BrowserRoutes, { basename: basename, pluginManager: opts.pluginManager, routes: opts.routes, clientRoutes: clientRoutes, history: opts.history },
40
52
  React.createElement(Routes, null)));
41
53
  for (const key of [
@@ -54,20 +66,72 @@ export function renderClient(opts) {
54
66
  args: {},
55
67
  });
56
68
  }
57
- const browser = (React.createElement(AppContext.Provider, { value: {
58
- routes: opts.routes,
59
- routeComponents: opts.routeComponents,
60
- clientRoutes,
61
- pluginManager: opts.pluginManager,
62
- rootElement: opts.rootElement,
63
- basename,
64
- } }, rootContainer));
65
- // @ts-ignore
69
+ const Browser = () => {
70
+ const [clientLoaderData, setClientLoaderData] = useState({});
71
+ const handleRouteChange = useCallback((p) => {
72
+ var _a;
73
+ // Patched routes has to id
74
+ const matchedRouteIds = (((_a = matchRoutes(clientRoutes, p)) === null || _a === void 0 ? void 0 : _a.map(
75
+ // @ts-ignore
76
+ (route) => route.route.id)) || []).filter(Boolean);
77
+ matchedRouteIds.forEach((id) => {
78
+ // preload
79
+ // @ts-ignore
80
+ const manifest = window.__umi_manifest__;
81
+ if (manifest) {
82
+ const routeIdReplaced = id.replace(/[\/\-]/g, '_');
83
+ const preloadId = 'preload-' + routeIdReplaced;
84
+ if (!document.getElementById(preloadId)) {
85
+ const key = Object.keys(manifest).find((k) => k.startsWith(routeIdReplaced + '.'));
86
+ if (!key)
87
+ return;
88
+ let file = manifest[key];
89
+ const link = document.createElement('link');
90
+ link.id = preloadId;
91
+ link.rel = 'preload';
92
+ link.as = 'script';
93
+ // publicPath already in the manifest,
94
+ // but if runtimePublicPath is true, we need to replace it
95
+ if (opts.runtimePublicPath) {
96
+ file = file.replace(new RegExp(`^${opts.publicPath}`),
97
+ // @ts-ignore
98
+ window.publicPath);
99
+ }
100
+ link.href = file;
101
+ document.head.appendChild(link);
102
+ }
103
+ }
104
+ // client loader
105
+ const clientLoader = opts.routes[id].clientLoader;
106
+ if (clientLoader && !clientLoaderData[id]) {
107
+ clientLoader().then((data) => {
108
+ setClientLoaderData((d) => ({ ...d, [id]: data }));
109
+ });
110
+ }
111
+ });
112
+ }, [clientLoaderData]);
113
+ useEffect(() => {
114
+ handleRouteChange(window.location.pathname);
115
+ return opts.history.listen((e) => {
116
+ handleRouteChange(e.location.pathname);
117
+ });
118
+ }, []);
119
+ return (React.createElement(AppContext.Provider, { value: {
120
+ routes: opts.routes,
121
+ routeComponents: opts.routeComponents,
122
+ clientRoutes,
123
+ pluginManager: opts.pluginManager,
124
+ rootElement: opts.rootElement,
125
+ basename,
126
+ clientLoaderData,
127
+ preloadRoute: handleRouteChange,
128
+ } }, rootContainer));
129
+ };
66
130
  if (ReactDOM.createRoot) {
67
- // @ts-ignore
68
- ReactDOM.createRoot(rootElement).render(browser);
131
+ ReactDOM.createRoot(rootElement).render(React.createElement(Browser, null));
69
132
  }
70
133
  else {
71
- ReactDOM.render(browser, rootElement);
134
+ // @ts-ignore
135
+ ReactDOM.render(React.createElement(Browser, null), rootElement);
72
136
  }
73
137
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { createBrowserHistory, createHashHistory, createMemoryHistory, History, } from 'history';
2
- export { createSearchParams, Link, matchPath, matchRoutes, NavLink, Outlet, useLocation, useMatch, useNavigate, useOutlet, useParams, useResolvedPath, useRoutes, useSearchParams, } from 'react-router-dom';
3
- export { useAppData } from './appContext';
2
+ export { createSearchParams, matchPath, matchRoutes, Navigate, NavLink, Outlet, resolvePath, useLocation, useMatch, useNavigate, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes, useSearchParams, } from 'react-router-dom';
3
+ export { useAppData, useClientLoaderData } from './appContext';
4
4
  export { renderClient } from './browser';
5
+ export { LinkWithPrefetch as Link } from './link';
5
6
  export { useRouteData } from './routeContext';
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { createBrowserHistory, createHashHistory, createMemoryHistory, } from 'history';
2
- export { createSearchParams, Link, matchPath, matchRoutes, NavLink, Outlet, useLocation, useMatch, useNavigate, useOutlet, useParams, useResolvedPath, useRoutes, useSearchParams, } from 'react-router-dom';
3
- export { useAppData } from './appContext';
2
+ export { createSearchParams, matchPath, matchRoutes, Navigate, NavLink, Outlet, resolvePath, useLocation, useMatch, useNavigate, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes, useSearchParams, } from 'react-router-dom';
3
+ export { useAppData, useClientLoaderData } from './appContext';
4
4
  export { renderClient } from './browser';
5
+ export { LinkWithPrefetch as Link } from './link';
5
6
  export { useRouteData } from './routeContext';
package/dist/link.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import React, { PropsWithChildren } from 'react';
2
+ import { LinkProps } from 'react-router-dom';
3
+ export declare function LinkWithPrefetch(props: PropsWithChildren<{
4
+ prefetch?: boolean;
5
+ } & LinkProps & React.RefAttributes<HTMLAnchorElement>>): JSX.Element;
package/dist/link.js ADDED
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { Link } from 'react-router-dom';
3
+ import { useAppData } from './appContext';
4
+ export function LinkWithPrefetch(props) {
5
+ const appData = useAppData();
6
+ const to = typeof props.to === 'string' ? props.to : props.to.pathname;
7
+ return (React.createElement(Link, { onMouseEnter: () => props.prefetch && to && appData.preloadRoute(to), ...props }, props.children));
8
+ }
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
+ import { IRoute } from './types';
2
3
  export interface IRouteContextType {
3
- route: any;
4
+ route: IRoute;
4
5
  }
5
6
  export declare const RouteContext: React.Context<IRouteContextType | undefined>;
6
7
  export declare function useRouteData(): IRouteContextType;
package/dist/routes.d.ts CHANGED
@@ -1,25 +1,8 @@
1
1
  import React from 'react';
2
- import { IRoute, IRoutesById } from './types';
2
+ import { IClientRoute, IRoutesById } from './types';
3
3
  export declare function createClientRoutes(opts: {
4
4
  routesById: IRoutesById;
5
5
  routeComponents: Record<string, any>;
6
6
  parentId?: string;
7
7
  loadingComponent?: React.ReactNode;
8
- }): {
9
- parentId?: string | undefined;
10
- id: string;
11
- path: string | undefined;
12
- index: boolean | undefined;
13
- element: JSX.Element;
14
- }[];
15
- export declare function createClientRoute(opts: {
16
- route: IRoute;
17
- routeComponent: any;
18
- loadingComponent?: React.ReactNode;
19
- }): {
20
- parentId?: string | undefined;
21
- id: string;
22
- path: string | undefined;
23
- index: boolean | undefined;
24
- element: JSX.Element;
25
- };
8
+ }): IClientRoute[];
package/dist/routes.js CHANGED
@@ -1,14 +1,3 @@
1
- var __rest = (this && this.__rest) || function (s, e) {
2
- var t = {};
3
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
- t[p] = s[p];
5
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
- t[p[i]] = s[p[i]];
9
- }
10
- return t;
11
- };
12
1
  // @ts-ignore
13
2
  import loadable from '@loadable/component';
14
3
  import React from 'react';
@@ -31,26 +20,29 @@ export function createClientRoutes(opts) {
31
20
  loadingComponent: opts.loadingComponent,
32
21
  });
33
22
  if (children.length > 0) {
34
- // @ts-ignore
35
23
  route.children = children;
36
24
  // TODO: remove me
37
25
  // compatible with @ant-design/pro-layout
38
- // @ts-ignore
39
26
  route.routes = children;
40
27
  }
41
28
  return route;
42
29
  });
43
30
  }
44
- export function createClientRoute(opts) {
31
+ function createClientRoute(opts) {
45
32
  const { route } = opts;
46
- const { id, path, index, redirect } = route, props = __rest(route, ["id", "path", "index", "redirect"]);
47
- return Object.assign({ id: id, path: path, index: index, element: redirect ? (React.createElement(Navigate, { to: redirect })) : (React.createElement(RouteContext.Provider, { value: {
33
+ const { redirect, ...props } = route;
34
+ return {
35
+ children: [],
36
+ routes: [],
37
+ element: redirect ? (React.createElement(Navigate, { to: redirect })) : (React.createElement(RouteContext.Provider, { value: {
48
38
  route: opts.route,
49
39
  } },
50
- React.createElement(RemoteComponent, { loader: opts.routeComponent, loadingComponent: opts.loadingComponent || DefaultLoading }))) }, props);
40
+ React.createElement(RemoteComponent, { loader: opts.routeComponent, loadingComponent: opts.loadingComponent || DefaultLoading }))),
41
+ ...props,
42
+ };
51
43
  }
52
44
  function DefaultLoading() {
53
- return React.createElement("div", null, "Loading...");
45
+ return React.createElement("div", null);
54
46
  }
55
47
  function RemoteComponent(props) {
56
48
  const Component = loadable(props.loader, {
package/dist/types.d.ts CHANGED
@@ -1,9 +1,21 @@
1
+ /// <reference types="react" />
1
2
  export interface IRoute {
2
3
  id: string;
3
4
  path?: string;
4
5
  index?: boolean;
5
6
  parentId?: string;
6
7
  redirect?: string;
8
+ clientLoader?: () => Promise<any>;
9
+ }
10
+ export interface IClientRoute {
11
+ id: string;
12
+ element: React.ReactNode;
13
+ children: IClientRoute[];
14
+ routes: IClientRoute[];
15
+ path?: string;
16
+ index?: boolean;
17
+ parentId?: string;
18
+ clientLoader?: () => Promise<any>;
7
19
  }
8
20
  export interface IRoutesById {
9
21
  [id: string]: IRoute;
@@ -11,3 +23,6 @@ export interface IRoutesById {
11
23
  export interface IRouteComponents {
12
24
  [id: string]: any;
13
25
  }
26
+ export interface ILoaderData {
27
+ [routeKey: string]: any;
28
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umijs/renderer-react",
3
- "version": "4.0.0-rc.2",
3
+ "version": "4.0.0-rc.22",
4
4
  "description": "@umijs/renderer-react",
5
5
  "homepage": "https://github.com/umijs/umi-next/tree/master/packages/renderer-react#readme",
6
6
  "bugs": "https://github.com/umijs/umi-next/issues",
@@ -17,17 +17,18 @@
17
17
  ],
18
18
  "scripts": {
19
19
  "build": "pnpm tsc",
20
- "build:deps": "pnpm esno ../../scripts/bundleDeps.ts",
21
- "dev": "pnpm build -- --watch"
20
+ "build:deps": "umi-scripts bundleDeps",
21
+ "dev": "pnpm build -- --watch",
22
+ "test": "umi-scripts jest-turbo"
22
23
  },
23
24
  "dependencies": {
24
25
  "@loadable/component": "5.15.2",
25
- "history": "5.2.0",
26
- "react-router-dom": "6.2.1"
26
+ "history": "5.3.0",
27
+ "react-router-dom": "6.3.0"
27
28
  },
28
29
  "devDependencies": {
29
- "react": "17.0.2",
30
- "react-dom": "17.0.2"
30
+ "react": "18.1.0",
31
+ "react-dom": "18.1.0"
31
32
  },
32
33
  "peerDependencies": {
33
34
  "react": ">=16.8",