@modern-js/runtime 1.5.0 → 1.16.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/js/modern/cli/index.js +5 -3
  3. package/dist/js/modern/core/compatible.js +31 -8
  4. package/dist/js/modern/core/index.js +1 -1
  5. package/dist/js/modern/core/loader/useLoader.js +1 -1
  6. package/dist/js/modern/{core/runtime-context.js → runtime-context.js} +0 -0
  7. package/dist/js/modern/ssr/index.js +34 -13
  8. package/dist/js/modern/ssr/index.node.js +4 -1
  9. package/dist/js/modern/ssr/react/withCallback/index.js +17 -0
  10. package/dist/js/modern/ssr/serverRender/helmet.js +2 -2
  11. package/dist/js/modern/ssr/serverRender/index.js +0 -1
  12. package/dist/js/modern/ssr/utils.js +9 -3
  13. package/dist/js/node/cli/index.js +4 -2
  14. package/dist/js/node/core/compatible.js +32 -8
  15. package/dist/js/node/core/index.js +1 -1
  16. package/dist/js/node/core/loader/useLoader.js +1 -1
  17. package/dist/js/node/{core/runtime-context.js → runtime-context.js} +0 -0
  18. package/dist/js/node/ssr/index.js +37 -15
  19. package/dist/js/node/ssr/index.node.js +4 -1
  20. package/dist/js/node/ssr/react/withCallback/index.js +27 -0
  21. package/dist/js/node/ssr/serverRender/helmet.js +2 -2
  22. package/dist/js/node/ssr/serverRender/index.js +0 -2
  23. package/dist/js/node/ssr/utils.js +9 -3
  24. package/dist/js/treeshaking/cli/index.js +5 -3
  25. package/dist/js/treeshaking/core/compatible.js +65 -23
  26. package/dist/js/treeshaking/core/index.js +1 -1
  27. package/dist/js/treeshaking/core/loader/useLoader.js +1 -1
  28. package/dist/js/treeshaking/{core/runtime-context.js → runtime-context.js} +0 -0
  29. package/dist/js/treeshaking/ssr/index.js +45 -33
  30. package/dist/js/treeshaking/ssr/index.node.js +12 -9
  31. package/dist/js/treeshaking/ssr/react/withCallback/index.js +16 -0
  32. package/dist/js/treeshaking/ssr/serverRender/helmet.js +2 -2
  33. package/dist/js/treeshaking/ssr/serverRender/index.js +0 -1
  34. package/dist/js/treeshaking/ssr/utils.js +8 -3
  35. package/dist/types/core/compatible.d.ts +6 -2
  36. package/dist/types/core/index.d.ts +2 -2
  37. package/dist/types/core/plugin.d.ts +15 -8
  38. package/dist/types/index.d.ts +2 -1
  39. package/dist/types/runtime-context.d.ts +24 -0
  40. package/dist/types/ssr/index.d.ts +0 -7
  41. package/dist/types/ssr/react/nossr/index.d.ts +1 -1
  42. package/dist/types/ssr/react/withCallback/index.d.ts +5 -0
  43. package/dist/types/ssr/serverRender/index.d.ts +0 -5
  44. package/dist/types/state/runtime/plugin.d.ts +1 -7
  45. package/package.json +13 -11
  46. package/dist/types/core/runtime-context.d.ts +0 -13
package/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # @modern-js/runtime
2
2
 
