@modern-js/runtime 1.15.0 → 1.17.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/dist/js/modern/cli/index.js +5 -12
  3. package/dist/js/modern/core/compatible.js +31 -8
  4. package/dist/js/modern/core/index.js +3 -3
  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 +32 -15
  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/node/cli/index.js +4 -12
  13. package/dist/js/node/core/compatible.js +32 -8
  14. package/dist/js/node/core/index.js +1 -1
  15. package/dist/js/node/core/loader/useLoader.js +1 -1
  16. package/dist/js/node/{core/runtime-context.js → runtime-context.js} +0 -0
  17. package/dist/js/node/ssr/index.js +35 -17
  18. package/dist/js/node/ssr/index.node.js +4 -1
  19. package/dist/js/node/ssr/react/withCallback/index.js +27 -0
  20. package/dist/js/node/ssr/serverRender/helmet.js +2 -2
  21. package/dist/js/node/ssr/serverRender/index.js +0 -2
  22. package/dist/js/treeshaking/cli/index.js +5 -11
  23. package/dist/js/treeshaking/core/compatible.js +63 -23
  24. package/dist/js/treeshaking/core/index.js +3 -3
  25. package/dist/js/treeshaking/core/loader/useLoader.js +1 -1
  26. package/dist/js/treeshaking/{core/runtime-context.js → runtime-context.js} +0 -0
  27. package/dist/js/treeshaking/ssr/index.js +42 -34
  28. package/dist/js/treeshaking/ssr/index.node.js +12 -9
  29. package/dist/js/treeshaking/ssr/react/withCallback/index.js +16 -0
  30. package/dist/js/treeshaking/ssr/serverRender/helmet.js +2 -2
  31. package/dist/js/treeshaking/ssr/serverRender/index.js +0 -1
  32. package/dist/types/common.d.ts +8 -1
  33. package/dist/types/core/app-config.d.ts +1 -3
  34. package/dist/types/core/compatible.d.ts +11 -2
  35. package/dist/types/core/index.d.ts +2 -3
  36. package/dist/types/core/loader/useLoader.d.ts +1 -0
  37. package/dist/types/core/plugin.d.ts +15 -8
  38. package/dist/types/index.d.ts +4 -8
  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 -12
  45. package/package.json +14 -11
  46. package/dist/types/core/runtime-context.d.ts +0 -13
package/CHANGELOG.md CHANGED
@@ -1,5 +1,61 @@
1
1
  # @modern-js/runtime
2
2
 
3
+ ## 1.17.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 77d3a38: feat: remove `.runtime-exports/index.js` export
8
+
9
+ feat: 移除 `.runtime-exports/index.js` 导出
10
+
11
+ - 492437f: fix: runtime type
12
+
13
+ fix: 修复 runtime 类型定义
14
+
15
+ - c3d4a6a: feat: support react 18 ssr
16
+ feat: 支持 React 18 下使用 SSR
17
+ - Updated dependencies [1b9176f]
18
+ - Updated dependencies [77d3a38]
19
+ - Updated dependencies [151329d]
20
+ - Updated dependencies [5af9472]
21
+ - Updated dependencies [6b6a534]
22
+ - Updated dependencies [6b43a2b]
23
+ - Updated dependencies [a7be124]
24
+ - Updated dependencies [31547b4]
25
+ - @modern-js/utils@1.17.0
26
+ - @modern-js/webpack@1.17.0
27
+ - @modern-js/plugin@1.17.0
28
+
29
+ ## 1.16.1
30
+
31
+ ### Patch Changes
32
+
33
+ - fix: runtime type
34
+
35
+ fix: 修复 runtime 类型定义
36
+
37
+ ## 1.16.0
38
+
39
+ ### Minor Changes
40
+
41
+ - 1100dd58c: chore: support react 18
42
+
43
+ chore: 支持 React 18
44
+
45
+ ### Patch Changes
46
+
47
+ - a480d6ad0: fix: remove helmet regexp's global tag
48
+ fix: 删除 helmet 中正则匹配的全局标记
49
+ - Updated dependencies [641592f52]
50
+ - Updated dependencies [3904b30a5]
51
+ - Updated dependencies [1100dd58c]
52
+ - Updated dependencies [e04e6e76a]
53
+ - Updated dependencies [81c66e4a4]
54
+ - Updated dependencies [2c305b6f5]
55
+ - @modern-js/utils@1.16.0
56
+ - @modern-js/webpack@1.16.0
57
+ - @modern-js/plugin@1.16.0
58
+
3
59
  ## 1.15.0
4
60
 
5
61
  ### Patch 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, 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";
