@modern-js/runtime 1.21.2 → 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.
- package/CHANGELOG.md +52 -0
- package/dist/js/modern/cli/index.js +1 -1
- package/dist/js/modern/core/index.js +1 -1
- package/dist/js/modern/index.js +1 -0
- package/dist/js/modern/router/cli/index.js +24 -8
- package/dist/js/modern/router/runtime/index.js +1 -1
- package/dist/js/modern/router/runtime/plugin.js +26 -44
- package/dist/js/modern/router/runtime/plugin.node.js +143 -0
- package/dist/js/modern/router/runtime/types.js +1 -0
- package/dist/js/modern/router/runtime/utils.js +97 -37
- package/dist/js/modern/router/runtime/withRouter.js +22 -0
- package/dist/js/modern/runtime-context.js +2 -1
- package/dist/js/modern/ssr/cli/index.js +44 -5
- package/dist/js/modern/ssr/index.js +67 -43
- package/dist/js/modern/ssr/index.node.js +6 -2
- package/dist/js/modern/ssr/serverRender/index.js +12 -26
- package/dist/js/modern/ssr/serverRender/renderToStream/buildTemplate.after.js +38 -0
- package/dist/js/modern/ssr/serverRender/renderToStream/buildTemplate.share.js +5 -0
- package/dist/js/modern/ssr/serverRender/renderToStream/bulidTemplate.before.js +24 -0
- package/dist/js/modern/ssr/serverRender/renderToStream/index.js +73 -0
- package/dist/js/modern/ssr/serverRender/renderToStream/loadable.js +26 -0
- package/dist/js/modern/ssr/serverRender/renderToStream/renderToPipe.js +61 -0
- package/dist/js/modern/ssr/serverRender/renderToStream/styledComponent.js +11 -0
- package/dist/js/modern/ssr/serverRender/renderToStream/template.js +22 -0
- package/dist/js/modern/ssr/serverRender/renderToStream/type.js +0 -0
- package/dist/js/modern/ssr/serverRender/{entry.js → renderToString/entry.js} +4 -6
- package/dist/js/modern/ssr/serverRender/renderToString/index.js +31 -0
- package/dist/js/modern/ssr/serverRender/{loadable.js → renderToString/loadable.js} +5 -13
- package/dist/js/modern/ssr/serverRender/{reduce.js → renderToString/reduce.js} +0 -0
- package/dist/js/modern/ssr/serverRender/{styledComponent.js → renderToString/styledComponent.js} +0 -0
- package/dist/js/modern/ssr/serverRender/{template.js → renderToString/template.js} +0 -0
- package/dist/js/modern/ssr/serverRender/{type.js → renderToString/type.js} +0 -1
- package/dist/js/modern/ssr/serverRender/types.js +2 -0
- package/dist/js/modern/ssr/serverRender/utils.js +24 -0
- package/dist/js/modern/ssr/utils.js +9 -3
- package/dist/js/node/cli/index.js +1 -1
- package/dist/js/node/core/index.js +8 -1
- package/dist/js/node/index.js +8 -0
- package/dist/js/node/router/cli/index.js +24 -8
- package/dist/js/node/router/runtime/index.js +4 -4
- package/dist/js/node/router/runtime/plugin.js +24 -49
- package/dist/js/node/router/runtime/plugin.node.js +169 -0
- package/dist/js/node/router/runtime/types.js +5 -0
- package/dist/js/node/router/runtime/utils.js +97 -35
- package/dist/js/node/router/runtime/withRouter.js +35 -0
- package/dist/js/node/runtime-context.js +4 -2
- package/dist/js/node/ssr/cli/index.js +43 -5
- package/dist/js/node/ssr/index.js +66 -43
- package/dist/js/node/ssr/index.node.js +7 -3
- package/dist/js/node/ssr/serverRender/index.js +13 -35
- package/dist/js/node/ssr/serverRender/renderToStream/buildTemplate.after.js +49 -0
- package/dist/js/node/ssr/serverRender/renderToStream/buildTemplate.share.js +14 -0
- package/dist/js/node/ssr/serverRender/renderToStream/bulidTemplate.before.js +37 -0
- package/dist/js/node/ssr/serverRender/renderToStream/index.js +90 -0
- package/dist/js/node/ssr/serverRender/renderToStream/loadable.js +34 -0
- package/dist/js/node/ssr/serverRender/renderToStream/renderToPipe.js +70 -0
- package/dist/js/node/ssr/serverRender/renderToStream/styledComponent.js +19 -0
- package/dist/js/node/ssr/serverRender/renderToStream/template.js +32 -0
- package/dist/js/node/ssr/serverRender/renderToStream/type.js +0 -0
- package/dist/js/node/ssr/serverRender/{entry.js → renderToString/entry.js} +13 -15
- package/dist/js/node/ssr/serverRender/renderToString/index.js +47 -0
- package/dist/js/node/ssr/serverRender/{loadable.js → renderToString/loadable.js} +7 -14
- package/dist/js/node/ssr/serverRender/{reduce.js → renderToString/reduce.js} +0 -0
- package/dist/js/node/ssr/serverRender/{styledComponent.js → renderToString/styledComponent.js} +0 -0
- package/dist/js/node/ssr/serverRender/{template.js → renderToString/template.js} +0 -0
- package/dist/js/node/ssr/serverRender/{type.js → renderToString/type.js} +0 -1
- package/dist/js/node/ssr/serverRender/types.js +13 -0
- package/dist/js/node/ssr/serverRender/utils.js +34 -0
- package/dist/js/node/ssr/utils.js +13 -4
- package/dist/js/treeshaking/cli/index.js +1 -1
- package/dist/js/treeshaking/core/index.js +1 -1
- package/dist/js/treeshaking/index.js +1 -0
- package/dist/js/treeshaking/router/cli/index.js +24 -8
- package/dist/js/treeshaking/router/runtime/index.js +1 -1
- package/dist/js/treeshaking/router/runtime/plugin.js +25 -43
- package/dist/js/treeshaking/router/runtime/plugin.node.js +174 -0
- package/dist/js/treeshaking/router/runtime/types.js +1 -0
- package/dist/js/treeshaking/router/runtime/utils.js +100 -36
- package/dist/js/treeshaking/router/runtime/withRouter.js +17 -0
- package/dist/js/treeshaking/runtime-context.js +2 -1
- package/dist/js/treeshaking/ssr/cli/index.js +47 -5
- package/dist/js/treeshaking/ssr/index.js +74 -45
- package/dist/js/treeshaking/ssr/index.node.js +6 -2
- package/dist/js/treeshaking/ssr/serverRender/index.js +41 -55
- package/dist/js/treeshaking/ssr/serverRender/renderToStream/buildTemplate.after.js +33 -0
- package/dist/js/treeshaking/ssr/serverRender/renderToStream/buildTemplate.share.js +7 -0
- package/dist/js/treeshaking/ssr/serverRender/renderToStream/bulidTemplate.before.js +29 -0
- package/dist/js/treeshaking/ssr/serverRender/renderToStream/index.js +120 -0
- package/dist/js/treeshaking/ssr/serverRender/renderToStream/loadable.js +24 -0
- package/dist/js/treeshaking/ssr/serverRender/renderToStream/renderToPipe.js +57 -0
- package/dist/js/treeshaking/ssr/serverRender/renderToStream/styledComponent.js +10 -0
- package/dist/js/treeshaking/ssr/serverRender/renderToStream/template.js +29 -0
- package/dist/js/treeshaking/ssr/serverRender/renderToStream/type.js +0 -0
- package/dist/js/treeshaking/ssr/serverRender/{entry.js → renderToString/entry.js} +3 -3
- package/dist/js/treeshaking/ssr/serverRender/renderToString/index.js +48 -0
- package/dist/js/treeshaking/ssr/serverRender/{loadable.js → renderToString/loadable.js} +5 -17
- package/dist/js/treeshaking/ssr/serverRender/{reduce.js → renderToString/reduce.js} +0 -0
- package/dist/js/treeshaking/ssr/serverRender/{styledComponent.js → renderToString/styledComponent.js} +0 -0
- package/dist/js/treeshaking/ssr/serverRender/{template.js → renderToString/template.js} +0 -0
- package/dist/js/treeshaking/ssr/serverRender/{type.js → renderToString/type.js} +0 -1
- package/dist/js/treeshaking/ssr/serverRender/types.js +2 -0
- package/dist/js/treeshaking/ssr/serverRender/{measure.js → utils.js} +16 -0
- package/dist/js/treeshaking/ssr/utils.js +15 -3
- package/dist/types/common.d.ts +0 -2
- package/dist/types/core/index.d.ts +1 -1
- package/dist/types/core/plugin.d.ts +1 -1
- package/dist/types/exports/server.d.ts +21 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/router/runtime/DefaultNotFound.d.ts +1 -0
- package/dist/types/router/runtime/index.d.ts +3 -3
- package/dist/types/router/runtime/plugin.d.ts +2 -45
- package/dist/types/router/runtime/plugin.node.d.ts +8 -0
- package/dist/types/router/runtime/types.d.ts +38 -0
- package/dist/types/router/runtime/utils.d.ts +5 -2
- package/dist/types/router/runtime/withRouter.d.ts +8 -0
- package/dist/types/runtime-context.d.ts +2 -1
- package/dist/types/ssr/index.d.ts +2 -2
- package/dist/types/ssr/index.node.d.ts +1 -1
- package/dist/types/ssr/react/nossr/index.d.ts +3 -1
- package/dist/types/ssr/serverRender/index.d.ts +2 -3
- package/dist/types/ssr/serverRender/renderToStream/buildTemplate.after.d.ts +6 -0
- package/dist/types/ssr/serverRender/renderToStream/buildTemplate.share.d.ts +3 -0
- package/dist/types/ssr/serverRender/renderToStream/bulidTemplate.before.d.ts +1 -0
- package/dist/types/ssr/serverRender/renderToStream/index.d.ts +6 -0
- package/dist/types/ssr/serverRender/renderToStream/loadable.d.ts +16 -0
- package/dist/types/ssr/serverRender/renderToStream/renderToPipe.d.ts +8 -0
- package/dist/types/ssr/serverRender/renderToStream/styledComponent.d.ts +12 -0
- package/dist/types/ssr/serverRender/renderToStream/template.d.ts +3 -0
- package/dist/types/ssr/serverRender/renderToStream/type.d.ts +4 -0
- package/dist/types/ssr/serverRender/{entry.d.ts → renderToString/entry.d.ts} +2 -2
- package/dist/types/ssr/serverRender/renderToString/index.d.ts +6 -0
- package/dist/types/ssr/serverRender/{loadable.d.ts → renderToString/loadable.d.ts} +0 -0
- package/dist/types/ssr/serverRender/{reduce.d.ts → renderToString/reduce.d.ts} +0 -0
- package/dist/types/ssr/serverRender/{styledComponent.d.ts → renderToString/styledComponent.d.ts} +0 -0
- package/dist/types/ssr/serverRender/{template.d.ts → renderToString/template.d.ts} +0 -0
- package/dist/types/ssr/serverRender/{type.d.ts → renderToString/type.d.ts} +1 -8
- package/dist/types/ssr/serverRender/types.d.ts +18 -0
- package/dist/types/ssr/serverRender/utils.d.ts +3 -0
- package/dist/types/ssr/utils.d.ts +4 -2
- package/dist/types/state/runtime/plugin.d.ts +1 -1
- package/package.json +57 -73
- package/types/index.d.ts +13 -0
- package/types/router.d.ts +14 -0
- package/dist/js/modern/ssr/serverRender/measure.js +0 -11
- package/dist/js/node/ssr/serverRender/measure.js +0 -20
- package/dist/types/ssr/serverRender/measure.d.ts +0 -1
- package/lib/types.d.ts +0 -10
- 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('@
|
|
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/
|
|
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
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
55
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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,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
|
+
}
|
|
File without changes
|
|
@@ -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 "
|
|
2
|
+
import { isCrossOrigin } from "../../utils";
|
|
3
|
+
import { getLoadableScripts } from "../utils";
|
|
3
4
|
|
|
4
5
|
const extname = uri => {
|
|
5
|
-
|
|
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
|
|
18
|
-
|
|
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 {
|
|
File without changes
|
package/dist/js/modern/ssr/serverRender/{styledComponent.js → renderToString/styledComponent.js}
RENAMED
|
File without changes
|
|
File without changes
|