3
+ ## 1.16.1
4
+
5
+ ### Patch Changes
6
+
7
+ - fix: runtime type
8
+
9
+ fix: 修复 runtime 类型定义
10
+
11
+ ## 1.16.0
12
+
13
+ ### Minor Changes
14
+
15
+ - 1100dd58c: chore: support react 18
16
+
17
+ chore: 支持 React 18
18
+
19
+ ### Patch Changes
20
+
21
+ - a480d6ad0: fix: remove helmet regexp's global tag
22
+ fix: 删除 helmet 中正则匹配的全局标记
23
+ - Updated dependencies [641592f52]
24
+ - Updated dependencies [3904b30a5]
25
+ - Updated dependencies [1100dd58c]
26
+ - Updated dependencies [e04e6e76a]
27
+ - Updated dependencies [81c66e4a4]
28
+ - Updated dependencies [2c305b6f5]
29
+ - @modern-js/utils@1.16.0
30
+ - @modern-js/webpack@1.16.0
31
+ - @modern-js/plugin@1.16.0
32
+
33
+ ## 1.15.0
34
+
35
+ ### Patch Changes
36
+
37
+ - 335c97c: fix: fix runtime context format bug
38
+ fix: 修复 runtimeContext 数据格式化时的问题
39
+ - a04a11b: fix: 修复 SSR 物理降级时,获取不到请求上下文的问题
40
+ fix: should get ssrContext anyway if entry is ssr enable
41
+ - Updated dependencies [8658a78]
42
+ - Updated dependencies [0df4970]
43
+ - Updated dependencies [05d4a4f]
44
+ - Updated dependencies [ad05af9]
45
+ - Updated dependencies [5d53d1c]
46
+ - Updated dependencies [37cd159]
47
+ - @modern-js/utils@1.15.0
48
+ - @modern-js/webpack@1.15.0
49
+ - @modern-js/plugin@1.15.0
50
+
3
51
  ## 1.5.0
4
52
 
5
53
  ### Minor Changes
@@ -1,5 +1,5 @@
1
1
  import path from 'path';
2
- import { PLUGIN_SCHEMAS, createRuntimeExportsUtils, cleanRequireCache } from '@modern-js/utils';
2
+ import { PLUGIN_SCHEMAS, createRuntimeExportsUtils, cleanRequireCache, isReact18 } from '@modern-js/utils';
3
3
  import PluginState from "../state/cli";
4
4
  import PluginSSR from "../ssr/cli";
5
5
  import PluginRouter from "../router/cli";
