@umijs/renderer-react 4.0.0-canary.20220615.2 → 4.0.0-canary.20220628.1

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,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { IClientRoute, ILoaderData, IRouteComponents, IRoutesById } from './types';
3
- interface IAppCentextType {
3
+ interface IAppContextType {
4
4
  routes: IRoutesById;
5
5
  routeComponents: IRouteComponents;
6
6
  clientRoutes: IClientRoute[];
@@ -8,9 +8,15 @@ interface IAppCentextType {
8
8
  rootElement?: HTMLElement;
9
9
  basename?: string;
10
10
  clientLoaderData: ILoaderData;
11
- preloadRoute: (to: string) => void;
11
+ preloadRoute?: (to: string) => void;
12
+ serverLoaderData: ILoaderData;
12
13
  }
13
- export declare const AppContext: React.Context<IAppCentextType>;
14
- export declare function useAppData(): IAppCentextType;
15
- export declare function useClientLoaderData(): any;
14
+ export declare const AppContext: React.Context<IAppContextType>;
15
+ export declare function useAppData(): IAppContextType;
16
+ export declare function useServerLoaderData(): {
17
+ data: any;
18
+ };
19
+ export declare function useClientLoaderData(): {
20
+ data: any;
21
+ };
16
22
  export {};
@@ -4,8 +4,13 @@ export const AppContext = React.createContext({});
4
4
  export function useAppData() {
5
5
  return React.useContext(AppContext);
6
6
  }
7
+ export function useServerLoaderData() {
8
+ const route = useRouteData();
9
+ const appData = useAppData();
10
+ return { data: appData.serverLoaderData[route.route.id] };
11
+ }
7
12
  export function useClientLoaderData() {
8
13
  const route = useRouteData();
9
14
  const appData = useAppData();
10
- return appData.clientLoaderData[route.route.id];
15
+ return { data: appData.clientLoaderData[route.route.id] };
11
16
  }
package/dist/browser.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { History } from 'history';
2
2
  import React from 'react';
3
3
  import { IRouteComponents, IRoutesById } from './types';
4
+ export declare function Routes(): React.ReactElement<any, string | React.JSXElementConstructor<any>> | null;
4
5
  export declare function renderClient(opts: {
5
6
  publicPath?: string;
6
7
  runtimePublicPath?: boolean;
@@ -11,4 +12,5 @@ export declare function renderClient(opts: {
11
12
  basename?: string;
12
13
  loadingComponent?: React.ReactNode;
13
14
  history: History;
15
+ hydrate?: boolean;
14
16
  }): void;
package/dist/browser.js CHANGED
@@ -29,7 +29,7 @@ function BrowserRoutes(props) {
29
29
  }, [history, props.routes, props.clientRoutes]);
30
30
  return (React.createElement(Router, { navigator: history, location: state.location, basename: props.basename }, props.children));
31
31
  }
32
- function Routes() {
32
+ export function Routes() {
33
33
  const { clientRoutes } = useAppData();
34
34
  return useRoutes(clientRoutes);
35
35
  }
@@ -68,10 +68,13 @@ export function renderClient(opts) {
68
68
  }
69
69
  const Browser = () => {
70
70
  const [clientLoaderData, setClientLoaderData] = useState({});
71
- const handleRouteChange = useCallback((p) => {
71
+ const [serverLoaderData, setServerLoaderData] = useState(
72
+ // @ts-ignore
73
+ window.__UMI_LOADER_DATA__ || {});
74
+ const handleRouteChange = useCallback((id, isFirst) => {
72
75
  var _a;
73
76
  // Patched routes has to id
74
- const matchedRouteIds = (((_a = matchRoutes(clientRoutes, p)) === null || _a === void 0 ? void 0 : _a.map(
77
+ const matchedRouteIds = (((_a = matchRoutes(clientRoutes, id)) === null || _a === void 0 ? void 0 : _a.map(
75
78
  // @ts-ignore
76
79
  (route) => route.route.id)) || []).filter(Boolean);
77
80
  matchedRouteIds.forEach((id) => {
@@ -102,6 +105,19 @@ export function renderClient(opts) {
102
105
  document.head.appendChild(link);
103
106
  }
104
107
  }
108
+ // server loader
109
+ if (!isFirst && opts.routes[id].hasServerLoader) {
110
+ fetch('/__serverLoader?route=' + id)
111
+ .then((d) => d.json())
112
+ .then((data) => {
113
+ // setServerLoaderData when startTransition because if ssr is enabled,
114
+ // the component may being hydrated and setLoaderData will break the hydration
115
+ React.startTransition(() => {
116
+ setServerLoaderData((d) => ({ ...d, [id]: data }));
117
+ });
118
+ })
119
+ .catch(console.error);
120
+ }
105
121
  // client loader
106
122
  // onPatchClientRoutes 添加的 route 在 opts.routes 里是不存在的
107
123
  const clientLoader = (_a = opts.routes[id]) === null || _a === void 0 ? void 0 : _a.clientLoader;
@@ -113,7 +129,7 @@ export function renderClient(opts) {
113
129
  });
114
130
  }, [clientLoaderData]);
115
131
  useEffect(() => {
116
- handleRouteChange(window.location.pathname);
132
+ handleRouteChange(window.location.pathname, true);
117
133
  return opts.history.listen((e) => {
118
134
  handleRouteChange(e.location.pathname);
119
135
  });
@@ -126,14 +142,20 @@ export function renderClient(opts) {
126
142
  rootElement: opts.rootElement,
127
143
  basename,
128
144
  clientLoaderData,
145
+ serverLoaderData,
129
146
  preloadRoute: handleRouteChange,
130
147
  } }, rootContainer));
131
148
  };
132
- if (ReactDOM.createRoot) {
133
- ReactDOM.createRoot(rootElement).render(React.createElement(Browser, null));
149
+ if (opts.hydrate) {
150
+ ReactDOM.hydrateRoot(rootElement, React.createElement(Browser, null));
134
151
  }
135
152
  else {
136
- // @ts-ignore
137
- ReactDOM.render(React.createElement(Browser, null), rootElement);
153
+ if (ReactDOM.createRoot) {
154
+ ReactDOM.createRoot(rootElement).render(React.createElement(Browser, null));
155
+ }
156
+ else {
157
+ // @ts-ignore
158
+ ReactDOM.render(React.createElement(Browser, null), rootElement);
159
+ }
138
160
  }
139
161
  }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { createBrowserHistory, createHashHistory, createMemoryHistory, History, } from 'history';
2
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';
3
+ export { useAppData, useClientLoaderData, useServerLoaderData, } from './appContext';
4
4
  export { renderClient } from './browser';
5
5
  export { LinkWithPrefetch as Link } from './link';
6
6
  export { useRouteData } from './routeContext';
7
+ export { __useFetcher } from './useFetcher';
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export { createBrowserHistory, createHashHistory, createMemoryHistory, } from 'history';
2
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';
3
+ export { useAppData, useClientLoaderData, useServerLoaderData, } from './appContext';
4
4
  export { renderClient } from './browser';
5
5
  export { LinkWithPrefetch as Link } from './link';
6
6
  export { useRouteData } from './routeContext';
7
+ export { __useFetcher } from './useFetcher';
package/dist/link.js CHANGED
@@ -4,5 +4,5 @@ import { useAppData } from './appContext';
4
4
  export function LinkWithPrefetch(props) {
5
5
  const appData = useAppData();
6
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));
7
+ return (React.createElement(Link, { onMouseEnter: () => { var _a; return props.prefetch && to && ((_a = appData.preloadRoute) === null || _a === void 0 ? void 0 : _a.call(appData, to)); }, ...props }, props.children));
8
8
  }
package/dist/routes.js CHANGED
@@ -1,5 +1,4 @@
1
1
  // @ts-ignore
2
- import loadable from '@loadable/component';
3
2
  import React from 'react';
4
3
  import { Navigate } from 'react-router-dom';
5
4
  import { RouteContext } from './routeContext';
@@ -43,8 +42,19 @@ function DefaultLoading() {
43
42
  return React.createElement("div", null);
44
43
  }
45
44
  function RemoteComponent(props) {
46
- const Component = loadable(props.loader, {
47
- fallback: React.createElement(props.loadingComponent, null),
48
- });
49
- return React.createElement(Component, null);
45
+ const useSuspense = true; // !!React.startTransition;
46
+ if (useSuspense) {
47
+ const Component = props.loader;
48
+ return (React.createElement(React.Suspense, { fallback: React.createElement(props.loadingComponent, null) },
49
+ React.createElement(Component, null)));
50
+ }
51
+ else {
52
+ return null;
53
+ // // @ts-ignore
54
+ // import loadable from '@loadable/component';
55
+ // const Component = loadable(props.loader, {
56
+ // fallback: <props.loadingComponent />,
57
+ // });
58
+ // return <Component />;
59
+ }
50
60
  }
@@ -0,0 +1,12 @@
1
+ /// <reference types="react" />
2
+ import { IRouteComponents, IRoutesById } from './types';
3
+ export declare function getClientRootComponent(opts: {
4
+ routes: IRoutesById;
5
+ routeComponents: IRouteComponents;
6
+ pluginManager: any;
7
+ location: string;
8
+ loaderData: {
9
+ [routeKey: string]: any;
10
+ };
11
+ manifest: any;
12
+ }): Promise<JSX.Element>;
package/dist/server.js ADDED
@@ -0,0 +1,59 @@
1
+ import React from 'react';
2
+ import { StaticRouter } from 'react-router-dom/server';
3
+ import { AppContext } from './appContext';
4
+ import { Routes } from './browser';
5
+ import { createClientRoutes } from './routes';
6
+ // Get the root React component for ReactDOMServer.renderToString
7
+ export async function getClientRootComponent(opts) {
8
+ const basename = '/';
9
+ const components = { ...opts.routeComponents };
10
+ const clientRoutes = createClientRoutes({
11
+ routesById: opts.routes,
12
+ routeComponents: components,
13
+ });
14
+ let rootContainer = (React.createElement(StaticRouter, { basename: basename, location: opts.location },
15
+ React.createElement(Routes, null)));
16
+ for (const key of [
17
+ // Lowest to the highest priority
18
+ 'innerProvider',
19
+ 'i18nProvider',
20
+ 'accessProvider',
21
+ 'dataflowProvider',
22
+ 'outerProvider',
23
+ 'rootContainer',
24
+ ]) {
25
+ rootContainer = opts.pluginManager.applyPlugins({
26
+ type: 'modify',
27
+ key: key,
28
+ initialValue: rootContainer,
29
+ args: {},
30
+ });
31
+ }
32
+ return (React.createElement(Html, { loaderData: opts.loaderData, manifest: opts.manifest },
33
+ React.createElement(AppContext.Provider, { value: {
34
+ routes: opts.routes,
35
+ routeComponents: opts.routeComponents,
36
+ clientRoutes,
37
+ pluginManager: opts.pluginManager,
38
+ basename,
39
+ clientLoaderData: {},
40
+ serverLoaderData: opts.loaderData,
41
+ } }, rootContainer)));
42
+ }
43
+ function Html({ children, loaderData, manifest }) {
44
+ // TODO: 处理 head 标签,比如 favicon.ico 的一致性
45
+ // TODO: root 支持配置
46
+ return (React.createElement("html", { lang: "en" },
47
+ React.createElement("head", null,
48
+ React.createElement("meta", { charSet: "utf-8" }),
49
+ React.createElement("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }),
50
+ manifest.assets['umi.css'] && (React.createElement("link", { rel: "stylesheet", href: manifest.assets['umi.css'] }))),
51
+ React.createElement("body", null,
52
+ React.createElement("noscript", { dangerouslySetInnerHTML: {
53
+ __html: `<b>Enable JavaScript to run this app.</b>`,
54
+ } }),
55
+ React.createElement("div", { id: "root" }, children),
56
+ React.createElement("script", { dangerouslySetInnerHTML: {
57
+ __html: `window.__UMI_LOADER_DATA__ = ${JSON.stringify(loaderData)}`,
58
+ } }))));
59
+ }
package/dist/types.d.ts CHANGED
@@ -6,6 +6,7 @@ export interface IRoute {
6
6
  parentId?: string;
7
7
  redirect?: string;
8
8
  clientLoader?: () => Promise<any>;
9
+ hasServerLoader?: boolean;
9
10
  }
10
11
  export interface IClientRoute {
11
12
  id: string;
@@ -0,0 +1,3 @@
1
+ export declare function __useFetcher(): {
2
+ load(path?: string): void;
3
+ };
@@ -0,0 +1,11 @@
1
+ import { useLocation } from 'react-router-dom';
2
+ import { useAppData } from './appContext';
3
+ export function __useFetcher() {
4
+ const { preloadRoute } = useAppData();
5
+ const location = useLocation();
6
+ return {
7
+ load(path) {
8
+ preloadRoute(path || location.pathname);
9
+ },
10
+ };
11
+ }
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@umijs/renderer-react",
3
- "version": "4.0.0-canary.20220615.2",
3
+ "version": "4.0.0-canary.20220628.1",
4
4
  "description": "@umijs/renderer-react",
5
- "homepage": "https://github.com/umijs/umi-next/tree/master/packages/renderer-react#readme",
6
- "bugs": "https://github.com/umijs/umi-next/issues",
5
+ "homepage": "https://github.com/umijs/umi/tree/master/packages/renderer-react#readme",
6
+ "bugs": "https://github.com/umijs/umi/issues",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "https://github.com/umijs/umi-next"
9
+ "url": "https://github.com/umijs/umi"
10
10
  },
11
11
  "license": "MIT",
12
12
  "sideEffects": false,
@@ -18,7 +18,7 @@
18
18
  "scripts": {
19
19
  "build": "pnpm tsc",
20
20
  "build:deps": "umi-scripts bundleDeps",
21
- "dev": "pnpm build -- --watch",
21
+ "dev": "pnpm build --watch",
22
22
  "test": "umi-scripts jest-turbo"
23
23
  },
24
24
  "dependencies": {