@umijs/renderer-react 4.2.4 → 4.2.6-alpha.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
  */
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,14 @@ 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
+ ReactDOM.hydrateRoot(opts.__INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.pureApp ? rootElement : document, /*#__PURE__*/React.createElement(Html, hydtateHtmloptions, /*#__PURE__*/React.createElement(Browser, null)));
251
284
  return;
252
285
  }
253
286
  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>): JSX.Element;
package/dist/html.js ADDED
@@ -0,0 +1,170 @@
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 loaderData = props.loaderData,
21
+ htmlPageOpts = props.htmlPageOpts,
22
+ manifest = props.manifest;
23
+ return /*#__PURE__*/React.createElement("script", {
24
+ suppressHydrationWarning: true,
25
+ dangerouslySetInnerHTML: {
26
+ __html: "window.__UMI_LOADER_DATA__ = ".concat(JSON.stringify(loaderData || {}), "; window.__UMI_METADATA_LOADER_DATA__ = ").concat(JSON.stringify(htmlPageOpts || {}), "; window.__UMI_BUILD_MANIFEST_DATA__ = ").concat(JSON.stringify(manifest) || {})
27
+ }
28
+ });
29
+ };
30
+ function normalizeScripts(script) {
31
+ var extraProps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
32
+ if (typeof script === 'string') {
33
+ return isUrl(script) ? _objectSpread({
34
+ src: script
35
+ }, extraProps) : {
36
+ content: script
37
+ };
38
+ } else if (_typeof(script) === 'object') {
39
+ return _objectSpread(_objectSpread({}, script), extraProps);
40
+ } else {
41
+ throw new Error("Invalid script type: ".concat(_typeof(script)));
42
+ }
43
+ }
44
+ function generatorStyle(style) {
45
+ return isUrl(style) ? {
46
+ type: 'link',
47
+ href: style
48
+ } : {
49
+ type: 'style',
50
+ content: style
51
+ };
52
+ }
53
+ var HydrateMetadata = function HydrateMetadata(props) {
54
+ var _htmlPageOpts$favicon, _htmlPageOpts$keyword, _htmlPageOpts$metas, _htmlPageOpts$links, _htmlPageOpts$styles, _htmlPageOpts$headScr;
55
+ var htmlPageOpts = props.htmlPageOpts;
56
+ 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) {
57
+ return /*#__PURE__*/React.createElement("link", {
58
+ key: key,
59
+ rel: "shortcut icon",
60
+ href: favicon
61
+ });
62
+ }), (htmlPageOpts === null || htmlPageOpts === void 0 ? void 0 : htmlPageOpts.description) && /*#__PURE__*/React.createElement("meta", {
63
+ name: "description",
64
+ content: htmlPageOpts.description
65
+ }), (htmlPageOpts === null || htmlPageOpts === void 0 || (_htmlPageOpts$keyword = htmlPageOpts.keywords) === null || _htmlPageOpts$keyword === void 0 ? void 0 : _htmlPageOpts$keyword.length) && /*#__PURE__*/React.createElement("meta", {
66
+ name: "keywords",
67
+ content: htmlPageOpts.keywords.join(',')
68
+ }), htmlPageOpts === null || htmlPageOpts === void 0 || (_htmlPageOpts$metas = htmlPageOpts.metas) === null || _htmlPageOpts$metas === void 0 ? void 0 : _htmlPageOpts$metas.map(function (em) {
69
+ return /*#__PURE__*/React.createElement("meta", {
70
+ key: em.name,
71
+ name: em.name,
72
+ content: em.content
73
+ });
74
+ }), htmlPageOpts === null || htmlPageOpts === void 0 || (_htmlPageOpts$links = htmlPageOpts.links) === null || _htmlPageOpts$links === void 0 ? void 0 : _htmlPageOpts$links.map(function (link, key) {
75
+ return /*#__PURE__*/React.createElement("link", _extends({
76
+ key: key
77
+ }, link));
78
+ }), htmlPageOpts === null || htmlPageOpts === void 0 || (_htmlPageOpts$styles = htmlPageOpts.styles) === null || _htmlPageOpts$styles === void 0 ? void 0 : _htmlPageOpts$styles.map(function (style, key) {
79
+ var _generatorStyle = generatorStyle(style),
80
+ type = _generatorStyle.type,
81
+ href = _generatorStyle.href,
82
+ content = _generatorStyle.content;
83
+ if (type === 'link') {
84
+ return /*#__PURE__*/React.createElement("link", {
85
+ key: key,
86
+ rel: "stylesheet",
87
+ href: href
88
+ });
89
+ } else if (type === 'style') {
90
+ return /*#__PURE__*/React.createElement("style", {
91
+ key: key
92
+ }, content);
93
+ }
94
+ }), htmlPageOpts === null || htmlPageOpts === void 0 || (_htmlPageOpts$headScr = htmlPageOpts.headScripts) === null || _htmlPageOpts$headScr === void 0 ? void 0 : _htmlPageOpts$headScr.map(function (script, key) {
95
+ var _normalizeScripts = normalizeScripts(script),
96
+ content = _normalizeScripts.content,
97
+ rest = _objectWithoutProperties(_normalizeScripts, _excluded);
98
+ return /*#__PURE__*/React.createElement("script", _extends({
99
+ dangerouslySetInnerHTML: {
100
+ __html: content
101
+ },
102
+ key: key
103
+ }, rest));
104
+ }));
105
+ };
106
+ export function Html(_ref) {
107
+ var _htmlPageOpts$scripts;
108
+ var children = _ref.children,
109
+ loaderData = _ref.loaderData,
110
+ manifest = _ref.manifest,
111
+ htmlPageOpts = _ref.htmlPageOpts,
112
+ __INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = _ref.__INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
113
+ mountElementId = _ref.mountElementId;
114
+ // TODO: 处理 head 标签,比如 favicon.ico 的一致性
115
+ // TODO: root 支持配置
116
+ 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) {
117
+ 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", {
118
+ id: mountElementId
119
+ }, children), /*#__PURE__*/React.createElement(GlobalDataScript, {
120
+ manifest: manifest,
121
+ loaderData: loaderData,
122
+ htmlPageOpts: htmlPageOpts
123
+ })));
124
+ }
125
+ 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) {
126
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(EnableJsScript, null), /*#__PURE__*/React.createElement("div", {
127
+ id: mountElementId
128
+ }, children), /*#__PURE__*/React.createElement(GlobalDataScript, {
129
+ manifest: manifest,
130
+ loaderData: loaderData,
131
+ htmlPageOpts: htmlPageOpts
132
+ }));
133
+ }
134
+ var serverBuildManifest = typeof window === 'undefined' ? manifest : window.__UMI_BUILD_MANIFEST_DATA__;
135
+ return (
136
+ /*#__PURE__*/
137
+ // FIXME: Resolve the hydrate warning for suppressHydrationWarning(3)
138
+ React.createElement("html", {
139
+ suppressHydrationWarning: true,
140
+ lang: (htmlPageOpts === null || htmlPageOpts === void 0 ? void 0 : htmlPageOpts.lang) || 'en'
141
+ }, /*#__PURE__*/React.createElement("head", null, /*#__PURE__*/React.createElement("meta", {
142
+ charSet: "utf-8"
143
+ }), /*#__PURE__*/React.createElement("meta", {
144
+ name: "viewport",
145
+ content: "width=device-width, initial-scale=1"
146
+ }), (serverBuildManifest === null || serverBuildManifest === void 0 ? void 0 : serverBuildManifest.assets['umi.css']) && /*#__PURE__*/React.createElement("link", {
147
+ suppressHydrationWarning: true,
148
+ rel: "stylesheet",
149
+ href: manifest === null || manifest === void 0 ? void 0 : manifest.assets['umi.css']
150
+ }), /*#__PURE__*/React.createElement(HydrateMetadata, {
151
+ htmlPageOpts: htmlPageOpts
152
+ })), /*#__PURE__*/React.createElement("body", null, /*#__PURE__*/React.createElement(EnableJsScript, null), /*#__PURE__*/React.createElement("div", {
153
+ id: mountElementId
154
+ }, children), /*#__PURE__*/React.createElement(GlobalDataScript, {
155
+ manifest: manifest,
156
+ loaderData: loaderData,
157
+ htmlPageOpts: htmlPageOpts
158
+ }), htmlPageOpts === null || htmlPageOpts === void 0 || (_htmlPageOpts$scripts = htmlPageOpts.scripts) === null || _htmlPageOpts$scripts === void 0 ? void 0 : _htmlPageOpts$scripts.map(function (script, key) {
159
+ var _normalizeScripts2 = normalizeScripts(script),
160
+ content = _normalizeScripts2.content,
161
+ rest = _objectWithoutProperties(_normalizeScripts2, _excluded2);
162
+ return /*#__PURE__*/React.createElement("script", _extends({
163
+ dangerouslySetInnerHTML: {
164
+ __html: content
165
+ },
166
+ key: key
167
+ }, rest));
168
+ })))
169
+ );
170
+ }
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/routes.js CHANGED
@@ -4,9 +4,9 @@ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
4
4
  var _excluded = ["redirect"];