@@ -11,8 +11,9 @@ export default (() => ({
11
11
  let runtimeExportsUtils = {};
12
12
  return {
13
13
  config() {
14
- const dir = api.useAppContext().internalDirectory;
14
+ const dir = api.useAppContext().internalDirectory || '';
15
15
  runtimeExportsUtils = createRuntimeExportsUtils(dir, 'index');
16
+ process.env.IS_REACT18 = isReact18(path.join(dir, '../../')).toString();
16
17
  return {
17
18
  runtime: {},
18
19
  runtimeByEntries: {},
@@ -26,7 +27,8 @@ export default (() => ({
26
27
  * So need to add alias
27
28
  */
28
29
  'styled-components': require.resolve('styled-components')
29
- }
30
+ },
31
+ envVars: ['IS_REACT18']
30
32
  }
31
33
  };
32
34
  },
@@ -11,12 +11,13 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
11
11
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
12
12
 
13
13
  import React, { useContext, useMemo } from 'react';
14
- import ReactDOM from 'react-dom';
14
+ import defaultReactDOM from 'react-dom';
15
15
  import hoistNonReactStatics from 'hoist-non-react-statics';
16
+ import { RuntimeReactContext } from "../runtime-context";
16
17
  import { runtime } from "./plugin";
17
- import { RuntimeReactContext } from "./runtime-context";
18
18
  import { createLoaderManager } from "./loader/loaderManager";
19
19
  import { jsx as _jsx } from "react/jsx-runtime";
20
+ const IS_REACT18 = process.env.IS_REACT18 === 'true';
20
21
 
21
22
  function isClientArgs(id) {
22
23
  return typeof id === 'string' || typeof HTMLElement !== 'undefined' && id instanceof HTMLElement;
@@ -105,7 +106,11 @@ export const bootstrap = async (BootApp,
105
106
  * When csr, id is root id.
106
107
  * When ssr, id is serverContext
107
108
  */
108
- id) => {
109
+ id,
110
+ /**
111
+ * root.render need use root to run function
112
+ */
113
+ root, render = defaultReactDOM.render, hydrate = defaultReactDOM.hydrate) => {
109
114
  let App = BootApp;
110
115
  let runner = runnerMap.get(App); // ensure Component used is created by `createApp`
111
116
 
@@ -169,18 +174,36 @@ id) => {
169
174
  context.initialData = initialData;
170
175
  }
171
176
 
177
+ const rootElement = typeof id !== 'string' ? id : document.getElementById(id || 'root'); // https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html
178
+
179
+ const ModernRender = App => {
180
+ if (IS_REACT18) {
181
+ root.render(App);
182
+ } else {
183
+ render(App, rootElement);
184
+ }
185
+ };
186
+
187
+ const ModernHydrate = (App, callback) => {
188
+ if (IS_REACT18) {
189
+ hydrate(rootElement, App);
190
+ } else {
191
+ hydrate(App, rootElement, callback);
192
+ }
193
+ };
194
+
172
195
  return runner.client({
173
196
  App,
174
197
  context,
175
- rootElement: typeof id !== 'string' ? id : document.getElementById(id || 'root')
198
+ ModernRender,
199
+ ModernHydrate
176
200
  }, {
177
201
  onLast: ({
178
- App,
179
- rootElement
202
+ App
180
203
  }) => {
181
- ReactDOM.render( /*#__PURE__*/React.createElement(App, {
204
+ ModernRender( /*#__PURE__*/React.createElement(App, {
182
205
  context
183
- }), rootElement);
206
+ }));
184
207
  }
185
208
  });
186
209
  } else {
@@ -2,6 +2,6 @@ export { createPlugin, createRuntime, runtime, registerInit, registerPrefetch }
2
2
  export { defineConfig, getConfig } from "./app-config";
3
3
  // compatible
4
4
  export * from "./compatible";
5
- export { RuntimeReactContext } from "./runtime-context";
5
+ export { RuntimeReactContext } from "../runtime-context";
6
6
  export * from "./loader";
7
7
  export * from '@modern-js/plugin';
@@ -6,7 +6,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
6
6
 
7
7
  import { useContext, useRef, useMemo, useState, useCallback, useEffect } from 'react';
8
8
  import invariant from 'invariant';
9
- import { RuntimeReactContext } from "../runtime-context";
9
+ import { RuntimeReactContext } from "../../runtime-context";
10
10
  import { LoaderStatus } from "./loaderManager";
11
11
 
12
12
  const useLoader = (loaderFn, options = {
@@ -4,11 +4,13 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
4
4
 
5
5
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
6
 
7
- import ReactDOM from 'react-dom';
8
7
  import { loadableReady } from '@loadable/component';
8
+ import hoistNonReactStatics from 'hoist-non-react-statics';
9
9
  import { RenderLevel } from "./serverRender/type";
10
+ import { WithCallback } from "./react/withCallback";
10
11
  import { formatClient, mockResponse } from "./utils";
11
12
  import { jsx as _jsx } from "react/jsx-runtime";
13
+ const IS_REACT18 = process.env.IS_REACT18 === 'true';
12
14
 
13
15
  const ssr = () => ({
14
16
  name: '@modern-js/plugin-ssr',
@@ -18,37 +20,52 @@ const ssr = () => ({
18
20
  client: async ({
19
21
  App,
20
22
  context,
21
- rootElement
23
+ ModernRender,
24
+ ModernHydrate
22
25
  }) => {
23
26
  var _window, _window$_SSR_DATA;
24
27
 
25
28
  const renderLevel = (_window = window) === null || _window === void 0 ? void 0 : (_window$_SSR_DATA = _window._SSR_DATA) === null || _window$_SSR_DATA === void 0 ? void 0 : _window$_SSR_DATA.renderLevel;
26
29
 
27
30
  if (renderLevel === RenderLevel.CLIENT_RENDER) {
28
- var _prefetch, _ref;
29
-
30
- await (App === null || App === void 0 ? void 0 : (_prefetch = (_ref = App).prefetch) === null || _prefetch === void 0 ? void 0 : _prefetch.call(_ref, context));
31
- ReactDOM.render( /*#__PURE__*/_jsx(App, {
31
+ // prefetch block render while csr
32
+ // await (App as any)?.prefetch?.(context);
33
+ ModernRender( /*#__PURE__*/_jsx(App, {
32
34
  context: context
33
- }), rootElement);
35
+ }));
34
36
  } else if (renderLevel === RenderLevel.SERVER_RENDER) {
35
37
  loadableReady(() => {
36
38
  const hydrateContext = _objectSpread(_objectSpread({}, context), {}, {
37
39
  _hydration: true
38
40
  });
39
41
 
40
- ReactDOM.hydrate( /*#__PURE__*/_jsx(App, {
41
- context: hydrateContext
42
- }), rootElement, () => {
42
+ const callback = () => {
43
43
  // won't cause component re-render because context's reference identity doesn't change
44
44
  delete hydrateContext._hydration;
45
- });
45
+ }; // callback: https://github.com/reactwg/react-18/discussions/5
46
+
47
+
48
+ if (IS_REACT18) {
49
+ let SSRApp = () => /*#__PURE__*/_jsx(WithCallback, {
50
+ callback: callback,
51
+ children: /*#__PURE__*/_jsx(App, {
52
+ context: hydrateContext
53
+ })
54
+ });
55
+
56
+ SSRApp = hoistNonReactStatics(SSRApp, App);
57
+ ModernHydrate( /*#__PURE__*/_jsx(SSRApp, {}));
58
+ } else {
59
+ ModernHydrate( /*#__PURE__*/_jsx(App, {
60
+ context: hydrateContext
61
+ }), callback);
62
+ }
46
63
  });
47
64
  } else {
48
65
  // unknown renderlevel or renderlevel is server prefetch.
49
- ReactDOM.render( /*#__PURE__*/_jsx(App, {
66
+ ModernHydrate( /*#__PURE__*/_jsx(App, {
50
67
  context: context
51
- }), rootElement);
68
+ }));
52
69
  }
53
70
  },
54
71
 
@@ -60,6 +77,10 @@ const ssr = () => ({
60
77
  const request = (_window2 = window) === null || _window2 === void 0 ? void 0 : (_window2$_SSR_DATA = _window2._SSR_DATA) === null || _window2$_SSR_DATA === void 0 ? void 0 : (_window2$_SSR_DATA$co = _window2$_SSR_DATA.context) === null || _window2$_SSR_DATA$co === void 0 ? void 0 : _window2$_SSR_DATA$co.request;
61
78
 
62
79
  if (!request) {
80
+ context.ssrContext = _objectSpread(_objectSpread({}, context.ssrContext), {}, {
81
+ response: mockResp,
82
+ request: formatClient({})
83
+ });
63
84
  return next({
64
85
  context
65
86
  });
@@ -28,7 +28,9 @@ const plugin = () => ({
28
28
  }
29
29
 
30
30
  if (!isBrowser()) {
31
- const html = await require("./serverRender").render(context, (context === null || context === void 0 ? void 0 : context.ssrContext.distDir) || path.join(process.cwd(), 'dist'), App);
31
+ var _context$ssrContext;
32
+
33
+ const html = await require("./serverRender").render(context, (context === null || context === void 0 ? void 0 : (_context$ssrContext = context.ssrContext) === null || _context$ssrContext === void 0 ? void 0 : _context$ssrContext.distDir) || path.join(process.cwd(), 'dist'), App);
32
34
  return html;
33
35
  }
34
36
 
@@ -51,6 +53,7 @@ const plugin = () => ({
51
53
  context,
52
54
  pickedContext
53
55
  }, next) => {
56
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
54
57
  const {
55
58
  request,
56
59
  response
@@ -0,0 +1,17 @@
1
+ // See https://github.com/reactwg/react-18/discussions/5#discussioncomment-2276079
2
+ import { useRef, useLayoutEffect } from 'react';
3
+ export const WithCallback = ({
4
+ callback,
5
+ children
6
+ }) => {
7
+ const once = useRef(false);
8
+ useLayoutEffect(() => {
9
+ if (once.current) {
10
+ return;
11
+ }
12
+
13
+ once.current = true;
14
+ callback();
15
+ }, [callback]);
16
+ return children;
17
+ };
@@ -2,8 +2,8 @@
2
2
  const RE_HTML_ATTR = /<html[^>]*>/;
3
3
  const RE_BODY_ATTR = /<body[^>]*>/;
4
4
  const RE_LAST_IN_HEAD = /<\/head>/;
5
- const RE_TITLE = /<title[^>]*>([\s\S\n\r]*?)<\/title>/g;
6
- const TEST_TITLE_CONTENT = /(?<=<title[^>]*>)([\s\S\n\r]*?)([.|\S])([\s\S\n\r]*?)(?=<\/title>)/g; // 通过 react-helmet 修改模板
5
+ const RE_TITLE = /<title[^>]*>([\s\S\n\r]*?)<\/title>/;
6
+ const TEST_TITLE_CONTENT = /(?<=<title[^>]*>)([\s\S\n\r]*?)([.|\S])([\s\S\n\r]*?)(?=<\/title>)/; // 通过 react-helmet 修改模板
7
7
 
8
8
  export default function helmet(content, helmetData) {
9
9
  let result = content;
@@ -1,5 +1,4 @@
1
1
  import { run } from '@modern-js/utils/ssr';
2
- import { RuntimeContext } from "../../core";
3
2
  import { PreRender } from "../react/prerender";
4
3
  import SSREntry from "./entry";
5
4
  import { time } from "./measure";
@@ -19,19 +19,25 @@ export const formatServer = request => {
19
19
 
20
20
  const getQuery = () => window.location.search.substring(1).split('&').reduce((res, item) => {
21
21
  const [key, value] = item.split('=');
22
- res[key] = value;
22
+
23
+ if (key) {
24
+ res[key] = value;
25
+ }
26
+
23
27
  return res;
24
28
  }, {});
25
29
 
26
30
  export const formatClient = request => {
31
+ var _request$headers, _request$headers2;
32
+
27
33
  return {
28
34
  params: request.params || {},
29
35
  host: request.host || location.host,
30
36
  pathname: request.pathname || location.pathname,
31
37
  headers: request.headers || {},
32
38
  cookieMap: request.cookieMap || {},
33
- cookie: request.headers.cookie || document.cookie,
34
- userAgent: request.headers['user-agent'] || navigator.userAgent,
39
+ cookie: ((_request$headers = request.headers) === null || _request$headers === void 0 ? void 0 : _request$headers.cookie) || document.cookie,
40
+ userAgent: ((_request$headers2 = request.headers) === null || _request$headers2 === void 0 ? void 0 : _request$headers2['user-agent']) || navigator.userAgent,
35
41
  referer: request.referer || document.referrer,
36
42
  query: request.query || getQuery(),
37
43
  url: location.href
@@ -25,8 +25,9 @@ var _default = () => ({
25
25
  let runtimeExportsUtils = {};
26
26
  return {
27
27
  config() {
28
- const dir = api.useAppContext().internalDirectory;
28
+ const dir = api.useAppContext().internalDirectory || '';
29
29
  runtimeExportsUtils = (0, _utils.createRuntimeExportsUtils)(dir, 'index');
30
+ process.env.IS_REACT18 = (0, _utils.isReact18)(_path.default.join(dir, '../../')).toString();
30
31
  return {
31
32
  runtime: {},
32
33
  runtimeByEntries: {},
@@ -40,7 +41,8 @@ var _default = () => ({
40
41
  * So need to add alias
41
42
  */
42
43
  'styled-components': require.resolve('styled-components')
43
- }
44
+ },
45
+ envVars: ['IS_REACT18']
44
46
  }
45
47
  };
46
48
  },
@@ -11,9 +11,9 @@ var _reactDom = _interopRequireDefault(require("react-dom"));
11
11
 
12
12
  var _hoistNonReactStatics = _interopRequireDefault(require("hoist-non-react-statics"));
13
13
 
14
- var _plugin = require("./plugin");
14
+ var _runtimeContext = require("../runtime-context");
15
15
 
16
- var _runtimeContext = require("./runtime-context");
16
+ var _plugin = require("./plugin");
17
17
 
18
18
  var _loaderManager = require("./loader/loaderManager");
19
19
 
@@ -37,6 +37,8 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
37
37
 
38
38
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
39
39
 
40
+ const IS_REACT18 = process.env.IS_REACT18 === 'true';
41
+
40
42
  function isClientArgs(id) {
41
43
  return typeof id === 'string' || typeof HTMLElement !== 'undefined' && id instanceof HTMLElement;
42
44
  }
@@ -129,7 +131,11 @@ const bootstrap = async (BootApp,
129
131
  * When csr, id is root id.
130
132
  * When ssr, id is serverContext
131
133
  */
132
- id) => {
134
+ id,
135
+ /**
136
+ * root.render need use root to run function
137
+ */
138
+ root, render = _reactDom.default.render, hydrate = _reactDom.default.hydrate) => {
133
139
  let App = BootApp;
134
140
  let runner = runnerMap.get(App); // ensure Component used is created by `createApp`
135
141
 
@@ -193,18 +199,36 @@ id) => {
193
199
  context.initialData = initialData;
194
200
  }
195
201
 
202
+ const rootElement = typeof id !== 'string' ? id : document.getElementById(id || 'root'); // https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html
203
+
204
+ const ModernRender = App => {
205
+ if (IS_REACT18) {
206
+ root.render(App);
207
+ } else {
208
+ render(App, rootElement);
209
+ }
210
+ };
211
+
212
+ const ModernHydrate = (App, callback) => {
213
+ if (IS_REACT18) {
214
+ hydrate(rootElement, App);
215
+ } else {
216
+ hydrate(App, rootElement, callback);
217
+ }
218
+ };
219
+
196
220
  return runner.client({
197
221
  App,
198
222
  context,
199
- rootElement: typeof id !== 'string' ? id : document.getElementById(id || 'root')
223
+ ModernRender,
224
+ ModernHydrate
200
225
  }, {
201
226
  onLast: ({
202
- App,
203
- rootElement
227
+ App
204
228
  }) => {
205
- _reactDom.default.render( /*#__PURE__*/_react.default.createElement(App, {
229
+ ModernRender( /*#__PURE__*/_react.default.createElement(App, {
206
230
  context
207
- }), rootElement);
231
+ }));
208
232
  }
209
233
  });
210
234
  } else {
@@ -80,7 +80,7 @@ Object.keys(_compatible).forEach(function (key) {
80
80
  });
81
81
  });
82
82
 
83
- var _runtimeContext = require("./runtime-context");
83
+ var _runtimeContext = require("../runtime-context");
84
84
 
85
85
  var _loader = require("./loader");
86
86
 
@@ -9,7 +9,7 @@ var _react = require("react");
9
9
 
10
10
  var _invariant = _interopRequireDefault(require("invariant"));
11
11
 
12
- var _runtimeContext = require("../runtime-context");
12
+ var _runtimeContext = require("../../runtime-context");
13
13
 
14
14
  var _loaderManager = require("./loaderManager");
15
15
 
@@ -6,12 +6,14 @@ Object.defineProperty(exports, "__esModule", {
6
6
  var _exportNames = {};
7
7
  exports.default = void 0;
8
8
 
9
- var _reactDom = _interopRequireDefault(require("react-dom"));
10
-
11
9
  var _component = require("@loadable/component");
12
10
 
11
+ var _hoistNonReactStatics = _interopRequireDefault(require("hoist-non-react-statics"));
12
+
13
13
  var _type = require("./serverRender/type");
14
14
 
15
+ var _withCallback = require("./react/withCallback");
16
+
15
17
  var _utils = require("./utils");
16
18
 
17
19
  var _jsxRuntime = require("react/jsx-runtime");
@@ -38,6 +40,8 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
38
40
 
39
41
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
40
42
 
43
+ const IS_REACT18 = process.env.IS_REACT18 === 'true';
44
+
41
45
  const ssr = () => ({
42
46
  name: '@modern-js/plugin-ssr',
43
47
  setup: () => {
@@ -46,38 +50,52 @@ const ssr = () => ({
46
50
  client: async ({
47
51
  App,
48
52
  context,
49
- rootElement
53
+ ModernRender,
54
+ ModernHydrate
50
55
  }) => {
51
56
  var _window, _window$_SSR_DATA;
52
57
 
53
58
  const renderLevel = (_window = window) === null || _window === void 0 ? void 0 : (_window$_SSR_DATA = _window._SSR_DATA) === null || _window$_SSR_DATA === void 0 ? void 0 : _window$_SSR_DATA.renderLevel;
54
59
 
55
60
  if (renderLevel === _type.RenderLevel.CLIENT_RENDER) {
56
- var _prefetch, _ref;
57
-
58
- await (App === null || App === void 0 ? void 0 : (_prefetch = (_ref = App).prefetch) === null || _prefetch === void 0 ? void 0 : _prefetch.call(_ref, context));
59
-
60
- _reactDom.default.render( /*#__PURE__*/(0, _jsxRuntime.jsx)(App, {
61
+ // prefetch block render while csr
62
+ // await (App as any)?.prefetch?.(context);
63
+ ModernRender( /*#__PURE__*/(0, _jsxRuntime.jsx)(App, {
61
64
  context: context
62
- }), rootElement);
65
+ }));
63
66
  } else if (renderLevel === _type.RenderLevel.SERVER_RENDER) {
64
67
  (0, _component.loadableReady)(() => {
65
68
  const hydrateContext = _objectSpread(_objectSpread({}, context), {}, {
66
69
  _hydration: true
67
70
  });
68
71
 
69
- _reactDom.default.hydrate( /*#__PURE__*/(0, _jsxRuntime.jsx)(App, {
70
- context: hydrateContext
71
- }), rootElement, () => {
72
+ const callback = () => {
72
73
  // won't cause component re-render because context's reference identity doesn't change
73
74
  delete hydrateContext._hydration;
74
- });
75
+ }; // callback: https://github.com/reactwg/react-18/discussions/5
76
+
77
+
78
+ if (IS_REACT18) {
79
+ let SSRApp = () => /*#__PURE__*/(0, _jsxRuntime.jsx)(_withCallback.WithCallback, {
80
+ callback: callback,
81
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(App, {
82
+ context: hydrateContext
83
+ })
84
+ });
85
+
86
+ SSRApp = (0, _hoistNonReactStatics.default)(SSRApp, App);
87
+ ModernHydrate( /*#__PURE__*/(0, _jsxRuntime.jsx)(SSRApp, {}));
88
+ } else {
89
+ ModernHydrate( /*#__PURE__*/(0, _jsxRuntime.jsx)(App, {
90
+ context: hydrateContext
91
+ }), callback);
92
+ }
75
93
  });
76
94
  } else {
77
95
  // unknown renderlevel or renderlevel is server prefetch.
78
- _reactDom.default.render( /*#__PURE__*/(0, _jsxRuntime.jsx)(App, {
96
+ ModernHydrate( /*#__PURE__*/(0, _jsxRuntime.jsx)(App, {
79
97
  context: context
80
- }), rootElement);
98
+ }));
81
99
  }
82
100
  },
83
101
 
@@ -89,6 +107,10 @@ const ssr = () => ({
89
107
  const request = (_window2 = window) === null || _window2 === void 0 ? void 0 : (_window2$_SSR_DATA = _window2._SSR_DATA) === null || _window2$_SSR_DATA === void 0 ? void 0 : (_window2$_SSR_DATA$co = _window2$_SSR_DATA.context) === null || _window2$_SSR_DATA$co === void 0 ? void 0 : _window2$_SSR_DATA$co.request;
90
108
 
91
109
  if (!request) {
110
+ context.ssrContext = _objectSpread(_objectSpread({}, context.ssrContext), {}, {
111
+ response: mockResp,
112
+ request: (0, _utils.formatClient)({})
113
+ });
92
114
  return next({
93
115
  context
94
116
  });
@@ -54,7 +54,9 @@ const plugin = () => ({
54
54
  }
55
55
 
56
56
  if (!(0, _common.isBrowser)()) {
57
- const html = await require("./serverRender").render(context, (context === null || context === void 0 ? void 0 : context.ssrContext.distDir) || _path.default.join(process.cwd(), 'dist'), App);
57
+ var _context$ssrContext;
58
+
59
+ const html = await require("./serverRender").render(context, (context === null || context === void 0 ? void 0 : (_context$ssrContext = context.ssrContext) === null || _context$ssrContext === void 0 ? void 0 : _context$ssrContext.distDir) || _path.default.join(process.cwd(), 'dist'), App);
58
60
  return html;
59
61
  }
60
62
 
@@ -77,6 +79,7 @@ const plugin = () => ({
77
79
  context,
78
80
  pickedContext
79
81
  }, next) => {
82
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
80
83
  const {
81
84
  request,
82
85
  response
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.WithCallback = void 0;
7
+
8
+ var _react = require("react");
9
+
10
+ // See https://github.com/reactwg/react-18/discussions/5#discussioncomment-2276079
11
+ const WithCallback = ({
12
+ callback,
13
+ children
14
+ }) => {
15
+ const once = (0, _react.useRef)(false);
16
+ (0, _react.useLayoutEffect)(() => {
17
+ if (once.current) {
18
+ return;
19
+ }
20
+
21
+ once.current = true;
22
+ callback();
23
+ }, [callback]);
24
+ return children;
25
+ };
26
+
27
+ exports.WithCallback = WithCallback;
@@ -8,8 +8,8 @@ exports.default = helmet;
8
8
  const RE_HTML_ATTR = /<html[^>]*>/;
9
9
  const RE_BODY_ATTR = /<body[^>]*>/;
10
10
  const RE_LAST_IN_HEAD = /<\/head>/;
11
- const RE_TITLE = /<title[^>]*>([\s\S\n\r]*?)<\/title>/g;
12
- const TEST_TITLE_CONTENT = /(?<=<title[^>]*>)([\s\S\n\r]*?)([.|\S])([\s\S\n\r]*?)(?=<\/title>)/g; // 通过 react-helmet 修改模板
11
+ const RE_TITLE = /<title[^>]*>([\s\S\n\r]*?)<\/title>/;
12
+ const TEST_TITLE_CONTENT = /(?<=<title[^>]*>)([\s\S\n\r]*?)([.|\S])([\s\S\n\r]*?)(?=<\/title>)/; // 通过 react-helmet 修改模板
13
13
 
14
14
  function helmet(content, helmetData) {
15
15
  let result = content;
@@ -7,8 +7,6 @@ exports.render = void 0;
7
7
 
8
8
  var _ssr = require("@modern-js/utils/ssr");
9
9
 
10
- var _core = require("../../core");
11
-
12
10
  var _prerender = require("../react/prerender");
13
11
 
14
12
  var _entry = _interopRequireDefault(require("./entry"));