@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.
Files changed (95) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/cjs/core/compatible.js +16 -17
  3. package/dist/cjs/core/loader/useLoader.js +10 -12
  4. package/dist/cjs/core/plugin.js +3 -2
  5. package/dist/cjs/document/Html.js +4 -3
  6. package/dist/cjs/document/cli/index.js +139 -138
  7. package/dist/cjs/router/cli/index.js +91 -92
  8. package/dist/cjs/router/runtime/DeferredDataScripts.node.js +4 -2
  9. package/dist/cjs/router/runtime/PrefetchLink.js +8 -4
  10. package/dist/cjs/router/runtime/plugin.js +10 -3
  11. package/dist/cjs/router/runtime/plugin.node.js +2 -1
  12. package/dist/cjs/router/runtime/utils.js +3 -3
  13. package/dist/cjs/ssr/cli/index.js +122 -123
  14. package/dist/cjs/ssr/index.js +105 -107
  15. package/dist/cjs/ssr/index.node.js +37 -38
  16. package/dist/cjs/ssr/prefetch.js +37 -39
  17. package/dist/cjs/ssr/react/prerender/util.js +4 -2
  18. package/dist/cjs/ssr/serverRender/constants.js +16 -0
  19. package/dist/cjs/ssr/serverRender/renderToStream/bulidTemplate.before.js +4 -2
  20. package/dist/cjs/ssr/serverRender/renderToStream/index.js +1 -1
  21. package/dist/cjs/ssr/serverRender/renderToStream/renderToPipe.js +8 -7
  22. package/dist/cjs/ssr/serverRender/renderToStream/renderToPipe.worker.js +8 -6
  23. package/dist/cjs/ssr/serverRender/renderToString/entry.js +18 -3
  24. package/dist/cjs/ssr/serverRender/renderToString/index.js +4 -1
  25. package/dist/cjs/ssr/serverRender/renderToString/loadable.js +2 -1
  26. package/dist/cjs/ssr/serverRender/reporter.js +27 -0
  27. package/dist/cjs/state/cli/index.js +70 -72
  28. package/dist/cjs/state/runtime/plugin.js +40 -42
  29. package/dist/esm/core/compatible.js +10 -9
  30. package/dist/esm/core/loader/useLoader.js +9 -9
  31. package/dist/esm/core/plugin.js +3 -2
  32. package/dist/esm/document/Html.js +4 -3
  33. package/dist/esm/document/cli/index.js +5 -3
  34. package/dist/esm/router/cli/index.js +2 -1
  35. package/dist/esm/router/runtime/DeferredDataScripts.node.js +4 -2
  36. package/dist/esm/router/runtime/PrefetchLink.js +8 -4
  37. package/dist/esm/router/runtime/plugin.js +10 -3
  38. package/dist/esm/router/runtime/plugin.node.js +2 -1
  39. package/dist/esm/router/runtime/utils.js +3 -3
  40. package/dist/esm/ssr/cli/index.js +7 -6
  41. package/dist/esm/ssr/index.js +6 -6
  42. package/dist/esm/ssr/index.node.js +2 -1
  43. package/dist/esm/ssr/prefetch.js +2 -2
  44. package/dist/esm/ssr/react/prerender/util.js +4 -2
  45. package/dist/esm/ssr/serverRender/constants.js +6 -0
  46. package/dist/esm/ssr/serverRender/renderToStream/bulidTemplate.before.js +4 -2
  47. package/dist/esm/ssr/serverRender/renderToStream/index.js +1 -1
  48. package/dist/esm/ssr/serverRender/renderToStream/renderToPipe.js +8 -7
  49. package/dist/esm/ssr/serverRender/renderToStream/renderToPipe.worker.js +7 -7
  50. package/dist/esm/ssr/serverRender/renderToString/entry.js +19 -4
  51. package/dist/esm/ssr/serverRender/renderToString/index.js +4 -1
  52. package/dist/esm/ssr/serverRender/renderToString/loadable.js +2 -1
  53. package/dist/esm/ssr/serverRender/reporter.js +17 -0
  54. package/dist/esm/state/runtime/plugin.js +2 -2
  55. package/dist/esm-node/core/compatible.js +16 -17
  56. package/dist/esm-node/core/loader/useLoader.js +10 -12
  57. package/dist/esm-node/core/plugin.js +3 -2
  58. package/dist/esm-node/document/Html.js +4 -3
  59. package/dist/esm-node/document/cli/index.js +139 -138
  60. package/dist/esm-node/router/cli/index.js +91 -92
  61. package/dist/esm-node/router/runtime/DeferredDataScripts.node.js +4 -2
  62. package/dist/esm-node/router/runtime/PrefetchLink.js +8 -4
  63. package/dist/esm-node/router/runtime/plugin.js +10 -3
  64. package/dist/esm-node/router/runtime/plugin.node.js +2 -1
  65. package/dist/esm-node/router/runtime/utils.js +3 -3
  66. package/dist/esm-node/ssr/cli/index.js +122 -123
  67. package/dist/esm-node/ssr/cli/loadable-bundler-plugin.js +2 -2
  68. package/dist/esm-node/ssr/index.js +105 -107
  69. package/dist/esm-node/ssr/index.node.js +37 -38
  70. package/dist/esm-node/ssr/prefetch.js +37 -39
  71. package/dist/esm-node/ssr/react/prerender/util.js +4 -2
  72. package/dist/esm-node/ssr/serverRender/constants.js +6 -0
  73. package/dist/esm-node/ssr/serverRender/renderToStream/bulidTemplate.before.js +4 -2
  74. package/dist/esm-node/ssr/serverRender/renderToStream/index.js +1 -1
  75. package/dist/esm-node/ssr/serverRender/renderToStream/renderToPipe.js +8 -7
  76. package/dist/esm-node/ssr/serverRender/renderToStream/renderToPipe.worker.js +8 -6
  77. package/dist/esm-node/ssr/serverRender/renderToString/entry.js +18 -3
  78. package/dist/esm-node/ssr/serverRender/renderToString/index.js +4 -1
  79. package/dist/esm-node/ssr/serverRender/renderToString/loadable.js +2 -1
  80. package/dist/esm-node/ssr/serverRender/reporter.js +17 -0
  81. package/dist/esm-node/state/cli/index.js +70 -72
  82. package/dist/esm-node/state/runtime/plugin.js +40 -42
  83. package/dist/types/router/runtime/types.d.ts +3 -0
  84. package/dist/types/ssr/serverRender/constants.d.ts +5 -0
  85. package/dist/types/ssr/serverRender/renderToString/entry.d.ts +3 -0
  86. package/dist/types/ssr/serverRender/reporter.d.ts +8 -0
  87. package/package.json +9 -9
  88. package/dist/cjs/ssr/serverRender/time.js +0 -20
  89. package/dist/cjs/ssr/serverRender/time.worker.js +0 -38
  90. package/dist/esm/ssr/serverRender/time.js +0 -11
  91. package/dist/esm/ssr/serverRender/time.worker.js +0 -29
  92. package/dist/esm-node/ssr/serverRender/time.js +0 -10
  93. package/dist/esm-node/ssr/serverRender/time.worker.js +0 -28
  94. package/dist/types/ssr/serverRender/time.d.ts +0 -1
  95. 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
