@modern-js/runtime 1.21.3 → 2.0.0-beta.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 (148) hide show
  1. package/CHANGELOG.md +48 -4
  2. package/dist/js/modern/cli/index.js +1 -1
  3. package/dist/js/modern/core/index.js +1 -1
  4. package/dist/js/modern/index.js +1 -0
  5. package/dist/js/modern/router/cli/index.js +24 -8
  6. package/dist/js/modern/router/runtime/index.js +1 -1
  7. package/dist/js/modern/router/runtime/plugin.js +26 -44
  8. package/dist/js/modern/router/runtime/plugin.node.js +143 -0
  9. package/dist/js/modern/router/runtime/types.js +1 -0
  10. package/dist/js/modern/router/runtime/utils.js +97 -37
  11. package/dist/js/modern/router/runtime/withRouter.js +22 -0
  12. package/dist/js/modern/runtime-context.js +2 -1
  13. package/dist/js/modern/ssr/cli/index.js +44 -5
  14. package/dist/js/modern/ssr/index.js +67 -43
  15. package/dist/js/modern/ssr/index.node.js +6 -2
  16. package/dist/js/modern/ssr/serverRender/index.js +12 -26
  17. package/dist/js/modern/ssr/serverRender/renderToStream/buildTemplate.after.js +38 -0
  18. package/dist/js/modern/ssr/serverRender/renderToStream/buildTemplate.share.js +5 -0
  19. package/dist/js/modern/ssr/serverRender/renderToStream/bulidTemplate.before.js +24 -0
  20. package/dist/js/modern/ssr/serverRender/renderToStream/index.js +73 -0
  21. package/dist/js/modern/ssr/serverRender/renderToStream/loadable.js +26 -0
  22. package/dist/js/modern/ssr/serverRender/renderToStream/renderToPipe.js +61 -0
  23. package/dist/js/modern/ssr/serverRender/renderToStream/styledComponent.js +11 -0
  24. package/dist/js/modern/ssr/serverRender/renderToStream/template.js +22 -0
  25. package/dist/js/modern/ssr/serverRender/renderToStream/type.js +0 -0
  26. package/dist/js/modern/ssr/serverRender/{entry.js → renderToString/entry.js} +4 -6
  27. package/dist/js/modern/ssr/serverRender/renderToString/index.js +31 -0
  28. package/dist/js/modern/ssr/serverRender/{loadable.js → renderToString/loadable.js} +5 -13
  29. package/dist/js/modern/ssr/serverRender/{reduce.js → renderToString/reduce.js} +0 -0
  30. package/dist/js/modern/ssr/serverRender/{styledComponent.js → renderToString/styledComponent.js} +0 -0
  31. package/dist/js/modern/ssr/serverRender/{template.js → renderToString/template.js} +0 -0
  32. package/dist/js/modern/ssr/serverRender/{type.js → renderToString/type.js} +0 -1
  33. package/dist/js/modern/ssr/serverRender/types.js +2 -0
  34. package/dist/js/modern/ssr/serverRender/utils.js +24 -0
  35. package/dist/js/modern/ssr/utils.js +9 -3
  36. package/dist/js/node/cli/index.js +1 -1
  37. package/dist/js/node/core/index.js +8 -1
  38. package/dist/js/node/index.js +8 -0
  39. package/dist/js/node/router/cli/index.js +24 -8
  40. package/dist/js/node/router/runtime/index.js +4 -4
  41. package/dist/js/node/router/runtime/plugin.js +24 -49
  42. package/dist/js/node/router/runtime/plugin.node.js +169 -0
  43. package/dist/js/node/router/runtime/types.js +5 -0
  44. package/dist/js/node/router/runtime/utils.js +97 -35
  45. package/dist/js/node/router/runtime/withRouter.js +35 -0
  46. package/dist/js/node/runtime-context.js +4 -2
  47. package/dist/js/node/ssr/cli/index.js +43 -5
  48. package/dist/js/node/ssr/index.js +66 -43
  49. package/dist/js/node/ssr/index.node.js +7 -3
  50. package/dist/js/node/ssr/serverRender/index.js +13 -35
  51. package/dist/js/node/ssr/serverRender/renderToStream/buildTemplate.after.js +49 -0
  52. package/dist/js/node/ssr/serverRender/renderToStream/buildTemplate.share.js +14 -0
  53. package/dist/js/node/ssr/serverRender/renderToStream/bulidTemplate.before.js +37 -0
  54. package/dist/js/node/ssr/serverRender/renderToStream/index.js +90 -0
  55. package/dist/js/node/ssr/serverRender/renderToStream/loadable.js +34 -0
  56. package/dist/js/node/ssr/serverRender/renderToStream/renderToPipe.js +70 -0
  57. package/dist/js/node/ssr/serverRender/renderToStream/styledComponent.js +19 -0
  58. package/dist/js/node/ssr/serverRender/renderToStream/template.js +32 -0
  59. package/dist/js/node/ssr/serverRender/renderToStream/type.js +0 -0
  60. package/dist/js/node/ssr/serverRender/{entry.js → renderToString/entry.js} +13 -15
  61. package/dist/js/node/ssr/serverRender/renderToString/index.js +47 -0
  62. package/dist/js/node/ssr/serverRender/{loadable.js → renderToString/loadable.js} +7 -14
  63. package/dist/js/node/ssr/serverRender/{reduce.js → renderToString/reduce.js} +0 -0
  64. package/dist/js/node/ssr/serverRender/{styledComponent.js → renderToString/styledComponent.js} +0 -0
  65. package/dist/js/node/ssr/serverRender/{template.js → renderToString/template.js} +0 -0
  66. package/dist/js/node/ssr/serverRender/{type.js → renderToString/type.js} +0 -1
  67. package/dist/js/node/ssr/serverRender/types.js +13 -0
  68. package/dist/js/node/ssr/serverRender/utils.js +34 -0
  69. package/dist/js/node/ssr/utils.js +13 -4
  70. package/dist/js/treeshaking/cli/index.js +1 -1
  71. package/dist/js/treeshaking/core/index.js +1 -1
  72. package/dist/js/treeshaking/index.js +1 -0
  73. package/dist/js/treeshaking/router/cli/index.js +24 -8
  74. package/dist/js/treeshaking/router/runtime/index.js +1 -1
  75. package/dist/js/treeshaking/router/runtime/plugin.js +25 -43
  76. package/dist/js/treeshaking/router/runtime/plugin.node.js +174 -0
  77. package/dist/js/treeshaking/router/runtime/types.js +1 -0
  78. package/dist/js/treeshaking/router/runtime/utils.js +100 -36
  79. package/dist/js/treeshaking/router/runtime/withRouter.js +17 -0
  80. package/dist/js/treeshaking/runtime-context.js +2 -1
  81. package/dist/js/treeshaking/ssr/cli/index.js +47 -5
  82. package/dist/js/treeshaking/ssr/index.js +74 -45
  83. package/dist/js/treeshaking/ssr/index.node.js +6 -2
  84. package/dist/js/treeshaking/ssr/serverRender/index.js +41 -55
  85. package/dist/js/treeshaking/ssr/serverRender/renderToStream/buildTemplate.after.js +33 -0
  86. package/dist/js/treeshaking/ssr/serverRender/renderToStream/buildTemplate.share.js +7 -0
  87. package/dist/js/treeshaking/ssr/serverRender/renderToStream/bulidTemplate.before.js +29 -0
  88. package/dist/js/treeshaking/ssr/serverRender/renderToStream/index.js +120 -0
  89. package/dist/js/treeshaking/ssr/serverRender/renderToStream/loadable.js +24 -0
  90. package/dist/js/treeshaking/ssr/serverRender/renderToStream/renderToPipe.js +57 -0
  91. package/dist/js/treeshaking/ssr/serverRender/renderToStream/styledComponent.js +10 -0
  92. package/dist/js/treeshaking/ssr/serverRender/renderToStream/template.js +29 -0
  93. package/dist/js/treeshaking/ssr/serverRender/renderToStream/type.js +0 -0
  94. package/dist/js/treeshaking/ssr/serverRender/{entry.js → renderToString/entry.js} +3 -3
  95. package/dist/js/treeshaking/ssr/serverRender/renderToString/index.js +48 -0
  96. package/dist/js/treeshaking/ssr/serverRender/{loadable.js → renderToString/loadable.js} +5 -17
  97. package/dist/js/treeshaking/ssr/serverRender/{reduce.js → renderToString/reduce.js} +0 -0
  98. package/dist/js/treeshaking/ssr/serverRender/{styledComponent.js → renderToString/styledComponent.js} +0 -0
  99. package/dist/js/treeshaking/ssr/serverRender/{template.js → renderToString/template.js} +0 -0
  100. package/dist/js/treeshaking/ssr/serverRender/{type.js → renderToString/type.js} +0 -1
  101. package/dist/js/treeshaking/ssr/serverRender/types.js +2 -0
  102. package/dist/js/treeshaking/ssr/serverRender/{measure.js → utils.js} +16 -0
  103. package/dist/js/treeshaking/ssr/utils.js +15 -3
  104. package/dist/types/common.d.ts +0 -2
  105. package/dist/types/core/index.d.ts +1 -1
  106. package/dist/types/core/plugin.d.ts +1 -1
  107. package/dist/types/exports/server.d.ts +21 -1
  108. package/dist/types/index.d.ts +1 -0
  109. package/dist/types/router/runtime/DefaultNotFound.d.ts +1 -0
  110. package/dist/types/router/runtime/index.d.ts +3 -3
  111. package/dist/types/router/runtime/plugin.d.ts +2 -45
  112. package/dist/types/router/runtime/plugin.node.d.ts +8 -0
  113. package/dist/types/router/runtime/types.d.ts +38 -0
  114. package/dist/types/router/runtime/utils.d.ts +5 -2
  115. package/dist/types/router/runtime/withRouter.d.ts +8 -0
  116. package/dist/types/runtime-context.d.ts +2 -1
  117. package/dist/types/ssr/index.d.ts +2 -2
  118. package/dist/types/ssr/index.node.d.ts +1 -1
  119. package/dist/types/ssr/react/nossr/index.d.ts +3 -1
  120. package/dist/types/ssr/serverRender/index.d.ts +2 -3
  121. package/dist/types/ssr/serverRender/renderToStream/buildTemplate.after.d.ts +6 -0
  122. package/dist/types/ssr/serverRender/renderToStream/buildTemplate.share.d.ts +3 -0
  123. package/dist/types/ssr/serverRender/renderToStream/bulidTemplate.before.d.ts +1 -0
  124. package/dist/types/ssr/serverRender/renderToStream/index.d.ts +6 -0
  125. package/dist/types/ssr/serverRender/renderToStream/loadable.d.ts +16 -0
  126. package/dist/types/ssr/serverRender/renderToStream/renderToPipe.d.ts +8 -0
  127. package/dist/types/ssr/serverRender/renderToStream/styledComponent.d.ts +12 -0
  128. package/dist/types/ssr/serverRender/renderToStream/template.d.ts +3 -0
  129. package/dist/types/ssr/serverRender/renderToStream/type.d.ts +4 -0
  130. package/dist/types/ssr/serverRender/{entry.d.ts → renderToString/entry.d.ts} +2 -2
  131. package/dist/types/ssr/serverRender/renderToString/index.d.ts +6 -0
  132. package/dist/types/ssr/serverRender/{loadable.d.ts → renderToString/loadable.d.ts} +0 -0
  133. package/dist/types/ssr/serverRender/{reduce.d.ts → renderToString/reduce.d.ts} +0 -0
  134. package/dist/types/ssr/serverRender/{styledComponent.d.ts → renderToString/styledComponent.d.ts} +0 -0
  135. package/dist/types/ssr/serverRender/{template.d.ts → renderToString/template.d.ts} +0 -0
  136. package/dist/types/ssr/serverRender/{type.d.ts → renderToString/type.d.ts} +1 -8
  137. package/dist/types/ssr/serverRender/types.d.ts +18 -0
  138. package/dist/types/ssr/serverRender/utils.d.ts +3 -0
  139. package/dist/types/ssr/utils.d.ts +4 -2
  140. package/dist/types/state/runtime/plugin.d.ts +1 -1
  141. package/package.json +57 -73
  142. package/types/index.d.ts +13 -0
  143. package/types/router.d.ts +14 -0
  144. package/dist/js/modern/ssr/serverRender/measure.js +0 -11
  145. package/dist/js/node/ssr/serverRender/measure.js +0 -20
  146. package/dist/types/ssr/serverRender/measure.d.ts +0 -1
  147. package/lib/types.d.ts +0 -10
  148. package/type.d.ts +0 -5
