@umijs/renderer-react 4.0.87 → 4.0.89

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,5 +1,5 @@
1
1
  import React from 'react';
2
- import { IClientRoute, ILoaderData, IRouteComponents, IRoutesById } from './types';
2
+ import { IClientRoute, ILoaderData, IRouteComponents, IRoutesById, ISelectedRoutes } from './types';
3
3
  interface IAppContextType {
4
4
  routes: IRoutesById;
5
5
  routeComponents: IRouteComponents;
@@ -14,10 +14,11 @@ interface IAppContextType {
14
14
  }
15
15
  export declare const AppContext: React.Context<IAppContextType>;
16
16
  export declare function useAppData(): IAppContextType;
17
- export declare function useSelectedRoutes(): import("react-router-dom").RouteMatch<string>[];
17
+ export declare function useSelectedRoutes(): ISelectedRoutes[];
18
18
  export declare function useRouteProps<T extends Record<string, any> = any>(): T;
19
- export declare function useServerLoaderData(): {
20
- data: any;
19
+ declare type ServerLoaderFunc = (...args: any[]) => Promise<any> | any;
20
+ export declare function useServerLoaderData<T extends ServerLoaderFunc = any>(): {
21
+ data: Awaited<ReturnType<T>> | undefined;
21
22
  };
22
23
  export declare function useClientLoaderData(): {
23
24
  data: any;
@@ -1,7 +1,9 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
1
2
  import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
2
3
  var _excluded = ["element"];
3
4
  import React from 'react';
4
5
  import { matchRoutes, useLocation } from 'react-router-dom';
6
+ import { fetchServerLoader } from "./dataFetcher";
5
7
  import { useRouteData } from "./routeContext";
6
8
  export var AppContext = /*#__PURE__*/React.createContext({});
7
9
  export function useAppData() {
@@ -24,10 +26,53 @@ export function useRouteProps() {
24
26
  return props;
25
27
  }
26
28
  export function useServerLoaderData() {
27
- var route = useRouteData();
28
- var appData = useAppData();
29
+ var routes = useSelectedRoutes();
30
+ var _useAppData2 = useAppData(),
31
+ serverLoaderData = _useAppData2.serverLoaderData,
32
+ basename = _useAppData2.basename;
33
+ var _React$useState = React.useState(function () {
34
+ var ret = {};
35
+ var has = false;
36
+ routes.forEach(function (route) {
37
+ // 多级路由嵌套时,需要合并多级路由 serverLoader 的数据
38
+ var routeData = serverLoaderData[route.route.id];
39
+ if (routeData) {
40
+ Object.assign(ret, routeData);
41
+ has = true;
42
+ }
43
+ });
44
+ return has ? ret : undefined;
45
+ }),
46
+ _React$useState2 = _slicedToArray(_React$useState, 2),
47
+ data = _React$useState2[0],
48
+ setData = _React$useState2[1];
49
+ React.useEffect(function () {
50
+ // @ts-ignore
51
+ if (!window.__UMI_LOADER_DATA__) {
52
+ // 支持 ssr 降级,客户端兜底加载 serverLoader 数据
53
+ Promise.all(routes.filter(function (route) {
54
+ return route.route.hasServerLoader;
55
+ }).map(function (route) {
56
+ return new Promise(function (resolve) {
57
+ fetchServerLoader({
58
+ id: route.route.id,
59
+ basename: basename,
60
+ cb: resolve
61
+ });
62
+ });
63
+ })).then(function (datas) {
64
+ if (datas.length) {
65
+ var res = {};
66
+ datas.forEach(function (data) {
67
+ Object.assign(res, data);
68
+ });
69
+ setData(res);
70
+ }
71
+ });
72
+ }
73
+ }, []);
29
74
  return {
30
- data: appData.serverLoaderData[route.route.id]
75
+ data: data
31
76
  };
32
77
  }
33
78
  export function useClientLoaderData() {
package/dist/browser.js CHANGED
@@ -6,6 +6,7 @@ import React, { useCallback, useEffect, useLayoutEffect, useState } from 'react'
6
6
  import ReactDOM from 'react-dom/client';
7
7
  import { matchRoutes, Router, useRoutes } from 'react-router-dom';
8
8
  import { AppContext, useAppData } from "./appContext";
9
+ import { fetchServerLoader } from "./dataFetcher";
9
10
  import { createClientRoutes } from "./routes";
10
11
  var root = null;
11
12
 
@@ -182,21 +183,19 @@ var getBrowser = function getBrowser(opts, routesElement) {
182
183
  // server loader
183
184
  // use ?. since routes patched with patchClientRoutes is not exists in opts.routes
184
185
  if (!isFirst && (_opts$routes$id = opts.routes[id]) !== null && _opts$routes$id !== void 0 && _opts$routes$id.hasServerLoader) {
185
- // 在有basename的情况下__serverLoader的请求路径需要加上basename
186
- fetch((basename.endsWith('/') ? basename : basename + '/') + '__serverLoader?route=' + id, {
187
- credentials: 'include'
188
- }).then(function (d) {
189
- return d.json();
190
- }).then(function (data) {
191
- // setServerLoaderData when startTransition because if ssr is enabled,
192
- // the component may being hydrated and setLoaderData will break the hydration
193
- // @ts-ignore
194
- React.startTransition(function () {
195
- setServerLoaderData(function (d) {
196
- return _objectSpread(_objectSpread({}, d), {}, _defineProperty({}, id, data));
186
+ fetchServerLoader({
187
+ id: id,
188
+ basename: basename,
189
+ cb: function cb(data) {
190
+ // setServerLoaderData when startTransition because if ssr is enabled,
191
+ // the component may being hydrated and setLoaderData will break the hydration
192
+ React.startTransition(function () {
193
+ setServerLoaderData(function (d) {
194
+ return _objectSpread(_objectSpread({}, d), {}, _defineProperty({}, id, data));
195
+ });
197
196
  });
198
- });
199
- }).catch(console.error);
197
+ }
198
+ });
200
199
  }
201
200
  // client loader
202
201
  // onPatchClientRoutes 添加的 route 在 opts.routes 里是不存在的
@@ -0,0 +1,5 @@
1
+ export declare function fetchServerLoader({ id, basename, cb, }: {
2
+ id: string;
3
+ basename?: string;
4
+ cb: (data: any) => void;
5
+ }): void;
@@ -0,0 +1,20 @@
1
+ export function fetchServerLoader(_ref) {
2
+ var id = _ref.id,
3
+ basename = _ref.basename,
4
+ cb = _ref.cb;
5
+ var query = new URLSearchParams({
6
+ route: id,
7
+ url: window.location.href
8
+ }).toString();
9
+ // 在有basename的情况下__serverLoader的请求路径需要加上basename
10
+ var url = "".concat(withEndSlash(basename), "__serverLoader?").concat(query);
11
+ fetch(url, {
12
+ credentials: 'include'
13
+ }).then(function (d) {
14
+ return d.json();
15
+ }).then(cb).catch(console.error);
16
+ }
17
+ function withEndSlash() {
18
+ var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
19
+ return str.endsWith('/') ? str : "".concat(str, "/");
20
+ }
package/dist/server.d.ts CHANGED
@@ -1,5 +1,6 @@
1
+ import type { IMetadata } from '@umijs/server/dist/types';
1
2
  import { IRouteComponents, IRoutesById } from './types';
2
- export declare function getClientRootComponent(opts: {
3
+ interface IHtmlProps {
3
4
  routes: IRoutesById;
4
5
  routeComponents: IRouteComponents;
5
6
  pluginManager: any;
@@ -8,5 +9,7 @@ export declare function getClientRootComponent(opts: {
8
9
  [routeKey: string]: any;
9
10
  };
10
11
  manifest: any;
11
- withoutHTML?: boolean;
12
- }): Promise<JSX.Element>;
12
+ metadata?: IMetadata;
13
+ }
14
+ export declare function getClientRootComponent(opts: IHtmlProps): Promise<JSX.Element>;
15
+ export {};
package/dist/server.js CHANGED
@@ -48,23 +48,8 @@ function _getClientRootComponent() {
48
48
  serverLoaderData: opts.loaderData
49
49
  }
50
50
  }, rootContainer);
51
- if (!opts.withoutHTML) {
52
- _context.next = 8;
53
- break;
54
- }
55
- return _context.abrupt("return", /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
56
- id: "root"
57
- }, app), /*#__PURE__*/React.createElement("script", {
58
- dangerouslySetInnerHTML: {
59
- __html: "window.__UMI_LOADER_DATA__ = ".concat(JSON.stringify(opts.loaderData))
60
- }
61
- })));
62
- case 8:
63
- return _context.abrupt("return", /*#__PURE__*/React.createElement(Html, {
64
- loaderData: opts.loaderData,
65
- manifest: opts.manifest
66
- }, app));
67
- case 9:
51
+ return _context.abrupt("return", /*#__PURE__*/React.createElement(Html, opts, app));
52
+ case 7:
68
53
  case "end":
69
54
  return _context.stop();
70
55
  }
@@ -73,19 +58,33 @@ function _getClientRootComponent() {
73
58
  return _getClientRootComponent.apply(this, arguments);
74
59
  }
75
60
  function Html(_ref) {
61
+ var _metadata$keywords, _metadata$metas;
76
62
  var children = _ref.children,
77
63
  loaderData = _ref.loaderData,
78
- manifest = _ref.manifest;
64
+ manifest = _ref.manifest,
65
+ metadata = _ref.metadata;
79
66
  // TODO: 处理 head 标签,比如 favicon.ico 的一致性
80
67
  // TODO: root 支持配置
81
68
 
82
69
  return /*#__PURE__*/React.createElement("html", {
83
- lang: "en"
70
+ lang: (metadata === null || metadata === void 0 ? void 0 : metadata.lang) || 'en'
84
71
  }, /*#__PURE__*/React.createElement("head", null, /*#__PURE__*/React.createElement("meta", {
85
72
  charSet: "utf-8"
86
73
  }), /*#__PURE__*/React.createElement("meta", {
87
74
  name: "viewport",
88
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 ? 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 ? 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
+ });
89
88
  }), manifest.assets['umi.css'] && /*#__PURE__*/React.createElement("link", {
90
89
  rel: "stylesheet",
91
90
  href: manifest.assets['umi.css']
package/dist/types.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  /// <reference types="react" />
2
+ import type { RouteMatch, RouteObject } from 'react-router-dom';
2
3
  export interface IRouteSSRProps {
3
4
  clientLoader?: () => Promise<any>;
4
5
  hasServerLoader?: boolean;
@@ -18,6 +19,11 @@ export interface IClientRoute extends IRoute {
18
19
  children?: IClientRoute[];
19
20
  routes?: IClientRoute[];
20
21
  }
22
+ export interface ISelectedRoute extends IRoute, RouteObject {
23
+ }
24
+ export interface ISelectedRoutes extends RouteMatch {
25
+ route: ISelectedRoute;
26
+ }
21
27
  export interface IRoutesById {
22
28
  [id: string]: IRoute;
23
29
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umijs/renderer-react",
3
- "version": "4.0.87",
3
+ "version": "4.0.89",
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",