@@ -8,25 +8,23 @@ export default (() => ({
8
8
  post: ['@modern-js/plugin-router', '@modern-js/plugin-ssr', '@modern-js/plugin-state', '@modern-js/plugin-design-token'],
9
9
  usePlugins: [PluginState(), PluginRouter(), PluginSSR()],
10
10
  setup: api => {
11
- let runtimeExportsUtils = {};
12
11
  return {
13
12
  config() {
14
- const dir = api.useAppContext().internalDirectory;
15
- runtimeExportsUtils = createRuntimeExportsUtils(dir, 'index');
13
+ const dir = api.useAppContext().internalDirectory || '';
14
+ process.env.IS_REACT18 = isReact18(path.join(dir, '../../')).toString();
16
15
  return {
17
16
  runtime: {},
18
17
  runtimeByEntries: {},
19
18
  source: {
20
19
  alias: {
21
- '@modern-js/runtime$': runtimeExportsUtils.getPath(),
22
-
23
20
  /**
24
21
  * twin.macro inserts styled-components into the code during the compilation process
25
22
  * But it will not be installed under the user project.
26
23
  * So need to add alias
27
24
  */
28
25
  'styled-components': require.resolve('styled-components')
29
- }
26
+ },
27
+ envVars: ['IS_REACT18']
30
28
  }
31
29
  };
32
30
  },
@@ -35,11 +33,6 @@ export default (() => ({
35
33
  return PLUGIN_SCHEMAS['@modern-js/runtime'];
36
34
  },
37
35
 
38
- addRuntimeExports() {
39
- const runtimePackage = path.resolve(__dirname, '../../../../');
40
- runtimeExportsUtils.addExport(`export * from '${runtimePackage}'`);
41
- },
42
-
43
36
  async beforeRestart() {
44
37
  cleanRequireCache([require.resolve("../state/cli"), require.resolve("../router/cli"), require.resolve("../ssr/cli")]);
45
38
  }
@@ -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, ReactDOM = defaultReactDOM) => {
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 || ReactDOM.createRoot(rootElement)).render(App);
182
+ } else {
183
+ ReactDOM.render(App, rootElement);
184
+ }
185
+ };
186
+
187
+ const ModernHydrate = (App, callback) => {
188
+ if (IS_REACT18) {
189
+ ReactDOM.hydrateRoot(rootElement, App);
190
+ } else {
191
+ ReactDOM.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 {
@@ -1,7 +1,7 @@
1
1
  export { createPlugin, createRuntime, runtime, registerInit, registerPrefetch } from "./plugin";
2
- export { defineConfig, getConfig } from "./app-config";
3
- // compatible
2
+ export { defineConfig, getConfig } from "./app-config"; // compatible
3
+
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
- 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;
28
+ // if render level not exist, use client render
29
+ 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) || RenderLevel.CLIENT_RENDER; // client render and server prefetch use same logic
26
30
 
27
- 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
+ if (renderLevel === RenderLevel.CLIENT_RENDER || renderLevel === RenderLevel.SERVER_PREFETCH) {
32
+ ModernRender( /*#__PURE__*/_jsx(App, {
32
33
  context: context
33
- }), rootElement);
34
+ }));
34
35
  } else if (renderLevel === RenderLevel.SERVER_RENDER) {
35
36
  loadableReady(() => {
36
37
  const hydrateContext = _objectSpread(_objectSpread({}, context), {}, {
37
38
  _hydration: true
38
39
  });
39
40
 
40
- ReactDOM.hydrate( /*#__PURE__*/_jsx(App, {
41
- context: hydrateContext
42
- }), rootElement, () => {
41
+ const callback = () => {
43
42
  // won't cause component re-render because context's reference identity doesn't change
44
43
  delete hydrateContext._hydration;
45
- });
44
+ }; // callback: https://github.com/reactwg/react-18/discussions/5
45
+
46
+
47
+ if (IS_REACT18) {
48
+ let SSRApp = () => /*#__PURE__*/_jsx(WithCallback, {
49
+ callback: callback,
50
+ children: /*#__PURE__*/_jsx(App, {
51
+ context: hydrateContext
52
+ })
53
+ });
54
+
55
+ SSRApp = hoistNonReactStatics(SSRApp, App);
56
+ ModernHydrate( /*#__PURE__*/_jsx(SSRApp, {}));
57
+ } else {
58
+ ModernHydrate( /*#__PURE__*/_jsx(App, {
59
+ context: hydrateContext
60
+ }), callback);
61
+ }
46
62
  });
47
63
  } else {
48
64
  // unknown renderlevel or renderlevel is server prefetch.
49
- ReactDOM.render( /*#__PURE__*/_jsx(App, {
65
+ console.warn(`unknow render level: ${renderLevel}, execute render()`);
66
+ ModernRender( /*#__PURE__*/_jsx(App, {
50
67
  context: context
51
- }), rootElement);
68
+ }));
52
69
  }
53
70
  },
54
71
 
@@ -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";
@@ -22,25 +22,23 @@ var _default = () => ({
22
22
  post: ['@modern-js/plugin-router', '@modern-js/plugin-ssr', '@modern-js/plugin-state', '@modern-js/plugin-design-token'],
23
23
  usePlugins: [(0, _cli.default)(), (0, _cli3.default)(), (0, _cli2.default)()],
24
24
  setup: api => {
25
- let runtimeExportsUtils = {};
26
25
  return {
27
26
  config() {
28
- const dir = api.useAppContext().internalDirectory;
29
- runtimeExportsUtils = (0, _utils.createRuntimeExportsUtils)(dir, 'index');
27
+ const dir = api.useAppContext().internalDirectory || '';
28
+ process.env.IS_REACT18 = (0, _utils.isReact18)(_path.default.join(dir, '../../')).toString();
30
29
  return {
31
30
  runtime: {},
32
31
  runtimeByEntries: {},
33
32
  source: {
34
33
  alias: {
35
- '@modern-js/runtime$': runtimeExportsUtils.getPath(),
36
-
37
34
  /**
38
35
  * twin.macro inserts styled-components into the code during the compilation process
39
36
  * But it will not be installed under the user project.
40
37
  * So need to add alias
41
38
  */
42
39
  'styled-components': require.resolve('styled-components')
43
- }
40
+ },
41
+ envVars: ['IS_REACT18']
44
42
  }
45
43
  };
46
44
  },
@@ -49,12 +47,6 @@ var _default = () => ({
49
47
  return _utils.PLUGIN_SCHEMAS['@modern-js/runtime'];
50
48
  },
51
49
 
52
- addRuntimeExports() {
53
- const runtimePackage = _path.default.resolve(__dirname, '../../../../');
54
-
55
- runtimeExportsUtils.addExport(`export * from '${runtimePackage}'`);
56
- },
57
-
58
50
  async beforeRestart() {
59
51
  (0, _utils.cleanRequireCache)([require.resolve("../state/cli"), require.resolve("../router/cli"), require.resolve("../ssr/cli")]);
60
52
  }
@@ -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, ReactDOM = _reactDom.default) => {
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 || ReactDOM.createRoot(rootElement)).render(App);
207
+ } else {
208
+ ReactDOM.render(App, rootElement);
209
+ }
210
+ };
211
+
212
+ const ModernHydrate = (App, callback) => {
213
+ if (IS_REACT18) {
214
+ ReactDOM.hydrateRoot(rootElement, App);
215
+ } else {
216
+ ReactDOM.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
- 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;
58
+ // if render level not exist, use client render
59
+ 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) || _type.RenderLevel.CLIENT_RENDER; // client render and server prefetch use same logic
54
60
 
55
- 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
+ if (renderLevel === _type.RenderLevel.CLIENT_RENDER || renderLevel === _type.RenderLevel.SERVER_PREFETCH) {
62
+ ModernRender( /*#__PURE__*/(0, _jsxRuntime.jsx)(App, {
61
63
  context: context
62
- }), rootElement);
64
+ }));
63
65
  } else if (renderLevel === _type.RenderLevel.SERVER_RENDER) {
64
66
  (0, _component.loadableReady)(() => {
65
67
  const hydrateContext = _objectSpread(_objectSpread({}, context), {}, {
66
68
  _hydration: true
67
69
  });
68
70
 
69
- _reactDom.default.hydrate( /*#__PURE__*/(0, _jsxRuntime.jsx)(App, {
70
- context: hydrateContext
71
- }), rootElement, () => {
71
+ const callback = () => {
72
72
  // won't cause component re-render because context's reference identity doesn't change
73
73
  delete hydrateContext._hydration;
74
- });
74
+ }; // callback: https://github.com/reactwg/react-18/discussions/5
75
+
76
+
77
+ if (IS_REACT18) {
78
+ let SSRApp = () => /*#__PURE__*/(0, _jsxRuntime.jsx)(_withCallback.WithCallback, {
79
+ callback: callback,
80
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(App, {
81
+ context: hydrateContext
82
+ })
83
+ });
84
+
85
+ SSRApp = (0, _hoistNonReactStatics.default)(SSRApp, App);
86
+ ModernHydrate( /*#__PURE__*/(0, _jsxRuntime.jsx)(SSRApp, {}));
87
+ } else {
88
+ ModernHydrate( /*#__PURE__*/(0, _jsxRuntime.jsx)(App, {
89
+ context: hydrateContext
90
+ }), callback);
91
+ }
75
92
  });
76
93
  } else {
77
94
  // unknown renderlevel or renderlevel is server prefetch.
78
- _reactDom.default.render( /*#__PURE__*/(0, _jsxRuntime.jsx)(App, {
95
+ console.warn(`unknow render level: ${renderLevel}, execute render()`);
96
+ ModernRender( /*#__PURE__*/(0, _jsxRuntime.jsx)(App, {
79
97
  context: context
80
- }), rootElement);
98
+ }));
81
99
  }
82
100
  },
83
101
 
@@ -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"));