@@ -1,5 +1,28 @@
1
1
  import { getEntryOptions, SERVER_RENDER_FUNCTION_NAME, LOADABLE_STATS_FILE, isUseSSRBundle, createRuntimeExportsUtils, isSingleEntry } from '@modern-js/utils';
2
2
  const PLUGIN_IDENTIFIER = 'ssr';
3
+
4
+ const hasStringSSREntry = userConfig => {
5
+ const isStreaming = ssr => ssr && typeof ssr === 'object' && ssr.mode === 'stream';
6
+
7
+ const {
8
+ server
9
+ } = userConfig;
10
+
11
+ if (server !== null && server !== void 0 && server.ssr && !isStreaming(server.ssr)) {
12
+ return true;
13
+ }
14
+
15
+ if (server !== null && server !== void 0 && server.ssrByEntries && typeof server.ssrByEntries === 'object') {
16
+ for (const name of Object.keys(server.ssrByEntries)) {
17
+ if (!isStreaming(server.ssrByEntries[name])) {
18
+ return true;
19
+ }
20
+ }
21
+ }
22
+
23
+ return false;
24
+ };
25
+
3
26
  export default (() => ({
4
27
  name: '@modern-js/plugin-ssr',
5
28
  required: ['@modern-js/runtime'],
@@ -23,9 +46,9 @@ export default (() => ({
23
46
  }) => {
24
47
  const userConfig = api.useResolvedConfigContext();
25
48
 
26
- if (isUseSSRBundle(userConfig) && name !== 'server') {
49
+ if (isUseSSRBundle(userConfig) && name !== 'server' && hasStringSSREntry(userConfig)) {
27
50
  // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
28
- const LoadableWebpackPlugin = require('@modern-js/webpack/@loadable/webpack-plugin');
51
+ const LoadableWebpackPlugin = require('@loadable/webpack-plugin');
29
52
 
30
53
  chain.plugin(CHAIN_ID.PLUGIN.LOADABLE).use(LoadableWebpackPlugin, [{
31
54
  filename: LOADABLE_STATS_FILE
@@ -35,7 +58,7 @@ export default (() => ({
35
58
  babel: config => {
36
59
  const userConfig = api.useResolvedConfigContext();
37
60
 
38
- if (isUseSSRBundle(userConfig)) {
61
+ if (isUseSSRBundle(userConfig) && hasStringSSREntry(userConfig)) {
39
62
  config.plugins.push(require.resolve('@loadable/babel-plugin'));
40
63
  }
41
64
  }
@@ -48,7 +71,8 @@ export default (() => ({
48
71
  imports
49
72
  }) {
50
73
  const {
51
- entryName
74
+ entryName,
75
+ fileSystemRoutes
52
76
  } = entrypoint;
53
77
  const userConfig = api.useResolvedConfigContext();
54
78
  const {
@@ -58,6 +82,21 @@ export default (() => ({
58
82
  pluginsExportsUtils.addExport(`export { default as ssr } from '@modern-js/runtime/ssr'`); // if use ssg then set ssr config to true
59
83
 
60
84
  const ssrConfig = getEntryOptions(entryName, userConfig.server.ssr, userConfig.server.ssrByEntries, packageName);
85
+
86
+ if (typeof ssrConfig === 'object' && ssrConfig.mode === 'stream') {
87
+ var _runtimeConfig$router;
88
+
89
+ const runtimeConfig = getEntryOptions(entryName, userConfig.runtime, userConfig.runtimeByEntries, packageName);
90
+
91
+ if (runtimeConfig !== null && runtimeConfig !== void 0 && (_runtimeConfig$router = runtimeConfig.router) !== null && _runtimeConfig$router !== void 0 && _runtimeConfig$router.legacy) {
92
+ throw new Error(`Legacy router plugin doesn't support streaming SSR, check your config 'runtime.router'`);
93
+ }
94
+
95
+ if (fileSystemRoutes && !entrypoint.nestedRoutesEntry) {
96
+ throw new Error(`You should switch to file-system based router to support streaming SSR.`);
97
+ }
98
+ }
99
+
61
100
  const ssgConfig = userConfig.output.ssg;
62
101
  const useSSG = isSingleEntry(entrypoints) ? Boolean(ssgConfig) : ssgConfig === true || typeof (ssgConfig === null || ssgConfig === void 0 ? void 0 : ssgConfig[0]) === 'function' || Boolean(ssgConfig === null || ssgConfig === void 0 ? void 0 : ssgConfig[entryName]);
63
102
  ssrConfigMap.set(entryName, ssrConfig || useSSG);
@@ -84,7 +123,7 @@ export default (() => ({
84
123
  if (ssrConfigMap.get(entrypoint.entryName)) {
85
124
  plugins.push({
86
125
  name: PLUGIN_IDENTIFIER,
87
- options: ssrConfigMap.get(entrypoint.entryName)
126
+ options: JSON.stringify(ssrConfigMap.get(entrypoint.entryName))
88
127
  });
89
128
  }
90
129
 
@@ -6,12 +6,11 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
6
6
 
7
7
  import { loadableReady } from '@loadable/component';
8
8
  import hoistNonReactStatics from 'hoist-non-react-statics';
9
- import { RenderLevel } from "./serverRender/type";
9
+ import { RenderLevel } from "./serverRender/types";
10
10
  import { WithCallback } from "./react/withCallback";
11
- import { formatClient, mockResponse } from "./utils";
11
+ import { formatClient, mockResponse, isReact18 } from "./utils";
12
12
  import { jsx as _jsx } from "react/jsx-runtime";
13
- const IS_REACT18 = process.env.IS_REACT18 === 'true';
14
- export const ssr = _ => ({
13
+ export const ssr = config => ({
15
14
  name: '@modern-js/plugin-ssr',
16
15
  setup: () => {
17
16
  const mockResp = mockResponse();
@@ -22,49 +21,74 @@ export const ssr = _ => ({
22
21
  ModernRender,
23
22
  ModernHydrate
24
23
  }) => {
25
- var _window, _window$_SSR_DATA;
26
-
27
- // if render level not exist, use client render
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) || RenderLevel.CLIENT_RENDER; // client render and server prefetch use same logic
29
-
30
- if (renderLevel === RenderLevel.CLIENT_RENDER || renderLevel === RenderLevel.SERVER_PREFETCH) {
31
- ModernRender( /*#__PURE__*/_jsx(App, {
32
- context: context
33
- }));
34
- } else if (renderLevel === RenderLevel.SERVER_RENDER) {
35
- loadableReady(() => {
36
- const hydrateContext = _objectSpread(_objectSpread({}, context), {}, {
37
- _hydration: true
38
- });
39
-
40
- const callback = () => {
41
- // won't cause component re-render because context's reference identity doesn't change
42
- delete hydrateContext._hydration;
43
- }; // callback: https://github.com/reactwg/react-18/discussions/5
44
-
45
-
46
- if (IS_REACT18) {
47
- let SSRApp = () => /*#__PURE__*/_jsx(WithCallback, {
48
- callback: callback,
49
- children: /*#__PURE__*/_jsx(App, {
50
- context: hydrateContext
51
- })
52
- });
24
+ const hydrateContext = _objectSpread(_objectSpread({}, context), {}, {
25
+ _hydration: true
26
+ });
27
+
28
+ const callback = () => {
29
+ // won't cause component re-render because context's reference identity doesn't change
30
+ delete hydrateContext._hydration;
31
+ }; // react streamSSR hydrate
32
+
33
+
34
+ if (isReact18() && config.mode === 'stream') {
35
+ return streamSSRHydrate();
36
+ } // react stringSSR hydrate
37
+
38
+
39
+ return stringSSRHydrate();
40
+
41
+ function stringSSRHydrate() {
42
+ var _window, _window$_SSR_DATA;
53
43
 
54
- SSRApp = hoistNonReactStatics(SSRApp, App);
55
- ModernHydrate( /*#__PURE__*/_jsx(SSRApp, {}));
44
+ // if render level not exist, use client render
45
+ 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
46
+
47
+ if (renderLevel === RenderLevel.CLIENT_RENDER || renderLevel === RenderLevel.SERVER_PREFETCH) {
48
+ ModernRender( /*#__PURE__*/_jsx(App, {
49
+ context: context
50
+ }));
51
+ } else if (renderLevel === RenderLevel.SERVER_RENDER) {
52
+ if (isReact18()) {
53
+ loadableReady(() => {
54
+ // callback: https://github.com/reactwg/react-18/discussions/5
55
+ let SSRApp = () => /*#__PURE__*/_jsx(WithCallback, {
56
+ callback: callback,
57
+ children: /*#__PURE__*/_jsx(App, {
58
+ context: hydrateContext
59
+ })
60
+ });
61
+
62
+ SSRApp = hoistNonReactStatics(SSRApp, App);
63
+ ModernHydrate( /*#__PURE__*/_jsx(SSRApp, {}));
64
+ });
56
65
  } else {
57
- ModernHydrate( /*#__PURE__*/_jsx(App, {
58
- context: hydrateContext
59
- }), callback);
66
+ loadableReady(() => {
67
+ ModernHydrate( /*#__PURE__*/_jsx(App, {
68
+ context: hydrateContext
69
+ }), callback);
70
+ });
60
71
  }
72
+ } else {
73
+ // unknown renderlevel or renderlevel is server prefetch.
74
+ console.warn(`unknow render level: ${renderLevel}, execute render()`);
75
+ ModernRender( /*#__PURE__*/_jsx(App, {
76
+ context: context
77
+ }));
78
+ }
79
+ }
80
+
81
+ function streamSSRHydrate() {
82
+ // callback: https://github.com/reactwg/react-18/discussions/5
83
+ let SSRApp = () => /*#__PURE__*/_jsx(WithCallback, {
84
+ callback: callback,
85
+ children: /*#__PURE__*/_jsx(App, {
86
+ context: hydrateContext
87
+ })
61
88
  });
62
- } else {
63
- // unknown renderlevel or renderlevel is server prefetch.
64
- console.warn(`unknow render level: ${renderLevel}, execute render()`);
65
- ModernRender( /*#__PURE__*/_jsx(App, {
66
- context: context
67
- }));
89
+
90
+ SSRApp = hoistNonReactStatics(SSRApp, App);
91
+ ModernHydrate( /*#__PURE__*/_jsx(SSRApp, {}));
68
92
  }
69
93
  },
70
94
 
@@ -5,9 +5,9 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
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
7
  import { registerPrefetch } from "../core";
8
- import { render } from "./serverRender";
9
8
  import prefetch from "./prefetch";
10
9
  import { formatServer } from "./utils";
10
+ import render from "./serverRender";
11
11
  const registeredApps = new WeakSet();
12
12
  export const ssr = (config = {}) => ({
13
13
  name: '@modern-js/plugin-ssr',
@@ -22,7 +22,11 @@ export const ssr = (config = {}) => ({
22
22
  registeredApps.add(App);
23
23
  }
24
24
 
25
- const html = await render(context, config, App);
25
+ const html = await render({
26
+ context: context,
27
+ App: App,
28
+ config
29
+ });
26
30
  return html;
27
31
  },
28
32
 
@@ -1,29 +1,15 @@
1
- import { run } from '@modern-js/utils/ssr';
2
- import { PreRender } from "../react/prerender";
3
- import SSREntry from "./entry";
4
- import { time } from "./measure";
5
- export const render = async (ctx, config, App) => {
6
- const {
7
- ssrContext
8
- } = ctx;
9
- return run(ssrContext.request.headers, async () => {
10
- const entry = new SSREntry({
11
- ctx: ssrContext,
12
- App,
13
- config
14
- });
15
- entry.metrics.emitCounter('app.visit.count', 1);
16
- const end = time();
17
- const html = await entry.renderToHtml(ctx);
18
- const cost = end();
19
- entry.logger.info('App Render Total cost = %d ms', cost);
20
- entry.metrics.emitTimer('app.render.cost', cost);
21
- const cacheConfig = PreRender.config();
1
+ /* eslint-disable eslint-comments/disable-enable-pair */
22
2
 
23
- if (cacheConfig) {
24
- ctx.ssrContext.cacheConfig = cacheConfig;
25
- }
3
+ /* eslint-disable @typescript-eslint/no-var-requires */
26
4
 
5
+ /* eslint-disable @typescript-eslint/no-require-imports */
6
+ import { isReact18 } from "../utils";
7
+ export default async function serverRender(options) {
8
+ if (isReact18() && options.config.mode === 'stream') {
9
+ const pipe = await require("./renderToStream").render(options);
10
+ return pipe;
11
+ } else {
12
+ const html = await require("./renderToString").render(options);
27
13
  return html;
28
- });
29
- };
14
+ }
15
+ }
@@ -0,0 +1,38 @@
1
+ import serialize from 'serialize-javascript';
2
+ import { buildTemplate } from "./buildTemplate.share";
3
+ export function buildShellAfterTemplate(afterAppTemplate, options) {
4
+ const callbacks = [injectSSRDataScript];
5
+ return buildTemplate(afterAppTemplate, callbacks);
6
+
7
+ function injectSSRDataScript(template) {
8
+ const ssrDataScript = buildSSRDataScript();
9
+ return template.replace('<!--<?- SSRDataScript ?>-->', ssrDataScript);
10
+
11
+ function buildSSRDataScript() {
12
+ const {
13
+ ssrContext
14
+ } = options.context;
15
+ const {
16
+ request
17
+ } = ssrContext;
18
+ const SSRData = {
19
+ context: {
20
+ request: {
21
+ params: request.params,
22
+ query: request.query,
23
+ pathname: request.pathname,
24
+ host: request.host,
25
+ url: request.url,
26
+ headers: request.headers,
27
+ cookieMap: request.cookieMap
28
+ }
29
+ }
30
+ };
31
+ return `
32
+ <script>window._SSR_DATA = ${serialize(SSRData, {
33
+ isJSON: true
34
+ })}</script>
35
+ `;
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,5 @@
1
+ // share script
2
+ export const HEAD_REG_EXP = /<head(.|\n)*>(.|\n)*<\/head>/;
3
+ export function buildTemplate(template, callbacks) {
4
+ return callbacks.reduce((template, buildTemplateCb) => buildTemplateCb(template), template);
5
+ }
@@ -0,0 +1,24 @@
1
+ import ReactHelmet from 'react-helmet';
2
+ import helmetReplace from "../helmet";
3
+ import { HEAD_REG_EXP, buildTemplate } from "./buildTemplate.share"; // build head template
4
+
5
+ function getHeadTemplate(beforeEntryTemplate) {
6
+ const callbacks = [headTemplate => {
7
+ const helmetData = ReactHelmet.renderStatic();
8
+ return helmetData ? helmetReplace(headTemplate, helmetData) : headTemplate;
9
+ }];
10
+ const [headTemplate = ''] = beforeEntryTemplate.match(HEAD_REG_EXP) || [];
11
+
12
+ if (!headTemplate.length) {
13
+ return '';
14
+ }
15
+
16
+ return buildTemplate(headTemplate, callbacks); // @TODO: inject css chunks of lazy components
17
+ // @TODO: prefetch scripts of lazy component
18
+ } // build script
19
+
20
+
21
+ export function buildShellBeforeTemplate(beforeAppTemplate) {
22
+ const headTemplate = getHeadTemplate(beforeAppTemplate);
23
+ return beforeAppTemplate.replace(HEAD_REG_EXP, headTemplate);
24
+ }
@@ -0,0 +1,73 @@
1
+ import { createElement } from 'react';
2
+ import { run } from '@modern-js/utils/ssr';
3
+ import { PreRender } from "../../react/prerender";
4
+ import { time } from "../utils";
5
+ import { createTemplates } from "./template";
6
+ import renderToPipe from "./renderToPipe";
7
+ export const render = ({
8
+ App,
9
+ context
10
+ }) => {
11
+ const {
12
+ ssrContext
13
+ } = context;
14
+
15
+ if (!ssrContext) {
16
+ throw new Error('The "ssrContext" must not be undefined, but received undefined');
17
+ }
18
+
19
+ return run(ssrContext.request.headers, async () => {
20
+ const end_all = time();
21
+ const rootElement = /*#__PURE__*/createElement(App, {
22
+ context: Object.assign(context || {}, {
23
+ ssr: true
24
+ })
25
+ });
26
+ const getTemplates = createTemplates(context);
27
+ const end = time();
28
+ const pipe = renderToPipe(rootElement, getTemplates, {
29
+ onShellReady() {
30
+ // set cacheConfig
31
+ const cacheConfig = PreRender.config();
32
+
33
+ if (cacheConfig) {
34
+ context.ssrContext.cacheConfig = cacheConfig;
35
+ }
36
+ },
37
+
38
+ onAllReady() {
39
+ // computed render html cost
40
+ const cost = end();
41
+ ssrContext.logger.debug('App Render To HTML cost = %d ms', cost);
42
+ ssrContext.metrics.emitTimer('app.render.html.cost', cost); // computed all ssr const
43
+
44
+ const cost_all = end_all();
45
+ ssrContext.logger.info('App Render Total cost = %d ms', cost_all);
46
+ ssrContext.metrics.emitTimer('app.render.cost', cost_all);
47
+ }
48
+
49
+ });
50
+ return pipe;
51
+ }); // eslint-disable-next-line @typescript-eslint/no-unused-vars
52
+
53
+ async function prefetch(App, context) {
54
+ const {
55
+ prefetch
56
+ } = App;
57
+ const ssrContext = context.ssrContext;
58
+ let prefetchData;
59
+ const end = time();
60
+
61
+ try {
62
+ prefetchData = prefetch ? await prefetch(context) : null;
63
+ const prefetchCost = end();
64
+ ssrContext.logger.debug(`App Prefetch cost = %d ms`, prefetchCost);
65
+ ssrContext.metrics.emitTimer('app.prefetch.cost', prefetchCost);
66
+ } catch (e) {
67
+ ssrContext.logger.error('App Prefetch Render', e);
68
+ ssrContext.metrics.emitCounter('app.prefetch.render.error', 1);
69
+ }
70
+
71
+ return prefetchData || {};
72
+ }
73
+ };
@@ -0,0 +1,26 @@
1
+ import { ChunkExtractor } from '@loadable/server';
2
+ export function getLoadableChunks({
3
+ context,
4
+ jsx
5
+ }) {
6
+ const {
7
+ loadableStats,
8
+ entryName
9
+ } = context.ssrContext;
10
+
11
+ if (!loadableStats) {
12
+ return {
13
+ jsx
14
+ };
15
+ }
16
+
17
+ const extractor = new ChunkExtractor({
18
+ stats: loadableStats,
19
+ entrypoints: [entryName]
20
+ });
21
+ const collectedJsx = extractor.collectChunks(jsx);
22
+ return {
23
+ jsx: collectedJsx,
24
+ chunkExtractor: extractor
25
+ };
26
+ }
@@ -0,0 +1,61 @@
1
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
2
+
3
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
4
+
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
+
7
+ import { Transform } from 'stream';
8
+ import { renderToPipeableStream } from 'react-dom/server';
9
+
10
+ function renderToPipe(rootElement, getTemplates, options) {
11
+ let isShellStream = true;
12
+
13
+ const forUserPipe = stream => {
14
+ return new Promise(resolve => {
15
+ const {
16
+ pipe
17
+ } = renderToPipeableStream(rootElement, _objectSpread(_objectSpread({}, options), {}, {
18
+ onShellReady() {
19
+ var _options$onShellReady;
20
+
21
+ options === null || options === void 0 ? void 0 : (_options$onShellReady = options.onShellReady) === null || _options$onShellReady === void 0 ? void 0 : _options$onShellReady.call(options);
22
+ const {
23
+ shellAfter,
24
+ shellBefore
25
+ } = getTemplates();
26
+ const injectableTransform = new Transform({
27
+ transform(chunk, _encoding, callback) {
28
+ try {
29
+ if (isShellStream) {
30
+ this.push(joinChunk(shellBefore, chunk, shellAfter));
31
+ isShellStream = false;
32
+ } else {
33
+ this.push(chunk);
34
+ }
35
+
36
+ callback();
37
+ } catch (e) {
38
+ if (e instanceof Error) {
39
+ callback(e);
40
+ } else {
41
+ callback(new Error('Received unkown error when streaming'));
42
+ }
43
+ }
44
+ }
45
+
46
+ });
47
+ resolve(pipe(injectableTransform).pipe(stream));
48
+ }
49
+
50
+ }));
51
+ });
52
+ };
53
+
54
+ return forUserPipe;
55
+
56
+ function joinChunk(before = '', chunk, after = '') {
57
+ return `${before}${chunk.toString()}${after}`;
58
+ }
59
+ }
60
+
61
+ export default renderToPipe;
@@ -0,0 +1,11 @@
1
+ import { ServerStyleSheet } from 'styled-components';
2
+ export function getStyledComponentCss({
3
+ jsx
4
+ }) {
5
+ const sheet = new ServerStyleSheet();
6
+ const collectedJsx = sheet.collectStyles(jsx);
7
+ return {
8
+ styleSheet: sheet,
9
+ jsx: collectedJsx
10
+ };
11
+ }
@@ -0,0 +1,22 @@
1
+ import { buildShellAfterTemplate } from "./buildTemplate.after";
2
+ import { buildShellBeforeTemplate } from "./bulidTemplate.before";
3
+ const HTML_SEPARATOR = '<!--<?- html ?>-->';
4
+ export function createTemplates(context) {
5
+ const getTemplates = () => {
6
+ const {
7
+ template
8
+ } = context.ssrContext;
9
+ const [beforeAppTemplate = '', afterAppHtmlTemplate = ''] = template.split(HTML_SEPARATOR) || []; // templates injected some variables
10
+
11
+ const builtBeforeTemplate = buildShellBeforeTemplate(beforeAppTemplate);
12
+ const builtAfterTemplate = buildShellAfterTemplate(afterAppHtmlTemplate, {
13
+ context
14
+ });
15
+ return {
16
+ shellBefore: builtBeforeTemplate,
17
+ shellAfter: builtAfterTemplate
18
+ };
19
+ };
20
+
21
+ return getTemplates;
22
+ }
@@ -4,13 +4,13 @@ import React from 'react';
4
4
  import ReactDomServer from 'react-dom/server';
5
5
  import serialize from 'serialize-javascript';
6
6
  import ReactHelmet from 'react-helmet';
7
+ import helmetReplace from "../helmet";
8
+ import { RenderLevel } from "../types";
9
+ import { time } from "../utils";
7
10
  import { toFragments } from "./template";
8
- import { RenderLevel } from "./type";
9
- import helmetReplace from "./helmet";
10
11
  import { reduce } from "./reduce";
11
12
  import * as loadableRenderer from "./loadable";
12
13
  import * as styledComponentRenderer from "./styledComponent";
13
- import { time } from "./measure";
14
14
 
15
15
  const buildTemplateData = (context, data, renderLevel) => {
16
16
  const {
@@ -80,9 +80,7 @@ export default class Entry {
80
80
  }
81
81
 
82
82
  async renderToHtml(context) {
83
- const {
84
- ssrContext
85
- } = context;
83
+ const ssrContext = context.ssrContext;
86
84
 
87
85
  if (ssrContext.redirection.url) {
88
86
  return '';
@@ -0,0 +1,31 @@
1
+ import { run } from '@modern-js/utils/ssr';
2
+ import { PreRender } from "../../react/prerender";
3
+ import { time } from "../utils";
4
+ import SSREntry from "./entry";
5
+ export const render = ({
6
+ App,
7
+ context,
8
+ config
9
+ }) => {
10
+ const ssrContext = context.ssrContext;
11
+ return run(ssrContext.request.headers, async () => {
12
+ const entry = new SSREntry({
13
+ ctx: ssrContext,
14
+ App,
15
+ config
16
+ });
17
+ entry.metrics.emitCounter('app.visit.count', 1);
18
+ const end = time();
19
+ const html = await entry.renderToHtml(context);
20
+ const cost = end();
21
+ entry.logger.info('App Render Total cost = %d ms', cost);
22
+ entry.metrics.emitTimer('app.render.cost', cost);
23
+ const cacheConfig = PreRender.config();
24
+
25
+ if (cacheConfig) {
26
+ context.ssrContext.cacheConfig = cacheConfig;
27
+ }
28
+
29
+ return html;
30
+ });
31
+ };
@@ -1,22 +1,14 @@
1
1
  import { ChunkExtractor } from '@loadable/server';
2
- import { isCrossOrigin } from "../utils";
2
+ import { isCrossOrigin } from "../../utils";
3
+ import { getLoadableScripts } from "../utils";
3
4
 
4
5
  const extname = uri => {
5
- return uri.match(/\.[^.]+$/) || '';
6
- };
7
-
8
- function getLoadableScripts(extractor) {
9
- const check = scripts => (scripts || '').includes('__LOADABLE_REQUIRED_CHUNKS___ext');
10
-
11
- const scripts = extractor.getScriptTags();
12
-
13
- if (!check(scripts)) {
6
+ if (typeof uri !== 'string' || !uri.includes('.')) {
14
7
  return '';
15
8
  }
16
9
 
17
- return scripts.split('</script>') // 前两个 script为 loadable 必须的 script
18
- .slice(0, 2).map(i => `${i}</script>`).join('');
19
- }
10
+ return `.${uri === null || uri === void 0 ? void 0 : uri.split('.').pop()}` || '';
11
+ };
20
12
 
21
13
  export const toHtml = (jsx, renderer, next) => {
22
14
  const {
@@ -1,4 +1,3 @@
1
- // import { IncomingHttpHeaders } from 'http';
2
1
  export let RenderLevel;
3
2
 
4
3
  (function (RenderLevel) {
@@ -0,0 +1,2 @@
1
+ import { RenderLevel } from "./renderToString/type";
2
+ export { RenderLevel };