- return run(context.ssrContext.request.headers, async () => {
7
- var _context_store;
8
- const { ssrContext } = context;
9
- const { loadableStats } = ssrContext;
10
- if (loadableStats) {
11
- const extractor = new ChunkExtractor({
12
- stats: loadableStats,
13
- entrypoints: [
14
- ssrContext.entryName
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 || prop === void 0 ? void 0 : prop.hasOwnProperty(key)) && usefulArray(prop[key])) {
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 || prop === void 0 ? void 0 : prop.hasOwnProperty(key)) && usefulObject(prop[key])) {
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 || matches === void 0 ? void 0 : matches.forEach((match, index) => {
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
- return (asset === null || asset === void 0 ? void 0 : asset.endsWith(".css")) && !headTemplate2.includes(asset);
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 || ssrContext === void 0 ? void 0 : ssrContext.nonce,
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 || options === void 0 ? void 0 : (_options_onShellReady = options.onShellReady) === null || _options_onShellReady === void 0 ? void 0 : _options_onShellReady.call(options);
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 || options === void 0 ? void 0 : (_options_onShellError = options.onShellError) === null || _options_onShellError === void 0 ? void 0 : _options_onShellError.call(options, error);
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 || options === void 0 ? void 0 : (_options_onError = options.onError) === null || _options_onError === void 0 ? void 0 : _options_onError.call(options, error);
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 || ssrContext === void 0 ? void 0 : ssrContext.nonce,
24
+ nonce: (_ssrContext = ssrContext) === null || _ssrContext === void 0 ? void 0 : _ssrContext.nonce,
24
25
  onError(error) {
25
- var _options_onError;
26
- ssrContext === null || ssrContext === void 0 ? void 0 : ssrContext.logger.error("An error occurs during streaming SSR", error);
27
- ssrContext === null || ssrContext === void 0 ? void 0 : ssrContext.metrics.emitCounter("app.render.streaming.error", 1);
28
- options === null || options === void 0 ? void 0 : (_options_onError = options.onError) === null || _options_onError === void 0 ? void 0 : _options_onError.call(options, error);
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
- ssrContext === null || ssrContext === void 0 ? void 0 : ssrContext.metrics.emitCounter("app.render.streaming.shell.error", 1);
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 { time } from "../time";
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 || uri === void 0 ? void 0 : uri.split(".").pop()}` || "";
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
- return {
5
- name: "@modern-js/plugin-state",
6
- required: [
7
- "@modern-js/runtime"
8
- ],
9
- setup: (api) => {
10
- const stateConfigMap = /* @__PURE__ */ new Map();
11
- let pluginsExportsUtils;
12
- return {
13
- config() {
14
- const appContext = api.useAppContext();
15
- pluginsExportsUtils = createRuntimeExportsUtils(appContext.internalDirectory, "plugins");
16
- return {
17
- source: {
18
- alias: {
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
- return {
42
- entrypoint,
43
- imports
44
- };
45
- },
46
- modifyEntryRuntimePlugins({ entrypoint, plugins }) {
47
- const stateOptions = stateConfigMap.get(entrypoint.entryName);
48
- if (stateOptions) {
49
- plugins.push({
50
- name: PLUGIN_IDENTIFIER,
51
- options: `${JSON.stringify(stateConfigMap.get(entrypoint.entryName))}`
52
- });
53
- }
54
- return {
55
- entrypoint,
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
- return {
35
- name: "@modern-js/plugin-state",
36
- setup: () => {
37
- const storeConfig = getStoreConfig(config);
38
- return {
39
- hoc({ App }, next) {
40
- const getStateApp = (props) => {
41
- const context = useContext(RuntimeReactContext);
42
- return /* @__PURE__ */ _jsx(Provider, {
43
- store: context.store,
44
- config: storeConfig,
45
- children: /* @__PURE__ */ _jsx(App, {
46
- ...props
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";
@@ -30,6 +30,9 @@ export type RouterConfig = {
30
30
  globalApp?: React.ComponentType<any>;
31
31
  routes: (NestedRoute | PageRoute)[];
32
32
  };
33
+ /**
34
+ * You should not use it
35
+ */
33
36
  oldVersion?: boolean;
34
37
  serverBase?: string[];
35
38
  supportHtml5History?: boolean;
@@ -0,0 +1,5 @@
1
+ export declare enum ServerTimingNames {
2
+ SSR_RENDER_TOTAL = "ssr-render-total",
3
+ SSR_PREFETCH = "ssr-prefetch",
4
+ SSR_RENDER_HTML = "ssr-render-html",
5
+ }
@@ -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
+ };