@modern-js/runtime 1.3.4-alpha.0 → 1.4.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 (156) hide show
  1. package/CHANGELOG.md +77 -19
  2. package/dist/js/modern/cli/index.js +4 -4
  3. package/dist/js/modern/common.js +1 -0
  4. package/dist/js/modern/exports/model.js +2 -1
  5. package/dist/js/modern/exports/router.js +2 -1
  6. package/dist/js/modern/exports/server.js +0 -1
  7. package/dist/js/modern/exports/ssr.js +2 -1
  8. package/dist/js/modern/router/cli/index.js +106 -0
  9. package/dist/js/modern/router/index.js +2 -0
  10. package/dist/js/modern/router/runtime/DefaultNotFound.js +13 -0
  11. package/dist/js/modern/router/runtime/index.js +4 -0
  12. package/dist/js/modern/router/runtime/plugin.js +88 -0
  13. package/dist/js/modern/router/runtime/utils.js +108 -0
  14. package/dist/js/modern/ssr/cli/index.js +120 -0
  15. package/dist/js/modern/ssr/index.js +109 -0
  16. package/dist/js/modern/ssr/index.node.js +78 -0
  17. package/dist/js/modern/ssr/prefetch.js +58 -0
  18. package/dist/js/modern/ssr/react/index.js +2 -0
  19. package/dist/js/modern/ssr/react/nossr/index.js +13 -0
  20. package/dist/js/modern/ssr/react/prerender/index.js +104 -0
  21. package/dist/js/modern/ssr/react/prerender/type.js +0 -0
  22. package/dist/js/modern/ssr/react/prerender/util.js +99 -0
  23. package/dist/js/modern/ssr/serverRender/entry.js +179 -0
  24. package/dist/js/modern/ssr/serverRender/helmet.js +46 -0
  25. package/dist/js/modern/ssr/serverRender/index.js +29 -0
  26. package/dist/js/modern/ssr/serverRender/loadable.js +48 -0
  27. package/dist/js/modern/ssr/serverRender/measure.js +11 -0
  28. package/dist/js/modern/ssr/serverRender/reduce.js +7 -0
  29. package/dist/js/modern/ssr/serverRender/styledComponent.js +8 -0
  30. package/dist/js/modern/ssr/serverRender/template.js +90 -0
  31. package/dist/js/modern/ssr/serverRender/type.js +8 -0
  32. package/dist/js/modern/ssr/utils.js +51 -0
  33. package/dist/js/modern/state/cli/index.js +110 -0
  34. package/dist/js/modern/state/index.js +2 -0
  35. package/dist/js/modern/state/plugins.js +7 -0
  36. package/dist/js/modern/state/runtime/index.js +4 -0
  37. package/dist/js/modern/state/runtime/plugin.js +71 -0
  38. package/dist/js/modern/state/types.js +1 -0
  39. package/dist/js/node/cli/index.js +5 -5
  40. package/dist/js/node/common.js +10 -0
  41. package/dist/js/node/exports/model.js +19 -5
  42. package/dist/js/node/exports/router.js +19 -5
  43. package/dist/js/node/exports/server.js +0 -17
  44. package/dist/js/node/exports/ssr.js +19 -5
  45. package/dist/js/node/router/cli/index.js +122 -0
  46. package/dist/js/node/router/index.js +30 -0
  47. package/dist/js/node/router/runtime/DefaultNotFound.js +26 -0
  48. package/dist/js/node/router/runtime/index.js +39 -0
  49. package/dist/js/node/router/runtime/plugin.js +111 -0
  50. package/dist/js/node/router/runtime/utils.js +128 -0
  51. package/dist/js/node/ssr/cli/index.js +136 -0
  52. package/dist/js/node/ssr/index.js +138 -0
  53. package/dist/js/node/ssr/index.node.js +105 -0
  54. package/dist/js/node/ssr/prefetch.js +75 -0
  55. package/dist/js/node/ssr/react/index.js +21 -0
  56. package/dist/js/node/ssr/react/nossr/index.js +28 -0
  57. package/dist/js/node/ssr/react/prerender/index.js +121 -0
  58. package/dist/js/node/ssr/react/prerender/type.js +0 -0
  59. package/dist/js/node/ssr/react/prerender/util.js +119 -0
  60. package/dist/js/node/ssr/serverRender/entry.js +208 -0
  61. package/dist/js/node/ssr/serverRender/helmet.js +52 -0
  62. package/dist/js/node/ssr/serverRender/index.js +46 -0
  63. package/dist/js/node/ssr/serverRender/loadable.js +60 -0
  64. package/dist/js/node/ssr/serverRender/measure.js +20 -0
  65. package/dist/js/node/ssr/serverRender/reduce.js +14 -0
  66. package/dist/js/node/ssr/serverRender/styledComponent.js +18 -0
  67. package/dist/js/node/ssr/serverRender/template.js +103 -0
  68. package/dist/js/node/ssr/serverRender/type.js +15 -0
  69. package/dist/js/node/ssr/utils.js +65 -0
  70. package/dist/js/node/state/cli/index.js +127 -0
  71. package/dist/js/node/state/index.js +30 -0
  72. package/dist/js/node/state/plugins.js +35 -0
  73. package/dist/js/node/state/runtime/index.js +61 -0
  74. package/dist/js/node/state/runtime/plugin.js +101 -0
  75. package/dist/js/node/state/types.js +5 -0
  76. package/dist/js/treeshaking/cli/index.js +4 -4
  77. package/dist/js/treeshaking/common.js +3 -0
  78. package/dist/js/treeshaking/exports/model.js +2 -1
  79. package/dist/js/treeshaking/exports/router.js +2 -1
  80. package/dist/js/treeshaking/exports/server.js +0 -1
  81. package/dist/js/treeshaking/exports/ssr.js +2 -1
  82. package/dist/js/treeshaking/router/cli/index.js +100 -0
  83. package/dist/js/treeshaking/router/index.js +2 -0
  84. package/dist/js/treeshaking/router/runtime/DefaultNotFound.js +15 -0
  85. package/dist/js/treeshaking/router/runtime/index.js +4 -0
  86. package/dist/js/treeshaking/router/runtime/plugin.js +89 -0
  87. package/dist/js/treeshaking/router/runtime/utils.js +106 -0
  88. package/dist/js/treeshaking/ssr/cli/index.js +113 -0
  89. package/dist/js/treeshaking/ssr/index.js +129 -0
  90. package/dist/js/treeshaking/ssr/index.node.js +100 -0
  91. package/dist/js/treeshaking/ssr/prefetch.js +97 -0
  92. package/dist/js/treeshaking/ssr/react/index.js +2 -0
  93. package/dist/js/treeshaking/ssr/react/nossr/index.js +16 -0
  94. package/dist/js/treeshaking/ssr/react/prerender/index.js +119 -0
  95. package/dist/js/treeshaking/ssr/react/prerender/type.js +0 -0
  96. package/dist/js/treeshaking/ssr/react/prerender/util.js +115 -0
  97. package/dist/js/treeshaking/ssr/serverRender/entry.js +267 -0
  98. package/dist/js/treeshaking/ssr/serverRender/helmet.js +37 -0
  99. package/dist/js/treeshaking/ssr/serverRender/index.js +69 -0
  100. package/dist/js/treeshaking/ssr/serverRender/loadable.js +59 -0
  101. package/dist/js/treeshaking/ssr/serverRender/measure.js +17 -0
  102. package/dist/js/treeshaking/ssr/serverRender/reduce.js +11 -0
  103. package/dist/js/treeshaking/ssr/serverRender/styledComponent.js +8 -0
  104. package/dist/js/treeshaking/ssr/serverRender/template.js +111 -0
  105. package/dist/js/treeshaking/ssr/serverRender/type.js +8 -0
  106. package/dist/js/treeshaking/ssr/utils.js +53 -0
  107. package/dist/js/treeshaking/state/cli/index.js +100 -0
  108. package/dist/js/treeshaking/state/index.js +2 -0
  109. package/dist/js/treeshaking/state/plugins.js +13 -0
  110. package/dist/js/treeshaking/state/runtime/index.js +4 -0
  111. package/dist/js/treeshaking/state/runtime/plugin.js +63 -0
  112. package/dist/js/treeshaking/state/types.js +1 -0
  113. package/dist/types/common.d.ts +1 -0
  114. package/dist/types/exports/model.d.ts +2 -1
  115. package/dist/types/exports/router.d.ts +2 -1
  116. package/dist/types/exports/server.d.ts +0 -1
  117. package/dist/types/exports/ssr.d.ts +2 -1
  118. package/dist/types/index.d.ts +8 -2
  119. package/dist/types/router/cli/index.d.ts +5 -0
  120. package/dist/types/router/index.d.ts +2 -0
  121. package/dist/types/router/runtime/DefaultNotFound.d.ts +2 -0
  122. package/dist/types/router/runtime/index.d.ts +6 -0
  123. package/dist/types/router/runtime/plugin.d.ts +51 -0
  124. package/dist/types/router/runtime/utils.d.ts +6 -0
  125. package/dist/types/ssr/cli/index.d.ts +5 -0
  126. package/dist/types/ssr/index.d.ts +18 -0
  127. package/dist/types/ssr/index.node.d.ts +4 -0
  128. package/dist/types/ssr/prefetch.d.ts +13 -0
  129. package/dist/types/ssr/react/index.d.ts +2 -0
  130. package/dist/types/ssr/react/nossr/index.d.ts +2 -0
  131. package/dist/types/ssr/react/prerender/index.d.ts +1 -0
  132. package/dist/types/ssr/react/prerender/type.d.ts +29 -0
  133. package/dist/types/ssr/react/prerender/util.d.ts +6 -0
  134. package/dist/types/ssr/serverRender/entry.d.ts +20 -0
  135. package/dist/types/ssr/serverRender/helmet.d.ts +2 -0
  136. package/dist/types/ssr/serverRender/index.d.ts +8 -0
  137. package/dist/types/ssr/serverRender/loadable.d.ts +2 -0
  138. package/dist/types/ssr/serverRender/measure.d.ts +1 -0
  139. package/dist/types/ssr/serverRender/reduce.d.ts +3 -0
  140. package/dist/types/ssr/serverRender/styledComponent.d.ts +2 -0
  141. package/dist/types/ssr/serverRender/template.d.ts +14 -0
  142. package/dist/types/ssr/serverRender/type.d.ts +32 -0
  143. package/dist/types/ssr/utils.d.ts +8 -0
  144. package/dist/types/state/cli/index.d.ts +5 -0
  145. package/dist/types/state/index.d.ts +2 -0
  146. package/dist/types/state/plugins.d.ts +4 -0
  147. package/dist/types/state/runtime/index.d.ts +4 -0
  148. package/dist/types/state/runtime/plugin.d.ts +17 -0
  149. package/dist/types/state/types.d.ts +17 -0
  150. package/package.json +37 -20
  151. package/types/model.d.ts +1 -1
  152. package/types/state.d.ts +4 -0
  153. package/dist/js/modern/exports/request.js +0 -1
  154. package/dist/js/node/exports/request.js +0 -13
  155. package/dist/js/treeshaking/exports/request.js +0 -1
  156. package/dist/types/exports/request.d.ts +0 -1
