@umijs/renderer-react 4.2.15 → 4.3.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.
@@ -23,4 +23,5 @@ export declare function useServerLoaderData<T extends ServerLoaderFunc = any>():
23
23
  export declare function useClientLoaderData(): {
24
24
  data: any;
25
25
  };
26
+ export declare function useLoaderData<T extends ServerLoaderFunc = any>(): Awaited<ReturnType<T>>;
26
27
  export {};
@@ -1,3 +1,4 @@
1
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
1
2
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
3
  import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
3
4
  var _excluded = ["element"];
@@ -25,6 +26,7 @@ export function useRouteProps() {
25
26
  props = _objectWithoutProperties(_ref, _excluded);
26
27
  return props;
27
28
  }
29
+ // @deprecated Please use `useLoaderData` instead.
28
30
  export function useServerLoaderData() {
29
31
  var routes = useSelectedRoutes();
30
32
  var _useAppData2 = useAppData(),
@@ -47,7 +49,6 @@ export function useServerLoaderData() {
47
49
  data = _React$useState2[0],
48
50
  setData = _React$useState2[1];
49
51
  React.useEffect(function () {
50
- // @ts-ignore
51
52
  if (!window.__UMI_LOADER_DATA__) {
52
53
  // 支持 ssr 降级,客户端兜底加载 serverLoader 数据
53
54
  Promise.all(routes.filter(function (route) {
@@ -75,10 +76,19 @@ export function useServerLoaderData() {
75
76
  data: data
76
77
  };
77
78
  }
79
+
80
+ // @deprecated Please use `useLoaderData` instead.
78
81
  export function useClientLoaderData() {
79
82
  var route = useRouteData();
80
83
  var appData = useAppData();
81
84
  return {
82
85
  data: appData.clientLoaderData[route.route.id]
83
86
  };
87
+ }
88
+ export function useLoaderData() {
89
+ var serverLoaderData = useServerLoaderData();
90
+ var clientLoaderData = useClientLoaderData();
91
+ return {
92
+ data: _objectSpread(_objectSpread({}, serverLoaderData.data), clientLoaderData.data)
93
+ };
84
94
  }
package/dist/browser.d.ts CHANGED
@@ -18,11 +18,26 @@ export declare type RenderClientOpts = {
18
18
  * @doc https://umijs.org/docs/api/config#runtimepublicpath
19
19
  */
20
20
  runtimePublicPath?: boolean;
21
+ /**
22
+ * react dom 渲染的的目标节点 id
23
+ * @doc 一般不需要改,微前端的时候会变化
24
+ */
25
+ mountElementId?: string;
21
26
  /**
22
27
  * react dom 渲染的的目标 dom
23
28
  * @doc 一般不需要改,微前端的时候会变化
24
29
  */
25
30
  rootElement?: HTMLElement;
31
+ __INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {
32
+ /**
33
+ * 内部流程, 渲染特殊 app 节点, 不要使用!!!
34
+ */
35
+ pureApp?: boolean;
36
+ /**
37
+ * 内部流程, 渲染特殊 html 节点, 不要使用!!!
38
+ */
39
+ pureHtml?: boolean;
40
+ };
26
41
  /**
27
42
  * 当前的路由配置
28
43
  */
@@ -73,4 +88,4 @@ export declare type RenderClientOpts = {
73
88
  * @param {RenderClientOpts} opts - 插件相关的配置
74
89
  * @returns void
75
90
  */
76
- export declare function renderClient(opts: RenderClientOpts): (() => JSX.Element) | undefined;
91
+ export declare function renderClient(opts: RenderClientOpts): (() => React.JSX.Element) | undefined;
package/dist/browser.js CHANGED
@@ -7,6 +7,7 @@ import ReactDOM from 'react-dom/client';
7
7
  import { matchRoutes, Router, useRoutes } from 'react-router-dom';
8
8
  import { AppContext, useAppData } from "./appContext";
9
9
  import { fetchServerLoader } from "./dataFetcher";
10
+ import { Html } from "./html";
10
11
  import { createClientRoutes } from "./routes";
11
12
  var root = null;
12
13
 
@@ -130,9 +131,7 @@ var getBrowser = function getBrowser(opts, routesElement) {
130
131
  _useState2 = _slicedToArray(_useState, 2),
131
132
  clientLoaderData = _useState2[0],
132
133
  setClientLoaderData = _useState2[1];
133
- var _useState3 = useState(
134
- // @ts-ignore
135
- window.__UMI_LOADER_DATA__ || {}),
134
+ var _useState3 = useState(window.__UMI_LOADER_DATA__ || {}),
136
135
  _useState4 = _slicedToArray(_useState3, 2),
137
136
  serverLoaderData = _useState4[0],
138
137
  setServerLoaderData = _useState4[1];
@@ -180,9 +179,13 @@ var getBrowser = function getBrowser(opts, routesElement) {
180
179
  });
181
180
  }
182
181
  }
182
+ var clientLoader = (_opts$routes$id = opts.routes[id]) === null || _opts$routes$id === void 0 ? void 0 : _opts$routes$id.clientLoader;
183
+ var hasClientLoader = !!clientLoader;
184
+ var hasServerLoader = (_opts$routes$id2 = opts.routes[id]) === null || _opts$routes$id2 === void 0 ? void 0 : _opts$routes$id2.hasServerLoader;
183
185
  // server loader
184
186
  // use ?. since routes patched with patchClientRoutes is not exists in opts.routes
185
- if (!isFirst && (_opts$routes$id = opts.routes[id]) !== null && _opts$routes$id !== void 0 && _opts$routes$id.hasServerLoader) {
187
+
188
+ if (!isFirst && hasServerLoader && !hasClientLoader && !window.__UMI_LOADER_DATA__) {
186
189
  fetchServerLoader({
187
190
  id: id,
188
191
  basename: basename,
@@ -199,9 +202,32 @@ var getBrowser = function getBrowser(opts, routesElement) {
199
202
  }
200
203
  // client loader
201
204
  // onPatchClientRoutes 添加的 route 在 opts.routes 里是不存在的
202
- var clientLoader = (_opts$routes$id2 = opts.routes[id]) === null || _opts$routes$id2 === void 0 ? void 0 : _opts$routes$id2.clientLoader;
203
- if (clientLoader && !clientLoaderData[id]) {
204
- clientLoader().then(function (data) {
205
+ var hasClientLoaderDataInRoute = !!clientLoaderData[id];
206
+
207
+ // Check if hydration is needed or there's no server loader for the current route
208
+ var shouldHydrateOrNoServerLoader = hasClientLoader && clientLoader.hydrate || !hasServerLoader;
209
+
210
+ // Check if server loader data is missing in the global window object
211
+ var isServerLoaderDataMissing = hasServerLoader && !window.__UMI_LOADER_DATA__;
212
+ if (hasClientLoader && !hasClientLoaderDataInRoute && (shouldHydrateOrNoServerLoader || isServerLoaderDataMissing)) {
213
+ // ...
214
+ clientLoader({
215
+ serverLoader: function serverLoader() {
216
+ return fetchServerLoader({
217
+ id: id,
218
+ basename: basename,
219
+ cb: function cb(data) {
220
+ // setServerLoaderData when startTransition because if ssr is enabled,
221
+ // the component may being hydrated and setLoaderData will break the hydration
222
+ React.startTransition(function () {
223
+ setServerLoaderData(function (d) {
224
+ return _objectSpread(_objectSpread({}, d), {}, _defineProperty({}, id, data));
225
+ });
226
+ });
227
+ }
228
+ });
229
+ }
230
+ }).then(function (data) {
205
231
  setClientLoaderData(function (d) {
206
232
  return _objectSpread(_objectSpread({}, d), {}, _defineProperty({}, id, data));
207
233
  });
@@ -247,7 +273,15 @@ export function renderClient(opts) {
247
273
  // 为了测试,直接返回组件
248
274
  if (opts.components) return Browser;
249
275
  if (opts.hydrate) {
250
- ReactDOM.hydrateRoot(rootElement, /*#__PURE__*/React.createElement(Browser, null));
276
+ var loaderData = window.__UMI_LOADER_DATA__ || {};
277
+ var metadata = window.__UMI_METADATA_LOADER_DATA__ || {};
278
+ var hydtateHtmloptions = {
279
+ metadata: metadata,
280
+ loaderData: loaderData,
281
+ mountElementId: opts.mountElementId
282
+ };
283
+ var _isInternal = opts.__INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.pureApp || opts.__INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.pureHtml;
284
+ ReactDOM.hydrateRoot(_isInternal ? rootElement : document, _isInternal ? /*#__PURE__*/React.createElement(Browser, null) : /*#__PURE__*/React.createElement(Html, hydtateHtmloptions, /*#__PURE__*/React.createElement(Browser, null)));
251
285
  return;
252
286
  }
253
287
  if (ReactDOM.createRoot) {
package/dist/html.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import { IHtmlProps } from './types';
3
+ export declare function Html({ children, loaderData, manifest, htmlPageOpts, __INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, mountElementId, }: React.PropsWithChildren<IHtmlProps>): React.JSX.Element;
package/dist/html.js ADDED
@@ -0,0 +1,168 @@
1
+ import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
2
+ import _extends from "@babel/runtime/helpers/esm/extends";
3
+ import _typeof from "@babel/runtime/helpers/esm/typeof";
4
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
5
+ var _excluded = ["content"],
6
+ _excluded2 = ["content"];
7
+ import React from 'react';
8
+ var RE_URL = /^(http:|https:)?\/\//;
9
+ function isUrl(str) {
10
+ return RE_URL.test(str) || str.startsWith('/') && !str.startsWith('/*') || str.startsWith('./') || str.startsWith('../');
11
+ }
12
+ var EnableJsScript = function EnableJsScript() {
13
+ return /*#__PURE__*/React.createElement("noscript", {
14
+ dangerouslySetInnerHTML: {
15
+ __html: "<b>Enable JavaScript to run this app.</b>"
16
+ }
17
+ });
18
+ };
19
+ var GlobalDataScript = function GlobalDataScript(props) {
20
+ var _manifest$assets;
21
+ var loaderData = props.loaderData,
22
+ htmlPageOpts = props.htmlPageOpts,
23
+ manifest = props.manifest;
24
+ var clientCssPath = (manifest === null || manifest === void 0 || (_manifest$assets = manifest.assets) === null || _manifest$assets === void 0 ? void 0 : _manifest$assets['umi.css']) || '';
25
+ return /*#__PURE__*/React.createElement("script", {
26
+ suppressHydrationWarning: true,
27
+ dangerouslySetInnerHTML: {
28
+ __html: "window.__UMI_LOADER_DATA__ = ".concat(JSON.stringify(loaderData || {}), "; window.__UMI_METADATA_LOADER_DATA__ = ").concat(JSON.stringify(htmlPageOpts || {}), "; window.__UMI_BUILD_ClIENT_CSS__ = '").concat(clientCssPath, "'")
29
+ }
30
+ });
31
+ };
32
+ function normalizeScripts(script) {
33
+ var extraProps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
34
+ if (typeof script === 'string') {
35
+ return isUrl(script) ? _objectSpread({
36
+ src: script
37
+ }, extraProps) : {
38
+ content: script
39
+ };
40
+ } else if (_typeof(script) === 'object') {
41
+ return _objectSpread(_objectSpread({}, script), extraProps);
42
+ } else {
43
+ throw new Error("Invalid script type: ".concat(_typeof(script)));
44
+ }
45
+ }
46
+ function generatorStyle(style) {
47
+ return isUrl(style) ? {
48
+ type: 'link',
49
+ href: style
50
+ } : {
51
+ type: 'style',
52
+ content: style
53
+ };
54
+ }
55
+ var HydrateMetadata = function HydrateMetadata(props) {
56
+ var _htmlPageOpts$favicon, _htmlPageOpts$keyword, _htmlPageOpts$metas, _htmlPageOpts$links, _htmlPageOpts$styles, _htmlPageOpts$headScr;
57
+ var htmlPageOpts = props.htmlPageOpts;
58
+ return /*#__PURE__*/React.createElement(React.Fragment, null, (htmlPageOpts === null || htmlPageOpts === void 0 ? void 0 : htmlPageOpts.title) && /*#__PURE__*/React.createElement("title", null, htmlPageOpts.title), htmlPageOpts === null || htmlPageOpts === void 0 || (_htmlPageOpts$favicon = htmlPageOpts.favicons) === null || _htmlPageOpts$favicon === void 0 ? void 0 : _htmlPageOpts$favicon.map(function (favicon, key) {
59
+ return /*#__PURE__*/React.createElement("link", {
60
+ key: key,
61
+ rel: "shortcut icon",
62
+ href: favicon
63
+ });
64
+ }), (htmlPageOpts === null || htmlPageOpts === void 0 ? void 0 : htmlPageOpts.description) && /*#__PURE__*/React.createElement("meta", {
65
+ name: "description",
66
+ content: htmlPageOpts.description
67
+ }), (htmlPageOpts === null || htmlPageOpts === void 0 || (_htmlPageOpts$keyword = htmlPageOpts.keywords) === null || _htmlPageOpts$keyword === void 0 ? void 0 : _htmlPageOpts$keyword.length) && /*#__PURE__*/React.createElement("meta", {
68
+ name: "keywords",
69
+ content: htmlPageOpts.keywords.join(',')
70
+ }), htmlPageOpts === null || htmlPageOpts === void 0 || (_htmlPageOpts$metas = htmlPageOpts.metas) === null || _htmlPageOpts$metas === void 0 ? void 0 : _htmlPageOpts$metas.map(function (em) {
71
+ return /*#__PURE__*/React.createElement("meta", {
72
+ key: em.name,
73
+ name: em.name,
74
+ content: em.content
75
+ });
76
+ }), htmlPageOpts === null || htmlPageOpts === void 0 || (_htmlPageOpts$links = htmlPageOpts.links) === null || _htmlPageOpts$links === void 0 ? void 0 : _htmlPageOpts$links.map(function (link, key) {
77
+ return /*#__PURE__*/React.createElement("link", _extends({
78
+ key: key
79
+ }, link));
80
+ }), htmlPageOpts === null || htmlPageOpts === void 0 || (_htmlPageOpts$styles = htmlPageOpts.styles) === null || _htmlPageOpts$styles === void 0 ? void 0 : _htmlPageOpts$styles.map(function (style, key) {
81
+ var _generatorStyle = generatorStyle(style),
82
+ type = _generatorStyle.type,
83
+ href = _generatorStyle.href,
84
+ content = _generatorStyle.content;
85
+ if (type === 'link') {
86
+ return /*#__PURE__*/React.createElement("link", {
87
+ key: key,
88
+ rel: "stylesheet",
89
+ href: href
90
+ });
91
+ } else if (type === 'style') {
92
+ return /*#__PURE__*/React.createElement("style", {
93
+ key: key
94
+ }, content);
95
+ }
96
+ }), htmlPageOpts === null || htmlPageOpts === void 0 || (_htmlPageOpts$headScr = htmlPageOpts.headScripts) === null || _htmlPageOpts$headScr === void 0 ? void 0 : _htmlPageOpts$headScr.map(function (script, key) {
97
+ var _normalizeScripts = normalizeScripts(script),
98
+ content = _normalizeScripts.content,
99
+ rest = _objectWithoutProperties(_normalizeScripts, _excluded);
100
+ return /*#__PURE__*/React.createElement("script", _extends({
101
+ dangerouslySetInnerHTML: {
102
+ __html: content
103
+ },
104
+ key: key,
105
+ crossOrigin: "anonymous"
106
+ }, rest));
107
+ }));
108
+ };
109
+ export function Html(_ref) {
110
+ var _htmlPageOpts$scripts;
111
+ var children = _ref.children,
112
+ loaderData = _ref.loaderData,
113
+ manifest = _ref.manifest,
114
+ htmlPageOpts = _ref.htmlPageOpts,
115
+ __INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = _ref.__INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
116
+ mountElementId = _ref.mountElementId;
117
+ // TODO: 处理 head 标签,比如 favicon.ico 的一致性
118
+ // TODO: root 支持配置
119
+ if (__INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED !== null && __INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED !== void 0 && __INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.pureHtml) {
120
+ return /*#__PURE__*/React.createElement("html", null, /*#__PURE__*/React.createElement("head", null), /*#__PURE__*/React.createElement("body", null, /*#__PURE__*/React.createElement(EnableJsScript, null), /*#__PURE__*/React.createElement("div", {
121
+ id: mountElementId
122
+ }, children), /*#__PURE__*/React.createElement(GlobalDataScript, {
123
+ manifest: manifest,
124
+ loaderData: loaderData,
125
+ htmlPageOpts: htmlPageOpts
126
+ })));
127
+ }
128
+ if (__INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED !== null && __INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED !== void 0 && __INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.pureApp) {
129
+ return /*#__PURE__*/React.createElement(React.Fragment, null, children);
130
+ }
131
+ var clientCss = typeof window === 'undefined' ? manifest === null || manifest === void 0 ? void 0 : manifest.assets['umi.css'] : window.__UMI_BUILD_ClIENT_CSS__;
132
+ return (
133
+ /*#__PURE__*/
134
+ // FIXME: Resolve the hydrate warning for suppressHydrationWarning(3)
135
+ React.createElement("html", {
136
+ suppressHydrationWarning: true,
137
+ lang: (htmlPageOpts === null || htmlPageOpts === void 0 ? void 0 : htmlPageOpts.lang) || 'en'
138
+ }, /*#__PURE__*/React.createElement("head", null, /*#__PURE__*/React.createElement("meta", {
139
+ charSet: "utf-8"
140
+ }), /*#__PURE__*/React.createElement("meta", {
141
+ name: "viewport",
142
+ content: "width=device-width, initial-scale=1"
143
+ }), clientCss && /*#__PURE__*/React.createElement("link", {
144
+ suppressHydrationWarning: true,
145
+ rel: "stylesheet",
146
+ href: clientCss
147
+ }), /*#__PURE__*/React.createElement(HydrateMetadata, {
148
+ htmlPageOpts: htmlPageOpts
149
+ })), /*#__PURE__*/React.createElement("body", null, /*#__PURE__*/React.createElement(EnableJsScript, null), /*#__PURE__*/React.createElement("div", {
150
+ id: mountElementId
151
+ }, children), /*#__PURE__*/React.createElement(GlobalDataScript, {
152
+ manifest: manifest,
153
+ loaderData: loaderData,
154
+ htmlPageOpts: htmlPageOpts
155
+ }), htmlPageOpts === null || htmlPageOpts === void 0 || (_htmlPageOpts$scripts = htmlPageOpts.scripts) === null || _htmlPageOpts$scripts === void 0 ? void 0 : _htmlPageOpts$scripts.map(function (script, key) {
156
+ var _normalizeScripts2 = normalizeScripts(script),
157
+ content = _normalizeScripts2.content,
158
+ rest = _objectWithoutProperties(_normalizeScripts2, _excluded2);
159
+ return /*#__PURE__*/React.createElement("script", _extends({
160
+ dangerouslySetInnerHTML: {
161
+ __html: content
162
+ },
163
+ key: key,
164
+ crossOrigin: "anonymous"
165
+ }, rest));
166
+ })))
167
+ );
168
+ }
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  export { createBrowserHistory, createHashHistory, createMemoryHistory, type History, } from 'history';
2
2
  export { Helmet, HelmetProvider } from 'react-helmet-async';
3
3
  export { createSearchParams, generatePath, matchPath, matchRoutes, Navigate, NavLink, Outlet, resolvePath, useLocation, useMatch, useNavigate, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes, useSearchParams, } from 'react-router-dom';
4
- export { useAppData, useClientLoaderData, useRouteProps, useSelectedRoutes, useServerLoaderData, } from './appContext';
4
+ export { useAppData, useClientLoaderData, useLoaderData, useRouteProps, useSelectedRoutes, useServerLoaderData, } from './appContext';
5
5
  export { renderClient, __getRoot } from './browser';
6
6
  export { LinkWithPrefetch as Link } from './link';
7
7
  export { useRouteData } from './routeContext';
8
+ export type { ClientLoader } from './types';
8
9
  export { __useFetcher } from './useFetcher';
9
10
  export { withRouter, type RouteComponentProps } from './withRouter';
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { createBrowserHistory, createHashHistory, createMemoryHistory } from 'history';
2
2
  export { Helmet, HelmetProvider } from 'react-helmet-async';
3
3
  export { createSearchParams, generatePath, matchPath, matchRoutes, Navigate, NavLink, Outlet, resolvePath, useLocation, useMatch, useNavigate, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes, useSearchParams } from 'react-router-dom';
4
- export { useAppData, useClientLoaderData, useRouteProps, useSelectedRoutes, useServerLoaderData } from "./appContext";
4
+ export { useAppData, useClientLoaderData, useLoaderData, useRouteProps, useSelectedRoutes, useServerLoaderData } from "./appContext";
5
5
  export { renderClient, __getRoot } from "./browser";
6
6
  export { LinkWithPrefetch as Link } from "./link";
7
7
  export { useRouteData } from "./routeContext";
package/dist/link.d.ts CHANGED
@@ -2,4 +2,4 @@ import React, { PropsWithChildren } from 'react';
2
2
  import { LinkProps } from 'react-router-dom';
3
3
  export declare function LinkWithPrefetch(props: PropsWithChildren<{
4
4
  prefetch?: boolean;
5
- } & LinkProps & React.RefAttributes<HTMLAnchorElement>>): JSX.Element | null;
5
+ } & LinkProps & React.RefAttributes<HTMLAnchorElement>>): React.JSX.Element | null;
package/dist/server.d.ts CHANGED
@@ -1,15 +1,3 @@
1
- import type { IMetadata } from '@umijs/server/dist/types';
2
- import { IRouteComponents, IRoutesById } from './types';
3
- interface IHtmlProps {
4
- routes: IRoutesById;
5
- routeComponents: IRouteComponents;
6
- pluginManager: any;
7
- location: string;
8
- loaderData: {
9
- [routeKey: string]: any;
10
- };
11
- manifest: any;
12
- metadata?: IMetadata;
13
- }
14
- export declare function getClientRootComponent(opts: IHtmlProps): Promise<JSX.Element>;
15
- export {};
1
+ import React from 'react';
2
+ import { IRootComponentOptions } from './types';
3
+ export declare function getClientRootComponent(opts: IRootComponentOptions): Promise<React.JSX.Element>;
package/dist/server.js CHANGED
@@ -5,6 +5,7 @@ import React from 'react';
5
5
  import { StaticRouter } from 'react-router-dom/server';
6
6
  import { AppContext } from "./appContext";
7
7
  import { Routes } from "./browser";
8
+ import { Html } from "./html";
8
9
  import { createClientRoutes } from "./routes";
9
10
  // Get the root React component for ReactDOMServer.renderToString
10
11
  export function getClientRootComponent(_x) {
@@ -17,11 +18,18 @@ function _getClientRootComponent() {
17
18
  while (1) switch (_context.prev = _context.next) {
18
19
  case 0:
19
20
  basename = '/';
20
- components = _objectSpread({}, opts.routeComponents);
21
+ components = _objectSpread({}, opts.routeComponents); // todo 参数对齐
21
22
  clientRoutes = createClientRoutes({
22
23
  routesById: opts.routes,
23
24
  routeComponents: components
24
25
  });
26
+ opts.pluginManager.applyPlugins({
27
+ key: 'patchClientRoutes',
28
+ type: 'event',
29
+ args: {
30
+ routes: clientRoutes
31
+ }
32
+ });
25
33
  rootContainer = /*#__PURE__*/React.createElement(StaticRouter, {
26
34
  basename: basename,
27
35
  location: opts.location
@@ -49,54 +57,11 @@ function _getClientRootComponent() {
49
57
  }
50
58
  }, rootContainer);
51
59
  return _context.abrupt("return", /*#__PURE__*/React.createElement(Html, opts, app));
52
- case 7:
60
+ case 8:
53
61
  case "end":
54
62
  return _context.stop();
55
63
  }
56
64
  }, _callee);
57
65
  }));
58
66
  return _getClientRootComponent.apply(this, arguments);
59
- }
60
- function Html(_ref) {
61
- var _metadata$keywords, _metadata$metas;
62
- var children = _ref.children,
63
- loaderData = _ref.loaderData,
64
- manifest = _ref.manifest,
65
- metadata = _ref.metadata;
66
- // TODO: 处理 head 标签,比如 favicon.ico 的一致性
67
- // TODO: root 支持配置
68
-
69
- return /*#__PURE__*/React.createElement("html", {
70
- lang: (metadata === null || metadata === void 0 ? void 0 : metadata.lang) || 'en'
71
- }, /*#__PURE__*/React.createElement("head", null, /*#__PURE__*/React.createElement("meta", {
72
- charSet: "utf-8"
73
- }), /*#__PURE__*/React.createElement("meta", {
74
- name: "viewport",
75
- content: "width=device-width, initial-scale=1"
76
- }), (metadata === null || metadata === void 0 ? void 0 : metadata.title) && /*#__PURE__*/React.createElement("title", null, metadata.title), (metadata === null || metadata === void 0 ? void 0 : metadata.description) && /*#__PURE__*/React.createElement("meta", {
77
- name: "description",
78
- content: metadata.description
79
- }), (metadata === null || metadata === void 0 || (_metadata$keywords = metadata.keywords) === null || _metadata$keywords === void 0 ? void 0 : _metadata$keywords.length) && /*#__PURE__*/React.createElement("meta", {
80
- name: "keywords",
81
- content: metadata.keywords.join(',')
82
- }), metadata === null || metadata === void 0 || (_metadata$metas = metadata.metas) === null || _metadata$metas === void 0 ? void 0 : _metadata$metas.map(function (em) {
83
- return /*#__PURE__*/React.createElement("meta", {
84
- key: em.name,
85
- name: em.name,
86
- content: em.content
87
- });
88
- }), manifest.assets['umi.css'] && /*#__PURE__*/React.createElement("link", {
89
- rel: "stylesheet",
90
- href: manifest.assets['umi.css']
91
- })), /*#__PURE__*/React.createElement("body", null, /*#__PURE__*/React.createElement("noscript", {
92
- dangerouslySetInnerHTML: {
93
- __html: "<b>Enable JavaScript to run this app.</b>"
94
- }
95
- }), /*#__PURE__*/React.createElement("div", {
96
- id: "root"
97
- }, children), /*#__PURE__*/React.createElement("script", {
98
- dangerouslySetInnerHTML: {
99
- __html: "window.__UMI_LOADER_DATA__ = ".concat(JSON.stringify(loaderData))
100
- }
101
- })));
102
67
  }
package/dist/types.d.ts CHANGED
@@ -1,7 +1,21 @@
1
1
  /// <reference types="react" />
2
+ import type { IhtmlPageOpts, ServerLoader } from '@umijs/server/dist/types';
2
3
  import type { RouteMatch, RouteObject } from 'react-router-dom';
4
+ declare global {
5
+ interface Window {
6
+ __UMI_LOADER_DATA__: any;
7
+ __UMI_METADATA_LOADER_DATA__: any;
8
+ __UMI_BUILD_ClIENT_CSS__: any;
9
+ }
10
+ }
11
+ declare type ClientLoaderFunctionArgs = {
12
+ serverLoader: ServerLoader;
13
+ };
14
+ export declare type ClientLoader = ((args: ClientLoaderFunctionArgs) => Promise<any>) & {
15
+ hydrate?: boolean;
16
+ };
3
17
  export interface IRouteSSRProps {
4
- clientLoader?: () => Promise<any>;
18
+ clientLoader?: ClientLoader;
5
19
  hasServerLoader?: boolean;
6
20
  }
7
21
  export interface IRouteConventionExportProps {
@@ -33,3 +47,38 @@ export interface IRouteComponents {
33
47
  export interface ILoaderData {
34
48
  [routeKey: string]: any;
35
49
  }
50
+ interface IHtmlHydrateOptions {
51
+ htmlPageOpts?: IhtmlPageOpts;
52
+ __INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED?: {
53
+ pureApp: boolean;
54
+ pureHtml: boolean;
55
+ };
56
+ mountElementId?: string;
57
+ }
58
+ export interface IRootComponentOptions extends IHtmlHydrateOptions {
59
+ routes: IRoutesById;
60
+ routeComponents: IRouteComponents;
61
+ pluginManager: any;
62
+ location: string;
63
+ loaderData: {
64
+ [routeKey: string]: any;
65
+ };
66
+ manifest: any;
67
+ }
68
+ export interface IHtmlProps extends IHtmlHydrateOptions {
69
+ children?: React.ReactNode;
70
+ loaderData?: {
71
+ [routeKey: string]: any;
72
+ };
73
+ manifest?: any;
74
+ }
75
+ export declare type IScript = Partial<{
76
+ async: boolean;
77
+ charset: string;
78
+ content: string;
79
+ crossOrigin: string | null;
80
+ defer: boolean;
81
+ src: string;
82
+ type: string;
83
+ }> | string;
84
+ export {};
@@ -14,4 +14,4 @@ export interface RouteComponentProps<T = ReturnType<typeof useParams>> {
14
14
  params?: T;
15
15
  navigate?: ReturnType<typeof useNavigate>;
16
16
  }
17
- export declare function withRouter<P extends RouteComponentProps<P>>(Component: React.ComponentType<P>): (props: P) => JSX.Element;
17
+ export declare function withRouter<P extends RouteComponentProps<P>>(Component: React.ComponentType<P>): (props: P) => React.JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umijs/renderer-react",
3
- "version": "4.2.15",
3
+ "version": "4.3.0",
4
4
  "description": "@umijs/renderer-react",
5
5
  "homepage": "https://github.com/umijs/umi/tree/master/packages/renderer-react#readme",
6
6
  "bugs": "https://github.com/umijs/umi/issues",
@@ -23,8 +23,8 @@
23
23
  "react-router-dom": "6.3.0"
24
24
  },
25
25
  "devDependencies": {
26
- "react": "18.1.0",
27
- "react-dom": "18.1.0"
26
+ "react": "18.3.1",
27
+ "react-dom": "18.3.1"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "react": ">=16.8",