@modern-js/runtime 2.27.1-alpha.0 → 2.29.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 +34 -0
- package/dist/cjs/core/compatible.js +16 -17
- package/dist/cjs/core/loader/useLoader.js +10 -12
- package/dist/cjs/core/plugin.js +3 -2
- package/dist/cjs/document/Html.js +4 -3
- package/dist/cjs/document/cli/index.js +139 -138
- package/dist/cjs/router/cli/index.js +91 -92
- package/dist/cjs/router/runtime/DeferredDataScripts.node.js +4 -2
- package/dist/cjs/router/runtime/PrefetchLink.js +8 -4
- package/dist/cjs/router/runtime/plugin.js +10 -3
- package/dist/cjs/router/runtime/plugin.node.js +2 -1
- package/dist/cjs/router/runtime/utils.js +3 -3
- package/dist/cjs/ssr/cli/index.js +122 -123
- package/dist/cjs/ssr/index.js +105 -107
- package/dist/cjs/ssr/index.node.js +37 -38
- package/dist/cjs/ssr/prefetch.js +37 -39
- package/dist/cjs/ssr/react/prerender/util.js +4 -2
- package/dist/cjs/ssr/serverRender/constants.js +16 -0
- package/dist/cjs/ssr/serverRender/renderToStream/bulidTemplate.before.js +4 -2
- package/dist/cjs/ssr/serverRender/renderToStream/index.js +1 -1
- package/dist/cjs/ssr/serverRender/renderToStream/renderToPipe.js +8 -7
- package/dist/cjs/ssr/serverRender/renderToStream/renderToPipe.worker.js +8 -6
- package/dist/cjs/ssr/serverRender/renderToString/entry.js +18 -3
- package/dist/cjs/ssr/serverRender/renderToString/index.js +4 -1
- package/dist/cjs/ssr/serverRender/renderToString/loadable.js +2 -1
- package/dist/cjs/ssr/serverRender/reporter.js +27 -0
- package/dist/cjs/state/cli/index.js +70 -72
- package/dist/cjs/state/runtime/plugin.js +40 -42
- package/dist/esm/core/compatible.js +10 -9
- package/dist/esm/core/loader/useLoader.js +9 -9
- package/dist/esm/core/plugin.js +3 -2
- package/dist/esm/document/Html.js +4 -3
- package/dist/esm/document/cli/index.js +5 -3
- package/dist/esm/router/cli/index.js +2 -1
- package/dist/esm/router/runtime/DeferredDataScripts.node.js +4 -2
- package/dist/esm/router/runtime/PrefetchLink.js +8 -4
- package/dist/esm/router/runtime/plugin.js +10 -3
- package/dist/esm/router/runtime/plugin.node.js +2 -1
- package/dist/esm/router/runtime/utils.js +3 -3
- package/dist/esm/ssr/cli/index.js +7 -6
- package/dist/esm/ssr/index.js +6 -6
- package/dist/esm/ssr/index.node.js +2 -1
- package/dist/esm/ssr/prefetch.js +2 -2
- package/dist/esm/ssr/react/prerender/util.js +4 -2
- package/dist/esm/ssr/serverRender/constants.js +6 -0
- package/dist/esm/ssr/serverRender/renderToStream/bulidTemplate.before.js +4 -2
- package/dist/esm/ssr/serverRender/renderToStream/index.js +1 -1
- package/dist/esm/ssr/serverRender/renderToStream/renderToPipe.js +8 -7
- package/dist/esm/ssr/serverRender/renderToStream/renderToPipe.worker.js +7 -7
- package/dist/esm/ssr/serverRender/renderToString/entry.js +19 -4
- package/dist/esm/ssr/serverRender/renderToString/index.js +4 -1
- package/dist/esm/ssr/serverRender/renderToString/loadable.js +2 -1
- package/dist/esm/ssr/serverRender/reporter.js +17 -0
- package/dist/esm/state/runtime/plugin.js +2 -2
- package/dist/esm-node/core/compatible.js +16 -17
- package/dist/esm-node/core/loader/useLoader.js +10 -12
- package/dist/esm-node/core/plugin.js +3 -2
- package/dist/esm-node/document/Html.js +4 -3
- package/dist/esm-node/document/cli/index.js +139 -138
- package/dist/esm-node/router/cli/index.js +91 -92
- package/dist/esm-node/router/runtime/DeferredDataScripts.node.js +4 -2
- package/dist/esm-node/router/runtime/PrefetchLink.js +8 -4
- package/dist/esm-node/router/runtime/plugin.js +10 -3
- package/dist/esm-node/router/runtime/plugin.node.js +2 -1
- package/dist/esm-node/router/runtime/utils.js +3 -3
- package/dist/esm-node/ssr/cli/index.js +122 -123
- package/dist/esm-node/ssr/cli/loadable-bundler-plugin.js +2 -2
- package/dist/esm-node/ssr/index.js +105 -107
- package/dist/esm-node/ssr/index.node.js +37 -38
- package/dist/esm-node/ssr/prefetch.js +37 -39
- package/dist/esm-node/ssr/react/prerender/util.js +4 -2
- package/dist/esm-node/ssr/serverRender/constants.js +6 -0
- package/dist/esm-node/ssr/serverRender/renderToStream/bulidTemplate.before.js +4 -2
- package/dist/esm-node/ssr/serverRender/renderToStream/index.js +1 -1
- package/dist/esm-node/ssr/serverRender/renderToStream/renderToPipe.js +8 -7
- package/dist/esm-node/ssr/serverRender/renderToStream/renderToPipe.worker.js +8 -6
- package/dist/esm-node/ssr/serverRender/renderToString/entry.js +18 -3
- package/dist/esm-node/ssr/serverRender/renderToString/index.js +4 -1
- package/dist/esm-node/ssr/serverRender/renderToString/loadable.js +2 -1
- package/dist/esm-node/ssr/serverRender/reporter.js +17 -0
- package/dist/esm-node/state/cli/index.js +70 -72
- package/dist/esm-node/state/runtime/plugin.js +40 -42
- package/dist/types/router/runtime/types.d.ts +3 -0
- package/dist/types/ssr/serverRender/constants.d.ts +5 -0
- package/dist/types/ssr/serverRender/renderToString/entry.d.ts +3 -0
- package/dist/types/ssr/serverRender/reporter.d.ts +8 -0
- package/package.json +9 -9
- package/dist/cjs/ssr/serverRender/time.js +0 -20
- package/dist/cjs/ssr/serverRender/time.worker.js +0 -38
- package/dist/esm/ssr/serverRender/time.js +0 -11
- package/dist/esm/ssr/serverRender/time.worker.js +0 -29
- package/dist/esm-node/ssr/serverRender/time.js +0 -10
- package/dist/esm-node/ssr/serverRender/time.worker.js +0 -28
- package/dist/types/ssr/serverRender/time.d.ts +0 -1
- package/dist/types/ssr/serverRender/time.worker.d.ts +0 -1
|
@@ -2,48 +2,46 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { renderToStaticMarkup } from "react-dom/server";
|
|
3
3
|
import { run } from "@modern-js/utils/runtime-node";
|
|
4
4
|
import { ChunkExtractor } from "@loadable/server";
|
|
5
|
-
const prefetch = async (App, context) => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
].filter(Boolean)
|
|
16
|
-
});
|
|
17
|
-
renderToStaticMarkup(extractor.collectChunks(/* @__PURE__ */ _jsx(App, {
|
|
18
|
-
context
|
|
19
|
-
})));
|
|
20
|
-
} else {
|
|
21
|
-
renderToStaticMarkup(/* @__PURE__ */ _jsx(App, {
|
|
22
|
-
context
|
|
23
|
-
}));
|
|
24
|
-
}
|
|
25
|
-
if (!context.loaderManager.hasPendingLoaders()) {
|
|
26
|
-
return {
|
|
27
|
-
initialData: context.initialData,
|
|
28
|
-
i18nData: context.__i18nData__
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
const loadersData = await context.loaderManager.awaitPendingLoaders();
|
|
32
|
-
Object.keys(loadersData).forEach((id) => {
|
|
33
|
-
const data = loadersData[id];
|
|
34
|
-
if (data._error) {
|
|
35
|
-
ssrContext.logger.error("App Prefetch Loader", data._error);
|
|
36
|
-
ssrContext.metrics.emitCounter("app.prefetch.loader.error", 1);
|
|
37
|
-
delete data._error;
|
|
38
|
-
}
|
|
5
|
+
const prefetch = async (App, context) => run(context.ssrContext.request.headers, async () => {
|
|
6
|
+
var _context_store, _context;
|
|
7
|
+
const { ssrContext } = context;
|
|
8
|
+
const { loadableStats } = ssrContext;
|
|
9
|
+
if (loadableStats) {
|
|
10
|
+
const extractor = new ChunkExtractor({
|
|
11
|
+
stats: loadableStats,
|
|
12
|
+
entrypoints: [
|
|
13
|
+
ssrContext.entryName
|
|
14
|
+
].filter(Boolean)
|
|
39
15
|
});
|
|
16
|
+
renderToStaticMarkup(extractor.collectChunks(/* @__PURE__ */ _jsx(App, {
|
|
17
|
+
context
|
|
18
|
+
})));
|
|
19
|
+
} else {
|
|
20
|
+
renderToStaticMarkup(/* @__PURE__ */ _jsx(App, {
|
|
21
|
+
context
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
if (!context.loaderManager.hasPendingLoaders()) {
|
|
40
25
|
return {
|
|
41
|
-
loadersData,
|
|
42
26
|
initialData: context.initialData,
|
|
43
|
-
i18nData: context.__i18nData__
|
|
44
|
-
// todo: move to plugin state
|
|
45
|
-
storeState: context === null || context === void 0 ? void 0 : (_context_store = context.store) === null || _context_store === void 0 ? void 0 : _context_store.getState()
|
|
27
|
+
i18nData: context.__i18nData__
|
|
46
28
|
};
|
|
29
|
+
}
|
|
30
|
+
const loadersData = await context.loaderManager.awaitPendingLoaders();
|
|
31
|
+
Object.keys(loadersData).forEach((id) => {
|
|
32
|
+
const data = loadersData[id];
|
|
33
|
+
if (data._error) {
|
|
34
|
+
ssrContext.logger.error("App Prefetch Loader", data._error);
|
|
35
|
+
ssrContext.metrics.emitCounter("app.prefetch.loader.error", 1);
|
|
36
|
+
delete data._error;
|
|
37
|
+
}
|
|
47
38
|
});
|
|
48
|
-
|
|
39
|
+
return {
|
|
40
|
+
loadersData,
|
|
41
|
+
initialData: context.initialData,
|
|
42
|
+
i18nData: context.__i18nData__,
|
|
43
|
+
// todo: move to plugin state
|
|
44
|
+
storeState: (_context = context) === null || _context === void 0 ? void 0 : (_context_store = _context.store) === null || _context_store === void 0 ? void 0 : _context_store.getState()
|
|
45
|
+
};
|
|
46
|
+
});
|
|
49
47
|
export default prefetch;
|
|
@@ -27,8 +27,9 @@ export const aggKeysFromPropsList = function aggKeysFromPropsList2(propsList, pr
|
|
|
27
27
|
}, {});
|
|
28
28
|
const res = propsList.filter((props) => usefulObject(props[propName])).reduce((result, next) => {
|
|
29
29
|
REQUEST_META.forEach((key) => {
|
|
30
|
+
var _prop;
|
|
30
31
|
const prop = next[propName];
|
|
31
|
-
if ((prop === null ||
|
|
32
|
+
if (((_prop = prop) === null || _prop === void 0 ? void 0 : _prop.hasOwnProperty(key)) && usefulArray(prop[key])) {
|
|
32
33
|
result[key] = unique(result[key].concat(prop[key]));
|
|
33
34
|
}
|
|
34
35
|
});
|
|
@@ -51,8 +52,9 @@ export const aggMatchesFromPropsList = function aggMatchesFromPropsList2(propsLi
|
|
|
51
52
|
}, {});
|
|
52
53
|
const res = propsList.filter((props) => usefulObject(props[propName])).reduce((result, next) => {
|
|
53
54
|
REQUEST_META.forEach((key) => {
|
|
55
|
+
var _prop;
|
|
54
56
|
const prop = next[propName];
|
|
55
|
-
if ((prop === null ||
|
|
57
|
+
if (((_prop = prop) === null || _prop === void 0 ? void 0 : _prop.hasOwnProperty(key)) && usefulObject(prop[key])) {
|
|
56
58
|
result[key] = Object.assign(result[key], prop[key]);
|
|
57
59
|
}
|
|
58
60
|
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export var ServerTimingNames;
|
|
2
|
+
(function(ServerTimingNames2) {
|
|
3
|
+
ServerTimingNames2["SSR_RENDER_TOTAL"] = "ssr-render-total";
|
|
4
|
+
ServerTimingNames2["SSR_PREFETCH"] = "ssr-prefetch";
|
|
5
|
+
ServerTimingNames2["SSR_RENDER_HTML"] = "ssr-render-html";
|
|
6
|
+
})(ServerTimingNames || (ServerTimingNames = {}));
|
|
@@ -20,6 +20,7 @@ function getHeadTemplate(beforeEntryTemplate, context) {
|
|
|
20
20
|
function injectCss(headTemplate2) {
|
|
21
21
|
return headTemplate2.replace(CSS_CHUNKS_PLACEHOLDER, getCssChunks());
|
|
22
22
|
function getCssChunks() {
|
|
23
|
+
var _matches;
|
|
23
24
|
const { routeManifest, routerContext, routes } = context;
|
|
24
25
|
if (!routeManifest || !routerContext || !routes) {
|
|
25
26
|
return "";
|
|
@@ -27,7 +28,7 @@ function getHeadTemplate(beforeEntryTemplate, context) {
|
|
|
27
28
|
const { routeAssets } = routeManifest;
|
|
28
29
|
const cssChunks = [];
|
|
29
30
|
const matches = matchRoutes(routes, routerContext.location, routerContext.basename);
|
|
30
|
-
matches === null ||
|
|
31
|
+
(_matches = matches) === null || _matches === void 0 ? void 0 : _matches.forEach((match, index) => {
|
|
31
32
|
if (!index) {
|
|
32
33
|
return;
|
|
33
34
|
}
|
|
@@ -37,7 +38,8 @@ function getHeadTemplate(beforeEntryTemplate, context) {
|
|
|
37
38
|
if (routeManifest2) {
|
|
38
39
|
const { referenceCssAssets = [] } = routeManifest2;
|
|
39
40
|
const _cssChunks = referenceCssAssets.filter((asset) => {
|
|
40
|
-
|
|
41
|
+
var _asset;
|
|
42
|
+
return ((_asset = asset) === null || _asset === void 0 ? void 0 : _asset.endsWith(".css")) && !headTemplate2.includes(asset);
|
|
41
43
|
});
|
|
42
44
|
cssChunks.push(..._cssChunks);
|
|
43
45
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createElement } from "react";
|
|
2
2
|
import { run } from "@modern-js/utils/runtime-node";
|
|
3
|
+
import { time } from "@modern-js/utils/universal/time";
|
|
3
4
|
import { PreRender } from "../../react/prerender";
|
|
4
|
-
import { time } from "../time";
|
|
5
5
|
import renderToPipe from "./renderToPipe";
|
|
6
6
|
export const render = ({ App, context }) => {
|
|
7
7
|
const { ssrContext } = context;
|
|
@@ -13,6 +13,7 @@ function renderToPipe(rootElement, context, options) {
|
|
|
13
13
|
const chunkVec = [];
|
|
14
14
|
const forUserPipe = (stream) => {
|
|
15
15
|
return new Promise((resolve) => {
|
|
16
|
+
var _ssrContext;
|
|
16
17
|
let renderToPipeableStream;
|
|
17
18
|
try {
|
|
18
19
|
({ renderToPipeableStream } = require("react-dom/server"));
|
|
@@ -20,11 +21,11 @@ function renderToPipe(rootElement, context, options) {
|
|
|
20
21
|
}
|
|
21
22
|
const { pipe } = renderToPipeableStream(rootElement, {
|
|
22
23
|
...options,
|
|
23
|
-
nonce: ssrContext === null ||
|
|
24
|
+
nonce: (_ssrContext = ssrContext) === null || _ssrContext === void 0 ? void 0 : _ssrContext.nonce,
|
|
24
25
|
onShellReady() {
|
|
25
|
-
var _options_onShellReady;
|
|
26
|
+
var _options_onShellReady, _options;
|
|
26
27
|
const { shellAfter, shellBefore } = getTemplates(context, RenderLevel.SERVER_RENDER);
|
|
27
|
-
options === null ||
|
|
28
|
+
(_options = options) === null || _options === void 0 ? void 0 : (_options_onShellReady = _options.onShellReady) === null || _options_onShellReady === void 0 ? void 0 : _options_onShellReady.call(_options);
|
|
28
29
|
const injectableTransform = new Transform({
|
|
29
30
|
transform(chunk, _encoding, callback) {
|
|
30
31
|
try {
|
|
@@ -52,18 +53,18 @@ function renderToPipe(rootElement, context, options) {
|
|
|
52
53
|
resolve(pipe(injectableTransform).pipe(stream));
|
|
53
54
|
},
|
|
54
55
|
onShellError(error) {
|
|
55
|
-
var _options_onShellError;
|
|
56
|
+
var _options_onShellError, _options;
|
|
56
57
|
ssrContext.metrics.emitCounter("app.render.streaming.shell.error", 1);
|
|
57
58
|
const { shellAfter, shellBefore } = getTemplates(context, RenderLevel.CLIENT_RENDER);
|
|
58
59
|
const fallbackHtml = `${shellBefore}${shellAfter}`;
|
|
59
60
|
resolve(fallbackHtml);
|
|
60
|
-
options === null ||
|
|
61
|
+
(_options = options) === null || _options === void 0 ? void 0 : (_options_onShellError = _options.onShellError) === null || _options_onShellError === void 0 ? void 0 : _options_onShellError.call(_options, error);
|
|
61
62
|
},
|
|
62
63
|
onError(error) {
|
|
63
|
-
var _options_onError;
|
|
64
|
+
var _options_onError, _options;
|
|
64
65
|
ssrContext.logger.error("An error occurs during streaming SSR", error);
|
|
65
66
|
ssrContext.metrics.emitCounter("app.render.streaming.error", 1);
|
|
66
|
-
options === null ||
|
|
67
|
+
(_options = options) === null || _options === void 0 ? void 0 : (_options_onError = _options.onError) === null || _options_onError === void 0 ? void 0 : _options_onError.call(_options, error);
|
|
67
68
|
}
|
|
68
69
|
});
|
|
69
70
|
});
|
|
@@ -18,14 +18,15 @@ function renderToPipe(rootElement, context, options) {
|
|
|
18
18
|
}
|
|
19
19
|
const { shellAfter, shellBefore } = getTemplates(context, RenderLevel.SERVER_RENDER);
|
|
20
20
|
try {
|
|
21
|
+
var _ssrContext;
|
|
21
22
|
const readableOriginal = await renderToReadableStream(rootElement, {
|
|
22
23
|
...options,
|
|
23
|
-
nonce: ssrContext === null ||
|
|
24
|
+
nonce: (_ssrContext = ssrContext) === null || _ssrContext === void 0 ? void 0 : _ssrContext.nonce,
|
|
24
25
|
onError(error) {
|
|
25
|
-
var _options_onError;
|
|
26
|
-
ssrContext === null ||
|
|
27
|
-
ssrContext === null ||
|
|
28
|
-
options === null ||
|
|
26
|
+
var _ssrContext2, _ssrContext12, _options_onError, _options;
|
|
27
|
+
(_ssrContext2 = ssrContext) === null || _ssrContext2 === void 0 ? void 0 : _ssrContext2.logger.error("An error occurs during streaming SSR", error);
|
|
28
|
+
(_ssrContext12 = ssrContext) === null || _ssrContext12 === void 0 ? void 0 : _ssrContext12.metrics.emitCounter("app.render.streaming.error", 1);
|
|
29
|
+
(_options = options) === null || _options === void 0 ? void 0 : (_options_onError = _options.onError) === null || _options_onError === void 0 ? void 0 : _options_onError.call(_options, error);
|
|
29
30
|
}
|
|
30
31
|
});
|
|
31
32
|
const reader = readableOriginal.getReader();
|
|
@@ -56,7 +57,8 @@ function renderToPipe(rootElement, context, options) {
|
|
|
56
57
|
});
|
|
57
58
|
return injectableStream;
|
|
58
59
|
} catch (err) {
|
|
59
|
-
|
|
60
|
+
var _ssrContext1;
|
|
61
|
+
(_ssrContext1 = ssrContext) === null || _ssrContext1 === void 0 ? void 0 : _ssrContext1.metrics.emitCounter("app.render.streaming.shell.error", 1);
|
|
60
62
|
const { shellAfter: shellAfter2, shellBefore: shellBefore2 } = getTemplates(context, RenderLevel.CLIENT_RENDER);
|
|
61
63
|
const fallbackHtml = `${shellBefore2}${shellAfter2}`;
|
|
62
64
|
return fallbackHtml;
|
|
@@ -3,17 +3,19 @@ import React from "react";
|
|
|
3
3
|
import ReactDomServer from "react-dom/server";
|
|
4
4
|
import { serializeJson } from "@modern-js/utils/runtime-node";
|
|
5
5
|
import ReactHelmet from "react-helmet";
|
|
6
|
+
import { time } from "@modern-js/utils/universal/time";
|
|
6
7
|
import { serializeErrors } from "../../../router/runtime/utils";
|
|
7
8
|
import helmetReplace from "../helmet";
|
|
8
9
|
import { RenderLevel } from "../types";
|
|
9
|
-
import { time } from "../time";
|
|
10
10
|
import prefetch from "../../prefetch";
|
|
11
11
|
import { ROUTER_DATA_JSON_ID, SSR_DATA_JSON_ID, attributesToString } from "../utils";
|
|
12
|
+
import { createSSRReporter } from "../reporter";
|
|
13
|
+
import { ServerTimingNames } from "../constants";
|
|
12
14
|
import { toFragments } from "./template";
|
|
13
15
|
import { reduce } from "./reduce";
|
|
14
16
|
import * as loadableRenderer from "./loadable";
|
|
15
17
|
import * as styledComponentRenderer from "./styledComponent";
|
|
16
|
-
const buildTemplateData = (context, data, renderLevel) => {
|
|
18
|
+
const buildTemplateData = (context, data, renderLevel, reporter) => {
|
|
17
19
|
const { request, enableUnsafeCtx } = context;
|
|
18
20
|
const unsafeContext = {
|
|
19
21
|
headers: request.headers
|
|
@@ -28,6 +30,9 @@ const buildTemplateData = (context, data, renderLevel) => {
|
|
|
28
30
|
host: request.host,
|
|
29
31
|
url: request.url,
|
|
30
32
|
...enableUnsafeCtx ? unsafeContext : {}
|
|
33
|
+
},
|
|
34
|
+
reporter: {
|
|
35
|
+
sessionId: reporter.sessionId
|
|
31
36
|
}
|
|
32
37
|
},
|
|
33
38
|
renderLevel
|
|
@@ -56,7 +61,7 @@ class Entry {
|
|
|
56
61
|
errors: serializeErrors(routerContext.errors)
|
|
57
62
|
} : void 0;
|
|
58
63
|
let html = "";
|
|
59
|
-
const templateData = buildTemplateData(ssrContext, prefetchData, this.result.renderLevel);
|
|
64
|
+
const templateData = buildTemplateData(ssrContext, prefetchData, this.result.renderLevel, this.reporter);
|
|
60
65
|
const SSRData = this.getSSRDataScript(templateData, routerData);
|
|
61
66
|
for (const fragment of this.fragments) {
|
|
62
67
|
if (fragment.isVariable && fragment.content === "SSRDataScript") {
|
|
@@ -77,9 +82,12 @@ class Entry {
|
|
|
77
82
|
const prefetchCost = end();
|
|
78
83
|
this.logger.debug(`App Prefetch cost = %d ms`, prefetchCost);
|
|
79
84
|
this.metrics.emitTimer("app.prefetch.cost", prefetchCost);
|
|
85
|
+
this.reporter.reportTime("app_prefetch_cost", prefetchCost);
|
|
86
|
+
this.severTiming.addServeTiming(ServerTimingNames.SSR_PREFETCH, prefetchCost);
|
|
80
87
|
} catch (e) {
|
|
81
88
|
this.result.renderLevel = RenderLevel.CLIENT_RENDER;
|
|
82
89
|
this.logger.error("App Prefetch Render", e);
|
|
90
|
+
this.reporter.reportError("App Prefetch Render", e);
|
|
83
91
|
this.metrics.emitCounter("app.prefetch.render.error", 1);
|
|
84
92
|
}
|
|
85
93
|
return prefetchData || {};
|
|
@@ -111,9 +119,12 @@ class Entry {
|
|
|
111
119
|
const cost = end();
|
|
112
120
|
this.logger.debug("App Render To HTML cost = %d ms", cost);
|
|
113
121
|
this.metrics.emitTimer("app.render.html.cost", cost);
|
|
122
|
+
this.reporter.reportTime("app_render_html_cost", cost);
|
|
123
|
+
this.severTiming.addServeTiming(ServerTimingNames.SSR_RENDER_HTML, cost);
|
|
114
124
|
this.result.renderLevel = RenderLevel.SERVER_RENDER;
|
|
115
125
|
} catch (e) {
|
|
116
126
|
this.logger.error("App Render To HTML", e);
|
|
127
|
+
this.reporter.reportError("App Render To HTML", e);
|
|
117
128
|
this.metrics.emitCounter("app.render.html.error", 1);
|
|
118
129
|
}
|
|
119
130
|
return html;
|
|
@@ -140,6 +151,8 @@ class Entry {
|
|
|
140
151
|
_define_property(this, "result", void 0);
|
|
141
152
|
_define_property(this, "metrics", void 0);
|
|
142
153
|
_define_property(this, "logger", void 0);
|
|
154
|
+
_define_property(this, "severTiming", void 0);
|
|
155
|
+
_define_property(this, "reporter", void 0);
|
|
143
156
|
_define_property(this, "template", void 0);
|
|
144
157
|
_define_property(this, "App", void 0);
|
|
145
158
|
_define_property(this, "fragments", void 0);
|
|
@@ -154,6 +167,8 @@ class Entry {
|
|
|
154
167
|
this.host = host;
|
|
155
168
|
this.App = options.App;
|
|
156
169
|
this.pluginConfig = config;
|
|
170
|
+
this.reporter = createSSRReporter(ctx.reporter);
|
|
171
|
+
this.severTiming = ctx.serverTiming;
|
|
157
172
|
this.metrics = ctx.metrics;
|
|
158
173
|
this.logger = ctx.logger;
|
|
159
174
|
this.nonce = nonce;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { run } from "@modern-js/utils/runtime-node";
|
|
2
|
+
import { time } from "@modern-js/utils/universal/time";
|
|
2
3
|
import { PreRender } from "../../react/prerender";
|
|
3
|
-
import {
|
|
4
|
+
import { ServerTimingNames } from "../constants";
|
|
4
5
|
import SSREntry from "./entry";
|
|
5
6
|
export const render = ({ App, context, config }) => {
|
|
6
7
|
const ssrContext = context.ssrContext;
|
|
@@ -16,6 +17,8 @@ export const render = ({ App, context, config }) => {
|
|
|
16
17
|
const cost = end();
|
|
17
18
|
entry.logger.info("App Render Total cost = %d ms", cost);
|
|
18
19
|
entry.metrics.emitTimer("app.render.cost", cost);
|
|
20
|
+
entry.reporter.reportTime("app_render_cost", cost);
|
|
21
|
+
entry.severTiming.addServeTiming(ServerTimingNames.SSR_RENDER_TOTAL, cost);
|
|
19
22
|
const cacheConfig = PreRender.config();
|
|
20
23
|
if (cacheConfig) {
|
|
21
24
|
context.ssrContext.cacheConfig = cacheConfig;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { ChunkExtractor } from "@loadable/server";
|
|
2
2
|
import { attributesToString, getLoadableScripts } from "../utils";
|
|
3
3
|
const extname = (uri) => {
|
|
4
|
+
var _uri;
|
|
4
5
|
if (typeof uri !== "string" || !uri.includes(".")) {
|
|
5
6
|
return "";
|
|
6
7
|
}
|
|
7
|
-
return `.${uri === null ||
|
|
8
|
+
return `.${(_uri = uri) === null || _uri === void 0 ? void 0 : _uri.split(".").pop()}` || "";
|
|
8
9
|
};
|
|
9
10
|
export const toHtml = (jsx, renderer, next) => {
|
|
10
11
|
const { stats, result: { chunksMap }, config = {}, nonce } = renderer;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function createSSRReporter(reporter) {
|
|
2
|
+
const _reporter = {
|
|
3
|
+
get sessionId() {
|
|
4
|
+
return reporter.sessionId;
|
|
5
|
+
},
|
|
6
|
+
get userId() {
|
|
7
|
+
return reporter.userId;
|
|
8
|
+
},
|
|
9
|
+
reportError(content, e) {
|
|
10
|
+
reporter.reportError(`SSR Error - ${content}`, e);
|
|
11
|
+
},
|
|
12
|
+
reportTime(name, cost) {
|
|
13
|
+
reporter.reportTiming(`ssr_${name}`, cost);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
return _reporter;
|
|
17
|
+
}
|
|
@@ -1,79 +1,77 @@
|
|
|
1
1
|
import { getEntryOptions, createRuntimeExportsUtils } from "@modern-js/utils";
|
|
2
2
|
const PLUGIN_IDENTIFIER = "state";
|
|
3
|
-
export const statePlugin = () => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"@modern-js/runtime/plugins": pluginsExportsUtils.getPath()
|
|
20
|
-
}
|
|
3
|
+
export const statePlugin = () => ({
|
|
4
|
+
name: "@modern-js/plugin-state",
|
|
5
|
+
required: [
|
|
6
|
+
"@modern-js/runtime"
|
|
7
|
+
],
|
|
8
|
+
setup: (api) => {
|
|
9
|
+
const stateConfigMap = /* @__PURE__ */ new Map();
|
|
10
|
+
let pluginsExportsUtils;
|
|
11
|
+
return {
|
|
12
|
+
config() {
|
|
13
|
+
const appContext = api.useAppContext();
|
|
14
|
+
pluginsExportsUtils = createRuntimeExportsUtils(appContext.internalDirectory, "plugins");
|
|
15
|
+
return {
|
|
16
|
+
source: {
|
|
17
|
+
alias: {
|
|
18
|
+
"@modern-js/runtime/plugins": pluginsExportsUtils.getPath()
|
|
21
19
|
}
|
|
22
|
-
};
|
|
23
|
-
},
|
|
24
|
-
modifyEntryImports({ entrypoint, imports }) {
|
|
25
|
-
var _getEntryOptions;
|
|
26
|
-
const { entryName, isMainEntry } = entrypoint;
|
|
27
|
-
const userConfig = api.useResolvedConfigContext();
|
|
28
|
-
const { packageName } = api.useAppContext();
|
|
29
|
-
const stateConfig = (_getEntryOptions = getEntryOptions(entryName, isMainEntry, userConfig.runtime, userConfig.runtimeByEntries, packageName)) === null || _getEntryOptions === void 0 ? void 0 : _getEntryOptions.state;
|
|
30
|
-
stateConfigMap.set(entryName, stateConfig);
|
|
31
|
-
if (stateConfig) {
|
|
32
|
-
imports.push({
|
|
33
|
-
value: "@modern-js/runtime/plugins",
|
|
34
|
-
specifiers: [
|
|
35
|
-
{
|
|
36
|
-
imported: PLUGIN_IDENTIFIER
|
|
37
|
-
}
|
|
38
|
-
]
|
|
39
|
-
});
|
|
40
20
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
plugins
|
|
57
|
-
};
|
|
58
|
-
},
|
|
59
|
-
validateSchema() {
|
|
60
|
-
return [
|
|
61
|
-
{
|
|
62
|
-
target: "runtime.state",
|
|
63
|
-
schema: {
|
|
64
|
-
type: [
|
|
65
|
-
"boolean",
|
|
66
|
-
"object"
|
|
67
|
-
]
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
modifyEntryImports({ entrypoint, imports }) {
|
|
24
|
+
var _getEntryOptions;
|
|
25
|
+
const { entryName, isMainEntry } = entrypoint;
|
|
26
|
+
const userConfig = api.useResolvedConfigContext();
|
|
27
|
+
const { packageName } = api.useAppContext();
|
|
28
|
+
const stateConfig = (_getEntryOptions = getEntryOptions(entryName, isMainEntry, userConfig.runtime, userConfig.runtimeByEntries, packageName)) === null || _getEntryOptions === void 0 ? void 0 : _getEntryOptions.state;
|
|
29
|
+
stateConfigMap.set(entryName, stateConfig);
|
|
30
|
+
if (stateConfig) {
|
|
31
|
+
imports.push({
|
|
32
|
+
value: "@modern-js/runtime/plugins",
|
|
33
|
+
specifiers: [
|
|
34
|
+
{
|
|
35
|
+
imported: PLUGIN_IDENTIFIER
|
|
68
36
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
},
|
|
72
|
-
addRuntimeExports() {
|
|
73
|
-
pluginsExportsUtils.addExport(`export { default as state } from '@modern-js/runtime/model'`);
|
|
37
|
+
]
|
|
38
|
+
});
|
|
74
39
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
};
|
|
40
|
+
return {
|
|
41
|
+
entrypoint,
|
|
42
|
+
imports
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
modifyEntryRuntimePlugins({ entrypoint, plugins }) {
|
|
46
|
+
const stateOptions = stateConfigMap.get(entrypoint.entryName);
|
|
47
|
+
if (stateOptions) {
|
|
48
|
+
plugins.push({
|
|
49
|
+
name: PLUGIN_IDENTIFIER,
|
|
50
|
+
options: `${JSON.stringify(stateConfigMap.get(entrypoint.entryName))}`
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
entrypoint,
|
|
55
|
+
plugins
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
validateSchema() {
|
|
59
|
+
return [
|
|
60
|
+
{
|
|
61
|
+
target: "runtime.state",
|
|
62
|
+
schema: {
|
|
63
|
+
type: [
|
|
64
|
+
"boolean",
|
|
65
|
+
"object"
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
];
|
|
70
|
+
},
|
|
71
|
+
addRuntimeExports() {
|
|
72
|
+
pluginsExportsUtils.addExport(`export { default as state } from '@modern-js/runtime/model'`);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
});
|
|
79
77
|
export default statePlugin;
|
|
@@ -30,49 +30,47 @@ const getStoreConfig = (config) => {
|
|
|
30
30
|
storeConfig.plugins = plugins;
|
|
31
31
|
return storeConfig;
|
|
32
32
|
};
|
|
33
|
-
const state = (config) => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
})
|
|
48
|
-
});
|
|
49
|
-
};
|
|
50
|
-
return next({
|
|
51
|
-
App: hoistNonReactStatics(getStateApp, App)
|
|
52
|
-
});
|
|
53
|
-
},
|
|
54
|
-
init({ context }, next) {
|
|
55
|
-
if (isBrowser()) {
|
|
56
|
-
var _window__SSR_DATA, _window__SSR_DATA_data;
|
|
57
|
-
storeConfig.initialState = storeConfig.initialState || (window === null || window === void 0 ? void 0 : (_window__SSR_DATA = window._SSR_DATA) === null || _window__SSR_DATA === void 0 ? void 0 : (_window__SSR_DATA_data = _window__SSR_DATA.data) === null || _window__SSR_DATA_data === void 0 ? void 0 : _window__SSR_DATA_data.storeState) || {};
|
|
58
|
-
}
|
|
59
|
-
context.store = createStore(storeConfig);
|
|
60
|
-
return next({
|
|
61
|
-
context
|
|
62
|
-
});
|
|
63
|
-
},
|
|
64
|
-
pickContext({ context, pickedContext }, next) {
|
|
65
|
-
return next({
|
|
66
|
-
context,
|
|
67
|
-
pickedContext: {
|
|
68
|
-
...pickedContext,
|
|
69
|
-
store: context.store
|
|
70
|
-
}
|
|
33
|
+
const state = (config) => ({
|
|
34
|
+
name: "@modern-js/plugin-state",
|
|
35
|
+
setup: () => {
|
|
36
|
+
const storeConfig = getStoreConfig(config);
|
|
37
|
+
return {
|
|
38
|
+
hoc({ App }, next) {
|
|
39
|
+
const getStateApp = (props) => {
|
|
40
|
+
const context = useContext(RuntimeReactContext);
|
|
41
|
+
return /* @__PURE__ */ _jsx(Provider, {
|
|
42
|
+
store: context.store,
|
|
43
|
+
config: storeConfig,
|
|
44
|
+
children: /* @__PURE__ */ _jsx(App, {
|
|
45
|
+
...props
|
|
46
|
+
})
|
|
71
47
|
});
|
|
48
|
+
};
|
|
49
|
+
return next({
|
|
50
|
+
App: hoistNonReactStatics(getStateApp, App)
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
init({ context }, next) {
|
|
54
|
+
if (isBrowser()) {
|
|
55
|
+
var _window__SSR_DATA_data, _window__SSR_DATA, _window;
|
|
56
|
+
storeConfig.initialState = storeConfig.initialState || ((_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_data = _window__SSR_DATA.data) === null || _window__SSR_DATA_data === void 0 ? void 0 : _window__SSR_DATA_data.storeState) || {};
|
|
72
57
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
};
|
|
58
|
+
context.store = createStore(storeConfig);
|
|
59
|
+
return next({
|
|
60
|
+
context
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
pickContext({ context, pickedContext }, next) {
|
|
64
|
+
return next({
|
|
65
|
+
context,
|
|
66
|
+
pickedContext: {
|
|
67
|
+
...pickedContext,
|
|
68
|
+
store: context.store
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
});
|
|
77
75
|
export default state;
|
|
78
76
|
export * from "../plugins";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RuntimeContext, ModernSSRReactComponent, SSRPluginConfig } from '../types';
|
|
2
|
+
import { SSRReporter } from '../reporter';
|
|
2
3
|
import { SSRServerContext, RenderResult } from './type';
|
|
3
4
|
type EntryOptions = {
|
|
4
5
|
ctx: SSRServerContext;
|
|
@@ -10,6 +11,8 @@ export default class Entry {
|
|
|
10
11
|
result: RenderResult;
|
|
11
12
|
metrics: SSRServerContext['metrics'];
|
|
12
13
|
logger: SSRServerContext['logger'];
|
|
14
|
+
severTiming: SSRServerContext['serverTiming'];
|
|
15
|
+
reporter: SSRReporter;
|
|
13
16
|
private readonly template;
|
|
14
17
|
private readonly App;
|
|
15
18
|
private readonly fragments;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SSRServerContext } from './types';
|
|
2
|
+
export type SSRReporter = ReturnType<typeof createSSRReporter>;
|
|
3
|
+
export declare function createSSRReporter(reporter: SSRServerContext['reporter']): {
|
|
4
|
+
readonly sessionId: string | undefined;
|
|
5
|
+
readonly userId: string | undefined;
|
|
6
|
+
reportError(content: string, e: Error): void;
|
|
7
|
+
reportTime(name: string, cost: number): void;
|
|
8
|
+
};
|