@@ -0,0 +1,109 @@
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 ReactDOM from 'react-dom';
8
+ import { loadableReady } from '@loadable/component';
9
+ import { RenderLevel } from "./serverRender/type";
10
+ import { formatClient, mockResponse } from "./utils";
11
+ import { jsx as _jsx } from "react/jsx-runtime";
12
+
13
+ const ssr = () => ({
14
+ name: '@modern-js/plugin-ssr',
15
+ setup: () => {
16
+ const mockResp = mockResponse();
17
+ return {
18
+ client: async ({
19
+ App,
20
+ context,
21
+ rootElement
22
+ }) => {
23
+ var _window, _window$_SSR_DATA;
24
+
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;
26
+
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, {
32
+ context: context
33
+ }), rootElement);
34
+ } else if (renderLevel === RenderLevel.SERVER_RENDER) {
35
+ loadableReady(() => {
36
+ const hydrateContext = _objectSpread(_objectSpread({}, context), {}, {
37
+ _hydration: true
38
+ });
39
+
40
+ ReactDOM.hydrate( /*#__PURE__*/_jsx(App, {
41
+ context: hydrateContext
42
+ }), rootElement, () => {
43
+ // won't cause component re-render because context's reference identity doesn't change
44
+ delete hydrateContext._hydration;
45
+ });
46
+ });
47
+ } else {
48
+ // unknown renderlevel or renderlevel is server prefetch.
49
+ ReactDOM.render( /*#__PURE__*/_jsx(App, {
50
+ context: context
51
+ }), rootElement);
52
+ }
53
+ },
54
+
55
+ init({
56
+ context
57
+ }, next) {
58
+ var _window2, _window2$_SSR_DATA, _window2$_SSR_DATA$co;
59
+
60
+ 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
+
62
+ if (!request) {
63
+ return next({
64
+ context
65
+ });
66
+ }
67
+
68
+ context.ssrContext.response = mockResp;
69
+ context.ssrContext.request = formatClient(request);
70
+ return next({
71
+ context
72
+ });
73
+ },
74
+
75
+ pickContext: ({
76
+ context,
77
+ pickedContext
78
+ }, next) => {
79
+ var _window3, _window3$_SSR_DATA, _window3$_SSR_DATA$co;
80
+
81
+ const request = (_window3 = window) === null || _window3 === void 0 ? void 0 : (_window3$_SSR_DATA = _window3._SSR_DATA) === null || _window3$_SSR_DATA === void 0 ? void 0 : (_window3$_SSR_DATA$co = _window3$_SSR_DATA.context) === null || _window3$_SSR_DATA$co === void 0 ? void 0 : _window3$_SSR_DATA$co.request;
82
+ const {
83
+ initialData
84
+ } = context;
85
+
86
+ if (!request) {
87
+ return next({
88
+ context,
89
+ pickedContext: _objectSpread(_objectSpread({}, pickedContext), {}, {
90
+ initialData
91
+ })
92
+ });
93
+ }
94
+
95
+ return next({
96
+ context,
97
+ pickedContext: _objectSpread(_objectSpread({}, pickedContext), {}, {
98
+ initialData,
99
+ request,
100
+ response: mockResp
101
+ })
102
+ });
103
+ }
104
+ };
105
+ }
106
+ });
107
+
108
+ export default ssr;
109
+ export * from "./react";
@@ -0,0 +1,78 @@
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
+ /* eslint-disable @typescript-eslint/no-var-requires */
8
+
9
+ /* eslint-disable @typescript-eslint/no-require-imports */
10
+ import path from 'path';
11
+ import { registerPrefetch } from '@modern-js/runtime-core';
12
+ import { isBrowser } from "../common";
13
+ import prefetch from "./prefetch";
14
+ import { formatServer } from "./utils";
15
+ const registeredApps = new WeakSet();
16
+
17
+ const plugin = () => ({
18
+ name: '@modern-js/plugin-ssr',
19
+ setup: () => {
20
+ return {
21
+ server: async ({
22
+ App,
23
+ context
24
+ }) => {
25
+ if (!registeredApps.has(App)) {
26
+ registerPrefetch(App, _context => prefetch(App, _context));
27
+ registeredApps.add(App);
28
+ }
29
+
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);
32
+ return html;
33
+ }
34
+
35
+ return null;
36
+ },
37
+
38
+ init({
39
+ context
40
+ }, next) {
41
+ const {
42
+ request
43
+ } = context.ssrContext;
44
+ context.ssrContext.request = formatServer(request);
45
+ return next({
46
+ context
47
+ });
48
+ },
49
+
50
+ pickContext: ({
51
+ context,
52
+ pickedContext
53
+ }, next) => {
54
+ const {
55
+ request,
56
+ response
57
+ } = context === null || context === void 0 ? void 0 : context.ssrContext;
58
+ const {
59
+ initialData
60
+ } = context;
61
+ return next({
62
+ context,
63
+ pickedContext: _objectSpread(_objectSpread({}, pickedContext), {}, {
64
+ initialData,
65
+ request,
66
+ response
67
+ })
68
+ });
69
+ }
70
+ };
71
+ }
72
+ });
73
+
74
+ export default plugin;
75
+ export * from "./react";
76
+ /* eslint-enable @typescript-eslint/no-require-imports */
77
+
78
+ /* eslint-enable @typescript-eslint/no-var-requires */
@@ -0,0 +1,58 @@
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ import { renderToStaticMarkup } from 'react-dom/server';
4
+ import { run } from '@modern-js/utils/ssr';
5
+ import { LOADABLE_STATS_FILE } from '@modern-js/utils/constants';
6
+ import { ChunkExtractor } from '@loadable/server'; // todo: SSRContext
7
+
8
+ import { jsx as _jsx } from "react/jsx-runtime";
9
+
10
+ const prefetch = async (App, context) => run(context.ssrContext.request.headers, async () => {
11
+ var _context$store;
12
+
13
+ const {
14
+ ssrContext
15
+ } = context;
16
+ const loadablefile = path.resolve(ssrContext.distDir, LOADABLE_STATS_FILE);
17
+
18
+ if (fs.existsSync(loadablefile)) {
19
+ const extractor = new ChunkExtractor({
20
+ statsFile: path.resolve(ssrContext.distDir, LOADABLE_STATS_FILE),
21
+ entrypoints: [ssrContext.entryName].filter(Boolean)
22
+ });
23
+ renderToStaticMarkup(extractor.collectChunks( /*#__PURE__*/_jsx(App, {
24
+ context: context
25
+ })));
26
+ } else {
27
+ renderToStaticMarkup( /*#__PURE__*/_jsx(App, {
28
+ context: context
29
+ }));
30
+ }
31
+
32
+ if (!context.loaderManager.hasPendingLoaders()) {
33
+ return {
34
+ initialData: context.initialData,
35
+ i18nData: context.__i18nData__
36
+ };
37
+ }
38
+
39
+ const loadersData = await context.loaderManager.awaitPendingLoaders();
40
+ Object.keys(loadersData).forEach(id => {
41
+ const data = loadersData[id];
42
+
43
+ if (data._error) {
44
+ ssrContext.logger.error('App Prefetch Loader', data._error);
45
+ ssrContext.metrics.emitCounter('app.prefetch.loader.error', 1);
46
+ delete data._error;
47
+ }
48
+ });
49
+ return {
50
+ loadersData,
51
+ initialData: context.initialData,
52
+ i18nData: context.__i18nData__,
53
+ // todo: move to plugin state
54
+ storeState: context === null || context === void 0 ? void 0 : (_context$store = context.store) === null || _context$store === void 0 ? void 0 : _context$store.getState()
55
+ };
56
+ });
57
+
58
+ export default prefetch;
@@ -0,0 +1,2 @@
1
+ export { PreRender } from "./prerender";
2
+ export { NoSSR } from "./nossr";
@@ -0,0 +1,13 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ let csr = false;
3
+ export const NoSSR = props => {
4
+ const [isMounted, setMounted] = useState(csr);
5
+ useEffect(() => {
6
+ csr = true;
7
+ setMounted(true);
8
+ });
9
+ const {
10
+ children
11
+ } = props;
12
+ return /*#__PURE__*/React.createElement(React.Fragment, null, isMounted ? children : null);
13
+ };
@@ -0,0 +1,104 @@
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 withSideEffect from 'react-side-effect';
8
+ import React, { createElement } from 'react';
9
+ import { getOutermostProperty, aggKeysFromPropsList, exist, aggMatchesFromPropsList } from "./util";
10
+ const PROP_NAMES = {
11
+ INTERVAL: 'interval',
12
+ STALE_LIMIT: 'staleLimit',
13
+ LEVEL: 'level',
14
+ INCLUDES: 'includes',
15
+ EXCLUDES: 'excludes',
16
+ FALLBACK: 'fallback',
17
+ MATCHES: 'matches'
18
+ };
19
+
20
+ const handleClientStateChange = () => {// not used
21
+ };
22
+
23
+ const mapStateOnServer = reduceProps => {
24
+ const defaultProps = {
25
+ interval: 10,
26
+ staleLimit: false,
27
+ level: 0,
28
+ includes: null,
29
+ excludes: null,
30
+ fallback: false,
31
+ matches: null
32
+ };
33
+ return Object.keys(defaultProps).reduce((props, key) => {
34
+ const propKey = key;
35
+ const reduceProp = reduceProps[propKey];
36
+ let nextProps = props;
37
+
38
+ if (exist(reduceProp)) {
39
+ nextProps = _objectSpread(_objectSpread({}, props), {}, {
40
+ [propKey]: reduceProp
41
+ });
42
+ }
43
+
44
+ return nextProps;
45
+ }, defaultProps);
46
+ };
47
+
48
+ const reducePropsToState = propsList => {
49
+ const reduceProps = {
50
+ interval: getOutermostProperty(propsList, PROP_NAMES.INTERVAL),
51
+ staleLimit: getOutermostProperty(propsList, PROP_NAMES.STALE_LIMIT),
52
+ level: getOutermostProperty(propsList, PROP_NAMES.LEVEL),
53
+ includes: aggKeysFromPropsList(propsList, PROP_NAMES.INCLUDES),
54
+ excludes: aggKeysFromPropsList(propsList, PROP_NAMES.EXCLUDES),
55
+ fallback: getOutermostProperty(propsList, PROP_NAMES.FALLBACK),
56
+ matches: aggMatchesFromPropsList(propsList, PROP_NAMES.MATCHES)
57
+ };
58
+ return reduceProps;
59
+ };
60
+
61
+ function factory(Component) {
62
+ class Spr extends React.Component {
63
+ static set canUseDOM(canUseDOM) {
64
+ Component.canUseDOM = canUseDOM;
65
+ }
66
+
67
+ static get canUseDOM() {
68
+ return Component.canUseDOM;
69
+ }
70
+
71
+ verify() {
72
+ return true;
73
+ }
74
+
75
+ render() {
76
+ const newProps = _objectSpread({}, this.props);
77
+
78
+ const validate = this.verify();
79
+
80
+ if (!validate) {
81
+ throw new Error('invalid props, check usage');
82
+ }
83
+
84
+ return /*#__PURE__*/createElement(Component, _objectSpread({}, newProps));
85
+ }
86
+
87
+ }
88
+
89
+ _defineProperty(Spr, "peek", Component.peek);
90
+
91
+ _defineProperty(Spr, "rewind", Component.rewind);
92
+
93
+ _defineProperty(Spr, "config", () => {
94
+ const mappedState = Component.rewind();
95
+ return mappedState;
96
+ });
97
+
98
+ return Spr;
99
+ }
100
+
101
+ const NullComponent = () => null;
102
+
103
+ const SprSideEffects = withSideEffect(reducePropsToState, handleClientStateChange, mapStateOnServer)(NullComponent);
104
+ export const PreRender = factory(SprSideEffects);
File without changes
@@ -0,0 +1,99 @@
1
+ const REQUEST_META = ['header', 'query'];
2
+ export const getInnermostProperty = function getInnermostProperty(propsList, propName) {
3
+ for (let i = propsList.length - 1; i >= 0; i--) {
4
+ const props = propsList[i];
5
+
6
+ if (props.hasOwnProperty(propName)) {
7
+ return props[propName];
8
+ }
9
+ }
10
+
11
+ return null;
12
+ };
13
+ export const getOutermostProperty = function getOutermostProperty(propsList, propName) {
14
+ for (const props of propsList) {
15
+ if (props.hasOwnProperty(propName)) {
16
+ return props[propName];
17
+ }
18
+ }
19
+
20
+ return null;
21
+ };
22
+ export const aggKeysFromPropsList = function aggKeysFromPropsList(propsList, propName) {
23
+ const initResult = REQUEST_META.reduce((result, next) => {
24
+ const key = next;
25
+ result[key] = [];
26
+ return result;
27
+ }, {});
28
+ const res = propsList.filter(props => usefulObject(props[propName])).reduce((result, next) => {
29
+ REQUEST_META.forEach(key => {
30
+ const prop = next[propName];
31
+
32
+ if (prop !== null && prop !== void 0 && prop.hasOwnProperty(key) && usefulArray(prop[key])) {
33
+ result[key] = unique(result[key].concat(prop[key]));
34
+ }
35
+ });
36
+ return result;
37
+ }, initResult);
38
+ return REQUEST_META.reduce((result, next) => {
39
+ var _result$key;
40
+
41
+ const key = next;
42
+
43
+ if (result[key] && ((_result$key = result[key]) === null || _result$key === void 0 ? void 0 : _result$key.length) === 0) {
44
+ delete result[key];
45
+ }
46
+
47
+ return result;
48
+ }, res);
49
+ };
50
+ export const aggMatchesFromPropsList = function aggMatchesFromPropsList(propsList, propName) {
51
+ const initResult = REQUEST_META.reduce((result, next) => {
52
+ const key = next;
53
+ result[key] = {};
54
+ return result;
55
+ }, {});
56
+ const res = propsList.filter(props => usefulObject(props[propName])).reduce((result, next) => {
57
+ REQUEST_META.forEach(key => {
58
+ const prop = next[propName]; // 这边目前是浅拷贝,越后渲染优先级越高
59
+
60
+ if (prop !== null && prop !== void 0 && prop.hasOwnProperty(key) && usefulObject(prop[key])) {
61
+ result[key] = Object.assign(result[key], prop[key]);
62
+ }
63
+ });
64
+ return result;
65
+ }, initResult);
66
+ return REQUEST_META.reduce((result, next) => {
67
+ const key = next;
68
+
69
+ if (result[key] && Object.keys(result[key]).length === 0) {
70
+ delete result[key];
71
+ }
72
+
73
+ return result;
74
+ }, res);
75
+ };
76
+
77
+ function unique(arr) {
78
+ return Array.from(new Set(arr));
79
+ }
80
+
81
+ function usefulObject(target) {
82
+ if (!exist(target)) {
83
+ return false;
84
+ }
85
+
86
+ return target.constructor === Object && Object.keys(target).length > 0;
87
+ }
88
+
89
+ function usefulArray(target) {
90
+ if (!exist(target)) {
91
+ return false;
92
+ }
93
+
94
+ return Array.isArray(target) && target.length > 0;
95
+ }
96
+
97
+ export function exist(target) {
98
+ return target != null;
99
+ }
@@ -0,0 +1,179 @@
1
+ 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; }
2
+
3
+ import path from 'path';
4
+ import { LOADABLE_STATS_FILE } from '@modern-js/utils/constants';
5
+ import React from 'react';
6
+ import ReactDomServer from 'react-dom/server';
7
+ import serialize from 'serialize-javascript';
8
+ import ReactHelmet from 'react-helmet';
9
+ import { toFragments } from "./template";
10
+ import { RenderLevel } from "./type";
11
+ import helmetReplace from "./helmet";
12
+ import { reduce } from "./reduce";
13
+ import * as loadableRenderer from "./loadable";
14
+ import * as styledComponentRenderer from "./styledComponent";
15
+ import { time } from "./measure";
16
+
17
+ const buildTemplateData = (context, data, renderLevel) => {
18
+ const {
19
+ request
20
+ } = context;
21
+ return {
22
+ data,
23
+ context: {
24
+ request: {
25
+ params: request.params,
26
+ query: request.query,
27
+ pathname: request.pathname,
28
+ host: request.host,
29
+ url: request.url,
30
+ headers: request.headers,
31
+ cookieMap: request.cookieMap
32
+ }
33
+ },
34
+ renderLevel
35
+ };
36
+ };
37
+
38
+ export default class Entry {
39
+ constructor(options) {
40
+ _defineProperty(this, "entryName", void 0);
41
+
42
+ _defineProperty(this, "result", void 0);
43
+
44
+ _defineProperty(this, "metrics", void 0);
45
+
46
+ _defineProperty(this, "logger", void 0);
47
+
48
+ _defineProperty(this, "App", void 0);
49
+
50
+ _defineProperty(this, "fragments", void 0);
51
+
52
+ const {
53
+ ctx
54
+ } = options;
55
+ const {
56
+ entryName,
57
+ template: templateHTML
58
+ } = ctx;
59
+ this.fragments = toFragments(templateHTML);
60
+ this.entryName = entryName;
61
+ this.App = options.App;
62
+ this.metrics = ctx.metrics;
63
+ this.logger = ctx.logger;
64
+ this.result = {
65
+ renderLevel: RenderLevel.CLIENT_RENDER,
66
+ html: '',
67
+ chunksMap: {
68
+ js: '',
69
+ css: ''
70
+ }
71
+ };
72
+ }
73
+
74
+ async renderToHtml(context) {
75
+ const {
76
+ ssrContext
77
+ } = context;
78
+
79
+ if (ssrContext.redirection.url) {
80
+ return '';
81
+ }
82
+
83
+ const prefetchData = await this.prefetch(context);
84
+
85
+ if (ssrContext.redirection.url) {
86
+ return '';
87
+ }
88
+
89
+ if (this.result.renderLevel >= RenderLevel.SERVER_PREFETCH) {
90
+ this.result.html = this.renderToString(context);
91
+ }
92
+
93
+ if (ssrContext.redirection.url) {
94
+ return '';
95
+ }
96
+
97
+ let html = '';
98
+ const templateData = buildTemplateData(ssrContext, prefetchData, this.result.renderLevel);
99
+ const SSRData = this.getSSRDataScript(templateData);
100
+
101
+ for (const fragment of this.fragments) {
102
+ if (fragment.isVariable && fragment.content === 'SSRDataScript') {
103
+ html += fragment.getValue(SSRData);
104
+ } else {
105
+ html += fragment.getValue(this.result);
106
+ }
107
+ }
108
+
109
+ const helmetData = ReactHelmet.renderStatic();
110
+ return helmetData ? helmetReplace(html, helmetData) : html;
111
+ }
112
+
113
+ async prefetch(context) {
114
+ const {
115
+ App: {
116
+ prefetch
117
+ }
118
+ } = this;
119
+ let prefetchData;
120
+ const end = time();
121
+
122
+ try {
123
+ prefetchData = prefetch ? await prefetch(context) : null;
124
+ this.result.renderLevel = RenderLevel.SERVER_PREFETCH;
125
+ const prefetchCost = end();
126
+ this.logger.debug(`App Prefetch cost = %d ms`, prefetchCost);
127
+ this.metrics.emitTimer('app.prefetch.cost', prefetchCost);
128
+ } catch (e) {
129
+ this.result.renderLevel = RenderLevel.CLIENT_RENDER;
130
+ this.logger.error('App Prefetch Render', e);
131
+ this.metrics.emitCounter('app.prefetch.render.error', 1);
132
+ }
133
+
134
+ return prefetchData || {};
135
+ }
136
+
137
+ renderToString(context) {
138
+ let html = '';
139
+ const end = time();
140
+ const {
141
+ ssrContext
142
+ } = context;
143
+
144
+ try {
145
+ const App = /*#__PURE__*/React.createElement(this.App, {
146
+ context: Object.assign(context, {
147
+ ssr: true
148
+ })
149
+ }); // Todo render Hook
150
+
151
+ const renderContext = {
152
+ loadableManifest: path.resolve(ssrContext.distDir, LOADABLE_STATS_FILE),
153
+ result: this.result,
154
+ entryName: this.entryName
155
+ };
156
+ html = reduce(App, renderContext, [styledComponentRenderer.toHtml, loadableRenderer.toHtml, jsx => ReactDomServer.renderToString(jsx)]);
157
+ const cost = end();
158
+ this.logger.debug('App Render To HTML cost = %d ms', cost);
159
+ this.metrics.emitTimer('app.render.html.cost', cost);
160
+ this.result.renderLevel = RenderLevel.SERVER_RENDER;
161
+ } catch (e) {
162
+ this.logger.error('App Render To HTML', e);
163
+ this.metrics.emitCounter('app.render.html.error', 1);
164
+ }
165
+
166
+ return html;
167
+ }
168
+
169
+ getSSRDataScript(templateData) {
170
+ return {
171
+ SSRDataScript: `
172
+ <script>window._SSR_DATA = ${serialize(templateData, {
173
+ isJSON: true
174
+ })}</script>
175
+ `
176
+ };
177
+ }
178
+
179
+ }
@@ -0,0 +1,46 @@
1
+ // 用于 react-helmet 正则替换
2
+ const RE_HTML_ATTR = /<html[^>]*>/;
3
+ const RE_BODY_ATTR = /<body[^>]*>/;
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 修改模板
7
+
8
+ export default function helmet(content, helmetData) {
9
+ let result = content;
10
+ const bodyAttributes = helmetData.bodyAttributes.toString();
11
+
12
+ if (bodyAttributes) {
13
+ result = result.replace(RE_BODY_ATTR, `<body ${bodyAttributes}>`);
14
+ }
15
+
16
+ const htmlAttributes = helmetData.htmlAttributes.toString();
17
+
18
+ if (htmlAttributes) {
19
+ result = result.replace(RE_HTML_ATTR, `<html ${htmlAttributes}>`);
20
+ }
21
+
22
+ const base = helmetData.base.toString();
23
+ const link = helmetData.link.toString();
24
+ const meta = helmetData.meta.toString();
25
+ const noscript = helmetData.noscript.toString();
26
+ const script = helmetData.script.toString();
27
+ const style = helmetData.style.toString();
28
+ const title = helmetData.title.toString(); // 如果模板中存在 title,且 helmetData title 有内容则做替换
29
+
30
+ const existTitle = RE_TITLE.test(content);
31
+
32
+ if (TEST_TITLE_CONTENT.test(title.trim()) && existTitle) {
33
+ result = result.replace(RE_TITLE, title);
34
+ }
35
+
36
+ return result.replace(RE_LAST_IN_HEAD, `
37
+ ${base}
38
+ ${link}
39
+ ${meta}
40
+ ${noscript}
41
+ ${script}
42
+ ${style}
43
+ ${existTitle ? '' : title}
44
+ </head>
45
+ `);
46
+ }