5
5
  // @ts-ignore
6
6
  import React from 'react';
7
- import { generatePath, Navigate, Outlet, useLocation, useParams } from 'react-router-dom';
8
- import { useAppData, useRouteProps } from "./appContext";
7
+ import { generatePath, Navigate, useParams, Outlet } from 'react-router-dom';
9
8
  import { RouteContext, useRouteData } from "./routeContext";
9
+ import { useAppData } from "./appContext";
10
10
  export function createClientRoutes(opts) {
11
11
  var routesById = opts.routesById,
12
12
  parentId = opts.parentId,
@@ -43,15 +43,8 @@ export function createClientRoutes(opts) {
43
43
  }
44
44
  function NavigateWithParams(props) {
45
45
  var params = useParams();
46
- var to = generatePath(props.to, params);
47
- var routeProps = useRouteProps();
48
- var location = useLocation();
49
- if (routeProps !== null && routeProps !== void 0 && routeProps.keepQuery) {
50
- var queryAndHash = location.search + location.hash;
51
- to += queryAndHash;
52
- }
53
46
  var propsWithParams = _objectSpread(_objectSpread({}, props), {}, {
54
- to: to
47
+ to: generatePath(props.to, params)
55
48
  });
56
49
  return /*#__PURE__*/React.createElement(Navigate, _extends({
57
50
  replace: true
package/dist/server.d.ts CHANGED
@@ -1,15 +1,2 @@
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 { IRootComponentOptions } from './types';
2
+ export declare function getClientRootComponent(opts: IRootComponentOptions): Promise<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_MANIFEST_DATA__: 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 {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umijs/renderer-react",
3
- "version": "4.2.4",
3
+ "version": "4.2.6-alpha.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",