@modern-js/runtime 2.29.0 → 2.31.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 (37) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/cjs/document/Body.js +1 -0
  3. package/dist/cjs/document/Head.js +2 -0
  4. package/dist/cjs/document/cli/index.js +8 -1
  5. package/dist/cjs/document/constants.js +12 -5
  6. package/dist/cjs/router/runtime/plugin.js +49 -37
  7. package/dist/cjs/ssr/cli/index.js +19 -13
  8. package/dist/cjs/ssr/serverRender/renderToString/entry.js +10 -25
  9. package/dist/cjs/ssr/serverRender/renderToString/index.js +2 -5
  10. package/dist/cjs/ssr/serverRender/tracker.js +86 -0
  11. package/dist/esm/document/Body.js +2 -1
  12. package/dist/esm/document/Head.js +3 -1
  13. package/dist/esm/document/cli/index.js +9 -2
  14. package/dist/esm/document/constants.js +4 -2
  15. package/dist/esm/router/runtime/plugin.js +52 -40
  16. package/dist/esm/ssr/cli/index.js +19 -13
  17. package/dist/esm/ssr/serverRender/renderToString/entry.js +10 -25
  18. package/dist/esm/ssr/serverRender/renderToString/index.js +2 -5
  19. package/dist/esm/ssr/serverRender/tracker.js +61 -0
  20. package/dist/esm-node/document/Body.js +2 -1
  21. package/dist/esm-node/document/Head.js +3 -1
  22. package/dist/esm-node/document/cli/index.js +9 -2
  23. package/dist/esm-node/document/constants.js +3 -2
  24. package/dist/esm-node/router/runtime/plugin.js +50 -38
  25. package/dist/esm-node/ssr/cli/index.js +19 -13
  26. package/dist/esm-node/ssr/serverRender/renderToString/entry.js +10 -25
  27. package/dist/esm-node/ssr/serverRender/renderToString/index.js +2 -5
  28. package/dist/esm-node/ssr/serverRender/tracker.js +64 -0
  29. package/dist/types/document/constants.d.ts +3 -1
  30. package/dist/types/ssr/index.node.d.ts +1 -1
  31. package/dist/types/ssr/serverRender/renderToString/entry.d.ts +2 -4
  32. package/dist/types/ssr/serverRender/tracker.d.ts +21 -0
  33. package/package.json +9 -9
  34. package/dist/cjs/ssr/serverRender/reporter.js +0 -27
  35. package/dist/esm/ssr/serverRender/reporter.js +0 -17
  36. package/dist/esm-node/ssr/serverRender/reporter.js +0 -17
  37. package/dist/types/ssr/serverRender/reporter.d.ts +0 -8
package/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # @modern-js/runtime
2
2
 
3
+ ## 2.31.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 4a87c07: feat: memo creating router
8
+ feat: 缓存 router 创建
9
+ - 2361ce8: feat: support partials html in Document
10
+ feat: 支持 partials html 在 Document 中也生效
11
+ - cd39c6f: fix: use [\s\S]_ to replace ._ for \n\r char regex
12
+ fix: 使用 [\s\X]_ 替换 ._ 匹配 \n\r 字符
13
+ - Updated dependencies [1882366]
14
+ - @modern-js/utils@2.31.0
15
+ - @modern-js/plugin@2.31.0
16
+ - @modern-js/types@2.31.0
17
+
18
+ ## 2.30.0
19
+
20
+ ### Minor Changes
21
+
22
+ - 855a61e: feat(plugin-runtime): add ssr tracker
23
+ feat(plugin-runtime): 新增 ssr tracker
24
+
25
+ ### Patch Changes
26
+
27
+ - a8a4fd3: fix: ssr plugin use wrong config params
28
+ fix: ssr 插件使用了错误的 config 参数
29
+ - 276ace3: chore: remove noscript tag in html template
30
+ chore: 移除 HTML 模板中的 noscript 标签
31
+ - c731bf3: fix(plugin-runtime): the output maybe undefined;
32
+ fix(plugin-runtime): output 可能是个 undefined
33
+ - 8219d55: fix(plugin-runtime): ssg need use String SSR, so we should inject loadable-component babel plugin when enable ssg
34
+ fix(plugin-runtime): ssg 需要使用 String SSR, 我们需要在开启 SSG 得时候注入 loadbale-compnent babel 插件
35
+ - Updated dependencies [a5ee81a]
36
+ - Updated dependencies [b6ab299]
37
+ - @modern-js/types@2.30.0
38
+ - @modern-js/utils@2.30.0
39
+ - @modern-js/plugin@2.30.0
40
+
3
41
  ## 2.29.0
4
42
 
5
43
  ### Minor Changes
@@ -22,6 +22,7 @@ function Body(props) {
22
22
  children: [
23
23
  hasSetRoot ? null : /* @__PURE__ */ (0, _jsxruntime.jsx)(_Root.DefaultRoot, {}),
24
24
  children,
25
+ `${_constants.BODY_PARTICALS_SEPARATOR}`,
25
26
  `${_constants.DOCUMENT_CHUNKSMAP_PLACEHOLDER}`,
26
27
  `${_constants.DOCUMENT_SSRDATASCRIPT_PLACEHOLDER}`
27
28
  ]
@@ -30,9 +30,11 @@ function Head(props) {
30
30
  return /* @__PURE__ */ (0, _jsxruntime.jsxs)("head", {
31
31
  ...rest,
32
32
  children: [
33
+ `${_constants.TOP_PARTICALS_SEPARATOR}`,
33
34
  `${_constants.DOCUMENT_META_PLACEHOLDER}`,
34
35
  !hasSetLinks && /* @__PURE__ */ (0, _jsxruntime.jsx)(_Links.Links, {}),
35
36
  !hasSetScripts && /* @__PURE__ */ (0, _jsxruntime.jsx)(_Scripts.Scripts, {}),
37
+ `${_constants.HEAD_PARTICALS_SEPARATOR}`,
36
38
  children
37
39
  ]
38
40
  });
@@ -68,7 +68,7 @@ const documentPlugin = () => ({
68
68
  return null;
69
69
  }
70
70
  return async ({ htmlWebpackPlugin }) => {
71
- var _tsConfig;
71
+ var _tsConfig, _partialsByEntrypoint;
72
72
  const config = api.useResolvedConfigContext();
73
73
  const documentParams = getDocParams({
74
74
  config,
@@ -133,10 +133,17 @@ const documentPlugin = () => ({
133
133
  }, _react.default.createElement(Document, null));
134
134
  let html = _server.default.renderToStaticMarkup(HTMLElement);
135
135
  debug("entry %s's document jsx rendered html: %o", entryName, html);
136
+ const { partialsByEntrypoint } = api.useAppContext();
136
137
  const scripts = [
137
138
  htmlWebpackPlugin.tags.headTags.filter((item) => item.tagName === "script").join(""),
138
139
  htmlWebpackPlugin.tags.bodyTags.toString()
139
140
  ].join("");
141
+ if ((_partialsByEntrypoint = partialsByEntrypoint) === null || _partialsByEntrypoint === void 0 ? void 0 : _partialsByEntrypoint[entryName]) {
142
+ const partialsTop = partialsByEntrypoint[entryName].top.join("\n");
143
+ const partialsHead = partialsByEntrypoint[entryName].head.join("\n");
144
+ const partialsBody = partialsByEntrypoint[entryName].body.join("\n");
145
+ html = html.replace(_constants.TOP_PARTICALS_SEPARATOR, partialsTop).replace(_constants.HEAD_PARTICALS_SEPARATOR, partialsHead).replace(_constants.BODY_PARTICALS_SEPARATOR, partialsBody);
146
+ }
140
147
  const links = [
141
148
  htmlWebpackPlugin.tags.headTags.filter((item) => item.tagName === "link").join("")
142
149
  ].join("");
@@ -19,6 +19,15 @@ _export(exports, {
19
19
  HTML_SEPARATOR: function() {
20
20
  return HTML_SEPARATOR;
21
21
  },
22
+ HEAD_PARTICALS_SEPARATOR: function() {
23
+ return HEAD_PARTICALS_SEPARATOR;
24
+ },
25
+ BODY_PARTICALS_SEPARATOR: function() {
26
+ return BODY_PARTICALS_SEPARATOR;
27
+ },
28
+ TOP_PARTICALS_SEPARATOR: function() {
29
+ return TOP_PARTICALS_SEPARATOR;
30
+ },
22
31
  HTML_SSRDATASCRIPT_SEPARATOR: function() {
23
32
  return HTML_SSRDATASCRIPT_SEPARATOR;
24
33
  },
@@ -40,9 +49,6 @@ _export(exports, {
40
49
  DOCUMENT_LINKS_PLACEHOLDER: function() {
41
50
  return DOCUMENT_LINKS_PLACEHOLDER;
42
51
  },
43
- DOCUMENT_NO_SCRIPTE_PLACEHOLDER: function() {
44
- return DOCUMENT_NO_SCRIPTE_PLACEHOLDER;
45
- },
46
52
  DOCUMENT_SCRIPT_PLACEHOLDER_START: function() {
47
53
  return DOCUMENT_SCRIPT_PLACEHOLDER_START;
48
54
  },
@@ -74,6 +80,9 @@ const DOC_EXT = [
74
80
  ];
75
81
  const DOCUMENT_META_PLACEHOLDER = encodeURIComponent("<%= meta %>");
76
82
  const HTML_SEPARATOR = "<!--<?- html ?>-->";
83
+ const HEAD_PARTICALS_SEPARATOR = encodeURIComponent("<!--<?- partials.head ?>-->");
84
+ const BODY_PARTICALS_SEPARATOR = encodeURIComponent("<!--<?- partials.body ?>-->");
85
+ const TOP_PARTICALS_SEPARATOR = encodeURIComponent("<!--<?- partials.top ?>-->");
77
86
  const HTML_SSRDATASCRIPT_SEPARATOR = "<!--<?- SSRDataScript ?>-->";
78
87
  const DOCUMENT_SSR_PLACEHOLDER = encodeURIComponent(HTML_SEPARATOR);
79
88
  const DOCUMENT_CHUNKSMAP_PLACEHOLDER = encodeURIComponent(_constants.HTML_CHUNKSMAP_SEPARATOR);
@@ -81,7 +90,6 @@ const DOCUMENT_SSRDATASCRIPT_PLACEHOLDER = encodeURIComponent(HTML_SSRDATASCRIPT
81
90
  const DOCUMENT_FILE_NAME = "Document";
82
91
  const DOCUMENT_SCRIPTS_PLACEHOLDER = encodeURIComponent("<!-- chunk scripts placeholder -->");
83
92
  const DOCUMENT_LINKS_PLACEHOLDER = encodeURIComponent("<!-- chunk links placeholder -->");
84
- const DOCUMENT_NO_SCRIPTE_PLACEHOLDER = encodeURIComponent("<!-- no-script -->");
85
93
  const DOCUMENT_SCRIPT_PLACEHOLDER_START = encodeURIComponent("<!-- script-start -->");
86
94
  const DOCUMENT_SCRIPT_PLACEHOLDER_END = encodeURIComponent("<!-- script-end -->");
87
95
  const DOCUMENT_STYLE_PLACEHOLDER_START = encodeURIComponent("<!-- style-start -->");
@@ -89,7 +97,6 @@ const DOCUMENT_STYLE_PLACEHOLDER_END = encodeURIComponent("<!-- style-end -->");
89
97
  const DOCUMENT_COMMENT_PLACEHOLDER_START = encodeURIComponent("<!-- comment-start -->");
90
98
  const DOCUMENT_COMMENT_PLACEHOLDER_END = encodeURIComponent("<!-- comment-end -->");
91
99
  const PLACEHOLDER_REPLACER_MAP = {
92
- [DOCUMENT_NO_SCRIPTE_PLACEHOLDER]: `We're sorry but react app doesn't work properly without JavaScript enabled. Please enable it to continue.`,
93
100
  [DOCUMENT_SSR_PLACEHOLDER]: HTML_SEPARATOR,
94
101
  [DOCUMENT_CHUNKSMAP_PLACEHOLDER]: _constants.HTML_CHUNKSMAP_SEPARATOR,
95
102
  [DOCUMENT_SSRDATASCRIPT_PLACEHOLDER]: HTML_SSRDATASCRIPT_SEPARATOR
@@ -80,51 +80,63 @@ const routerPlugin = ({ serverBase = [], supportHtml5History = true, basename =
80
80
  });
81
81
  }
82
82
  const getRouteApp = () => {
83
- return (props) => {
84
- var _window__SERVER_DATA, _hydrationData;
85
- beforeCreateRouter = false;
86
- routes = createRoutes ? createRoutes() : (0, _router.createRoutesFromElements)((0, _utils.renderRoutes)({
87
- routesConfig: finalRouteConfig,
88
- props
89
- }));
90
- const runner = api.useHookRunners();
91
- routes = runner.modifyRoutes(routes);
83
+ const useCreateRouter = (props) => {
84
+ var _window__SERVER_DATA;
92
85
  const baseUrl = ((_window__SERVER_DATA = window._SERVER_DATA) === null || _window__SERVER_DATA === void 0 ? void 0 : _window__SERVER_DATA.router.baseUrl) || select(location.pathname);
93
86
  const _basename = baseUrl === "/" ? (0, _utils.urlJoin)(baseUrl, basename) : baseUrl;
94
87
  let hydrationData = window._ROUTER_DATA;
95
- if ((_hydrationData = hydrationData) === null || _hydrationData === void 0 ? void 0 : _hydrationData.errors) {
96
- hydrationData = {
97
- ...hydrationData,
98
- errors: (0, _utils.deserializeErrors)(hydrationData.errors)
99
- };
100
- }
101
- const router = supportHtml5History ? (0, _router.createBrowserRouter)(routes, {
102
- basename: _basename,
103
- hydrationData
104
- }) : (0, _router.createHashRouter)(routes, {
105
- basename: _basename,
106
- hydrationData
107
- });
108
88
  const runtimeContext = (0, _react.useContext)(_core.RuntimeReactContext);
109
- if (!runtimeContext.remixRouter) {
89
+ const { unstable_getBlockNavState: getBlockNavState } = runtimeContext;
90
+ return (0, _react.useMemo)(() => {
91
+ var _hydrationData;
92
+ if ((_hydrationData = hydrationData) === null || _hydrationData === void 0 ? void 0 : _hydrationData.errors) {
93
+ hydrationData = {
94
+ ...hydrationData,
95
+ errors: (0, _utils.deserializeErrors)(hydrationData.errors)
96
+ };
97
+ }
98
+ routes = createRoutes ? createRoutes() : (0, _router.createRoutesFromElements)((0, _utils.renderRoutes)({
99
+ routesConfig: finalRouteConfig,
100
+ props
101
+ }));
102
+ const runner = api.useHookRunners();
103
+ routes = runner.modifyRoutes(routes);
104
+ const router = supportHtml5History ? (0, _router.createBrowserRouter)(routes, {
105
+ basename: _basename,
106
+ hydrationData
107
+ }) : (0, _router.createHashRouter)(routes, {
108
+ basename: _basename,
109
+ hydrationData
110
+ });
111
+ const originSubscribe = router.subscribe;
112
+ router.subscribe = (listener) => {
113
+ const wrapedListener = (...args) => {
114
+ const blockRoute = getBlockNavState ? getBlockNavState() : false;
115
+ if (blockRoute) {
116
+ return;
117
+ }
118
+ return listener(...args);
119
+ };
120
+ return originSubscribe(wrapedListener);
121
+ };
110
122
  Object.defineProperty(runtimeContext, "remixRouter", {
111
123
  get() {
112
124
  return router;
113
- }
125
+ },
126
+ configurable: true
114
127
  });
115
- }
116
- const originSubscribe = router.subscribe;
117
- router.subscribe = (listener) => {
118
- const wrapedListener = (...args) => {
119
- const getBlockNavState = runtimeContext.unstable_getBlockNavState;
120
- const blockRoute = getBlockNavState ? getBlockNavState() : false;
121
- if (blockRoute) {
122
- return;
123
- }
124
- return listener(...args);
125
- };
126
- return originSubscribe(wrapedListener);
127
- };
128
+ return router;
129
+ }, [
130
+ finalRouteConfig,
131
+ props,
132
+ _basename,
133
+ hydrationData,
134
+ getBlockNavState
135
+ ]);
136
+ };
137
+ return (props) => {
138
+ beforeCreateRouter = false;
139
+ const router = useCreateRouter(props);
128
140
  return /* @__PURE__ */ (0, _jsxruntime.jsx)(App, {
129
141
  ...props,
130
142
  children: /* @__PURE__ */ (0, _jsxruntime.jsx)(_router.RouterProvider, {
@@ -24,8 +24,8 @@ const PLUGIN_IDENTIFIER = "ssr";
24
24
  const hasStringSSREntry = (userConfig) => {
25
25
  var _server, _server1;
26
26
  const isStreaming = (ssr) => ssr && typeof ssr === "object" && ssr.mode === "stream";
27
- const { server } = userConfig;
28
- if (((_server = server) === null || _server === void 0 ? void 0 : _server.ssr) && !isStreaming(server.ssr)) {
27
+ const { server, output } = userConfig;
28
+ if ((((_server = server) === null || _server === void 0 ? void 0 : _server.ssr) || output.ssg) && !isStreaming(server.ssr)) {
29
29
  return true;
30
30
  }
31
31
  if (((_server1 = server) === null || _server1 === void 0 ? void 0 : _server1.ssrByEntries) && typeof server.ssrByEntries === "object") {
@@ -37,6 +37,11 @@ const hasStringSSREntry = (userConfig) => {
37
37
  }
38
38
  return false;
39
39
  };
40
+ const checkUseStringSSR = (config) => {
41
+ var _output;
42
+ const { output } = config;
43
+ return Boolean((_output = output) === null || _output === void 0 ? void 0 : _output.ssg) || hasStringSSREntry(config);
44
+ };
40
45
  const ssrPlugin = () => ({
41
46
  name: "@modern-js/plugin-ssr",
42
47
  required: [
@@ -49,29 +54,30 @@ const ssrPlugin = () => ({
49
54
  config() {
50
55
  const appContext = api.useAppContext();
51
56
  pluginsExportsUtils = (0, _utils.createRuntimeExportsUtils)(appContext.internalDirectory, "plugins");
52
- const userConfig = api.useConfigContext();
53
57
  const { bundlerType = "webpack" } = api.useAppContext();
54
- const babelConfig = (() => {
58
+ const babelHandler = (() => {
55
59
  if (bundlerType === "webpack") {
56
60
  return (config) => {
57
61
  var _config_plugins;
62
+ const userConfig = api.useResolvedConfigContext();
58
63
  (_config_plugins = config.plugins) === null || _config_plugins === void 0 ? void 0 : _config_plugins.push(_path.default.join(__dirname, "./babel-plugin-ssr-loader-id"));
59
- if ((0, _utils.isUseSSRBundle)(userConfig) && hasStringSSREntry(userConfig)) {
64
+ if ((0, _utils.isUseSSRBundle)(userConfig) && checkUseStringSSR(userConfig)) {
60
65
  var _config_plugins1;
61
66
  (_config_plugins1 = config.plugins) === null || _config_plugins1 === void 0 ? void 0 : _config_plugins1.push(require.resolve("@loadable/babel-plugin"));
62
67
  }
63
68
  };
64
69
  } else if (bundlerType === "rspack") {
65
- if ((0, _utils.isUseSSRBundle)(userConfig)) {
66
- return (config) => {
70
+ return (config) => {
71
+ const userConfig = api.useResolvedConfigContext();
72
+ if ((0, _utils.isUseSSRBundle)(userConfig)) {
67
73
  var _config_plugins;
68
74
  (_config_plugins = config.plugins) === null || _config_plugins === void 0 ? void 0 : _config_plugins.push(_path.default.join(__dirname, "./babel-plugin-ssr-loader-id"));
69
- if (hasStringSSREntry(userConfig)) {
75
+ if (checkUseStringSSR(userConfig)) {
70
76
  var _config_plugins1;
71
77
  (_config_plugins1 = config.plugins) === null || _config_plugins1 === void 0 ? void 0 : _config_plugins1.push(require.resolve("@loadable/babel-plugin"));
72
78
  }
73
- };
74
- }
79
+ }
80
+ };
75
81
  }
76
82
  })();
77
83
  return {
@@ -87,8 +93,8 @@ const ssrPlugin = () => ({
87
93
  },
88
94
  tools: {
89
95
  bundlerChain(chain, { isServer, isServiceWorker, CHAIN_ID }) {
90
- const userConfig2 = api.useResolvedConfigContext();
91
- if ((0, _utils.isUseSSRBundle)(userConfig2) && !isServer && !isServiceWorker && hasStringSSREntry(userConfig2)) {
96
+ const userConfig = api.useResolvedConfigContext();
97
+ if ((0, _utils.isUseSSRBundle)(userConfig) && !isServer && !isServiceWorker && checkUseStringSSR(userConfig)) {
92
98
  const LoadableBundlerPlugin = require("./loadable-bundler-plugin.js");
93
99
  chain.plugin(CHAIN_ID.PLUGIN.LOADABLE).use(LoadableBundlerPlugin, [
94
100
  {
@@ -97,7 +103,7 @@ const ssrPlugin = () => ({
97
103
  ]);
98
104
  }
99
105
  },
100
- babel: babelConfig
106
+ babel: babelHandler
101
107
  }
102
108
  };
103
109
  },
@@ -21,13 +21,12 @@ const _helmet = /* @__PURE__ */ _interop_require_default._(require("../helmet"))
21
21
  const _types = require("../types");
22
22
  const _prefetch = /* @__PURE__ */ _interop_require_default._(require("../../prefetch"));
23
23
  const _utils1 = require("../utils");
24
- const _reporter = require("../reporter");
25
- const _constants = require("../constants");
24
+ const _tracker = require("../tracker");
26
25
  const _template = require("./template");
27
26
  const _reduce = require("./reduce");
28
27
  const _loadable = /* @__PURE__ */ _interop_require_wildcard._(require("./loadable"));
29
28
  const _styledComponent = /* @__PURE__ */ _interop_require_wildcard._(require("./styledComponent"));
30
- const buildTemplateData = (context, data, renderLevel, reporter) => {
29
+ const buildTemplateData = (context, data, renderLevel, tracker) => {
31
30
  const { request, enableUnsafeCtx } = context;
32
31
  const unsafeContext = {
33
32
  headers: request.headers
@@ -44,7 +43,7 @@ const buildTemplateData = (context, data, renderLevel, reporter) => {
44
43
  ...enableUnsafeCtx ? unsafeContext : {}
45
44
  },
46
45
  reporter: {
47
- sessionId: reporter.sessionId
46
+ sessionId: tracker.sessionId
48
47
  }
49
48
  },
50
49
  renderLevel
@@ -73,7 +72,7 @@ class Entry {
73
72
  errors: (0, _utils.serializeErrors)(routerContext.errors)
74
73
  } : void 0;
75
74
  let html = "";
76
- const templateData = buildTemplateData(ssrContext, prefetchData, this.result.renderLevel, this.reporter);
75
+ const templateData = buildTemplateData(ssrContext, prefetchData, this.result.renderLevel, this.tracker);
77
76
  const SSRData = this.getSSRDataScript(templateData, routerData);
78
77
  for (const fragment of this.fragments) {
79
78
  if (fragment.isVariable && fragment.content === "SSRDataScript") {
@@ -92,15 +91,10 @@ class Entry {
92
91
  prefetchData = await (0, _prefetch.default)(this.App, context);
93
92
  this.result.renderLevel = _types.RenderLevel.SERVER_PREFETCH;
94
93
  const prefetchCost = end();
95
- this.logger.debug(`App Prefetch cost = %d ms`, prefetchCost);
96
- this.metrics.emitTimer("app.prefetch.cost", prefetchCost);
97
- this.reporter.reportTime("app_prefetch_cost", prefetchCost);
98
- this.severTiming.addServeTiming(_constants.ServerTimingNames.SSR_PREFETCH, prefetchCost);
94
+ this.tracker.trackTiming(_tracker.SSRTimings.SSR_PREFETCH, prefetchCost);
99
95
  } catch (e) {
100
96
  this.result.renderLevel = _types.RenderLevel.CLIENT_RENDER;
101
- this.logger.error("App Prefetch Render", e);
102
- this.reporter.reportError("App Prefetch Render", e);
103
- this.metrics.emitCounter("app.prefetch.render.error", 1);
97
+ this.tracker.trackError(_tracker.SSRErrors.PREFETCH, e);
104
98
  }
105
99
  return prefetchData || {};
106
100
  }
@@ -129,15 +123,10 @@ class Entry {
129
123
  (jsx) => _server.default.renderToString(jsx)
130
124
  ]);
131
125
  const cost = end();
132
- this.logger.debug("App Render To HTML cost = %d ms", cost);
133
- this.metrics.emitTimer("app.render.html.cost", cost);
134
- this.reporter.reportTime("app_render_html_cost", cost);
135
- this.severTiming.addServeTiming(_constants.ServerTimingNames.SSR_RENDER_HTML, cost);
126
+ this.tracker.trackTiming(_tracker.SSRTimings.SSR_RENDER_HTML, cost);
136
127
  this.result.renderLevel = _types.RenderLevel.SERVER_RENDER;
137
128
  } catch (e) {
138
- this.logger.error("App Render To HTML", e);
139
- this.reporter.reportError("App Render To HTML", e);
140
- this.metrics.emitCounter("app.render.html.error", 1);
129
+ this.tracker.trackError(_tracker.SSRErrors.RENDER_HTML, e);
141
130
  }
142
131
  return html;
143
132
  }
@@ -162,9 +151,7 @@ class Entry {
162
151
  _define_property._(this, "entryName", void 0);
163
152
  _define_property._(this, "result", void 0);
164
153
  _define_property._(this, "metrics", void 0);
165
- _define_property._(this, "logger", void 0);
166
- _define_property._(this, "severTiming", void 0);
167
- _define_property._(this, "reporter", void 0);
154
+ _define_property._(this, "tracker", void 0);
168
155
  _define_property._(this, "template", void 0);
169
156
  _define_property._(this, "App", void 0);
170
157
  _define_property._(this, "fragments", void 0);
@@ -179,10 +166,8 @@ class Entry {
179
166
  this.host = host;
180
167
  this.App = options.App;
181
168
  this.pluginConfig = config;
182
- this.reporter = (0, _reporter.createSSRReporter)(ctx.reporter);
183
- this.severTiming = ctx.serverTiming;
169
+ this.tracker = (0, _tracker.createSSRTracker)(ctx);
184
170
  this.metrics = ctx.metrics;
185
- this.logger = ctx.logger;
186
171
  this.nonce = nonce;
187
172
  this.result = {
188
173
  renderLevel: _types.RenderLevel.CLIENT_RENDER,
@@ -12,7 +12,7 @@ const _interop_require_default = require("@swc/helpers/_/_interop_require_defaul
12
12
  const _runtimenode = require("@modern-js/utils/runtime-node");
13
13
  const _time = require("@modern-js/utils/universal/time");
14
14
  const _prerender = require("../../react/prerender");
15
- const _constants = require("../constants");
15
+ const _tracker = require("../tracker");
16
16
  const _entry = /* @__PURE__ */ _interop_require_default._(require("./entry"));
17
17
  const render = ({ App, context, config }) => {
18
18
  const ssrContext = context.ssrContext;
@@ -26,10 +26,7 @@ const render = ({ App, context, config }) => {
26
26
  const end = (0, _time.time)();
27
27
  const html = await entry.renderToHtml(context);
28
28
  const cost = end();
29
- entry.logger.info("App Render Total cost = %d ms", cost);
30
- entry.metrics.emitTimer("app.render.cost", cost);
31
- entry.reporter.reportTime("app_render_cost", cost);
32
- entry.severTiming.addServeTiming(_constants.ServerTimingNames.SSR_RENDER_TOTAL, cost);
29
+ entry.tracker.trackTiming(_tracker.SSRTimings.SSR_RENDER_TOTAL, cost);
33
30
  const cacheConfig = _prerender.PreRender.config();
34
31
  if (cacheConfig) {
35
32
  context.ssrContext.cacheConfig = cacheConfig;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for (var name in all)
7
+ Object.defineProperty(target, name, {
8
+ enumerable: true,
9
+ get: all[name]
10
+ });
11
+ }
12
+ _export(exports, {
13
+ SSRTimings: function() {
14
+ return SSRTimings;
15
+ },
16
+ SSRErrors: function() {
17
+ return SSRErrors;
18
+ },
19
+ createSSRTracker: function() {
20
+ return createSSRTracker;
21
+ }
22
+ });
23
+ var SSRTimings;
24
+ (function(SSRTimings2) {
25
+ SSRTimings2[SSRTimings2["SSR_RENDER_TOTAL"] = 0] = "SSR_RENDER_TOTAL";
26
+ SSRTimings2[SSRTimings2["SSR_PREFETCH"] = 1] = "SSR_PREFETCH";
27
+ SSRTimings2[SSRTimings2["SSR_RENDER_HTML"] = 2] = "SSR_RENDER_HTML";
28
+ })(SSRTimings || (SSRTimings = {}));
29
+ var SSRErrors;
30
+ (function(SSRErrors2) {
31
+ SSRErrors2[SSRErrors2["PREFETCH"] = 0] = "PREFETCH";
32
+ SSRErrors2[SSRErrors2["RENDER_HTML"] = 1] = "RENDER_HTML";
33
+ })(SSRErrors || (SSRErrors = {}));
34
+ const errors = {
35
+ [SSRErrors.PREFETCH]: {
36
+ reporter: "SSR Error - App Prefetch Render",
37
+ logger: "App Prefetch Render",
38
+ metrics: "app.prefetch.render.error"
39
+ },
40
+ [SSRErrors.RENDER_HTML]: {
41
+ reporter: "SSR Error - App Render To HTML",
42
+ logger: "App Render To HTML",
43
+ metrics: "app.render.html.error"
44
+ }
45
+ };
46
+ const timings = {
47
+ [SSRTimings.SSR_PREFETCH]: {
48
+ reporter: "ssr-prefetch",
49
+ serverTiming: "ssr-prefetch",
50
+ metrics: "app.prefeth.cost",
51
+ logger: "App Prefetch cost = %d ms"
52
+ },
53
+ [SSRTimings.SSR_RENDER_HTML]: {
54
+ reporter: "ssr-render-html",
55
+ serverTiming: "ssr-render-html",
56
+ metrics: "app.render.html.cost",
57
+ logger: "App Render To HTML cost = %d ms"
58
+ },
59
+ [SSRTimings.SSR_RENDER_TOTAL]: {
60
+ reporter: "ssr-render-total",
61
+ serverTiming: "ssr-render-total",
62
+ metrics: "app.render.cost",
63
+ logger: "App Render Total cost = %d ms"
64
+ }
65
+ };
66
+ function createSSRTracker({ reporter, serverTiming, metrics, logger }) {
67
+ const tracker = {
68
+ get sessionId() {
69
+ return reporter.sessionId;
70
+ },
71
+ trackError(key, e) {
72
+ const { reporter: reporterContent, metrics: metricsContent, logger: loggerContent } = errors[key];
73
+ reporterContent && reporter.reportError(reporterContent, e);
74
+ metricsContent && metrics.emitCounter(metricsContent, 1);
75
+ loggerContent && logger.error(loggerContent, e);
76
+ },
77
+ trackTiming(key, cost) {
78
+ const { reporter: reporterName, serverTiming: serverTimingName, logger: loggerName, metrics: metricsName } = timings[key];
79
+ reporterName && reporter.reportTiming(reporterName, cost);
80
+ serverTimingName && serverTiming.addServeTiming(serverTimingName, cost);
81
+ metricsName && metrics.emitTimer(metricsName, cost);
82
+ loggerName && logger.debug(loggerName, cost);
83
+ }
84
+ };
85
+ return tracker;
86
+ }
@@ -3,7 +3,7 @@ import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props";
3
3
  import { _ as _object_without_properties } from "@swc/helpers/_/_object_without_properties";
4
4
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
5
  import { useContext } from "react";
6
- import { DOCUMENT_CHUNKSMAP_PLACEHOLDER, DOCUMENT_SSRDATASCRIPT_PLACEHOLDER } from "./constants";
6
+ import { BODY_PARTICALS_SEPARATOR, DOCUMENT_CHUNKSMAP_PLACEHOLDER, DOCUMENT_SSRDATASCRIPT_PLACEHOLDER } from "./constants";
7
7
  import { DocumentStructureContext } from "./DocumentStructureContext";
8
8
  import { DefaultRoot } from "./Root";
9
9
  export function Body(props) {
@@ -15,6 +15,7 @@ export function Body(props) {
15
15
  children: [
16
16
  hasSetRoot ? null : /* @__PURE__ */ _jsx(DefaultRoot, {}),
17
17
  children,
18
+ "".concat(BODY_PARTICALS_SEPARATOR),
18
19
  "".concat(DOCUMENT_CHUNKSMAP_PLACEHOLDER),
19
20
  "".concat(DOCUMENT_SSRDATASCRIPT_PLACEHOLDER)
20
21
  ]
@@ -6,7 +6,7 @@ import { useContext } from "react";
6
6
  import { DocumentStructureContext } from "./DocumentStructureContext";
7
7
  import { Scripts } from "./Scripts";
8
8
  import { Links } from "./Links";
9
- import { DOCUMENT_META_PLACEHOLDER } from "./constants";
9
+ import { DOCUMENT_META_PLACEHOLDER, HEAD_PARTICALS_SEPARATOR, TOP_PARTICALS_SEPARATOR } from "./constants";
10
10
  export function Head(props) {
11
11
  var _useContext = useContext(DocumentStructureContext), hasSetScripts = _useContext.hasSetScripts, hasSetLinks = _useContext.hasSetLinks;
12
12
  var children = props.children, rest = _object_without_properties(props, [
@@ -14,9 +14,11 @@ export function Head(props) {
14
14
  ]);
15
15
  return /* @__PURE__ */ _jsxs("head", _object_spread_props(_object_spread({}, rest), {
16
16
  children: [
17
+ "".concat(TOP_PARTICALS_SEPARATOR),
17
18
  "".concat(DOCUMENT_META_PLACEHOLDER),
18
19
  !hasSetLinks && /* @__PURE__ */ _jsx(Links, {}),
19
20
  !hasSetScripts && /* @__PURE__ */ _jsx(Scripts, {}),
21
+ "".concat(HEAD_PARTICALS_SEPARATOR),
20
22
  children
21
23
  ]
22
24
  }));
@@ -8,7 +8,7 @@ import ReactDomServer from "react-dom/server";
8
8
  import { build } from "esbuild";
9
9
  import { createDebugger, findExists, fs } from "@modern-js/utils";
10
10
  import { DocumentContext } from "../DocumentContext";
11
- import { DOCUMENT_SCRIPTS_PLACEHOLDER, DOCUMENT_LINKS_PLACEHOLDER, DOCUMENT_FILE_NAME, DOCUMENT_META_PLACEHOLDER, PLACEHOLDER_REPLACER_MAP, DOC_EXT, DOCUMENT_SSR_PLACEHOLDER, DOCUMENT_CHUNKSMAP_PLACEHOLDER, DOCUMENT_SSRDATASCRIPT_PLACEHOLDER, DOCUMENT_SCRIPT_PLACEHOLDER_START, DOCUMENT_SCRIPT_PLACEHOLDER_END, HTML_SEPARATOR, DOCUMENT_COMMENT_PLACEHOLDER_START, DOCUMENT_COMMENT_PLACEHOLDER_END, DOCUMENT_STYLE_PLACEHOLDER_START, DOCUMENT_STYLE_PLACEHOLDER_END } from "../constants";
11
+ import { DOCUMENT_SCRIPTS_PLACEHOLDER, DOCUMENT_LINKS_PLACEHOLDER, DOCUMENT_FILE_NAME, DOCUMENT_META_PLACEHOLDER, PLACEHOLDER_REPLACER_MAP, DOC_EXT, DOCUMENT_SSR_PLACEHOLDER, DOCUMENT_CHUNKSMAP_PLACEHOLDER, DOCUMENT_SSRDATASCRIPT_PLACEHOLDER, DOCUMENT_SCRIPT_PLACEHOLDER_START, DOCUMENT_SCRIPT_PLACEHOLDER_END, HTML_SEPARATOR, DOCUMENT_COMMENT_PLACEHOLDER_START, DOCUMENT_COMMENT_PLACEHOLDER_END, DOCUMENT_STYLE_PLACEHOLDER_START, DOCUMENT_STYLE_PLACEHOLDER_END, TOP_PARTICALS_SEPARATOR, HEAD_PARTICALS_SEPARATOR, BODY_PARTICALS_SEPARATOR } from "../constants";
12
12
  var debug = createDebugger("html_genarate");
13
13
  export var getDocumenByEntryName = function getDocumenByEntryName2(entrypoints, entryName, fallbackDir) {
14
14
  var _entrypoints_find;
@@ -57,7 +57,7 @@ export var documentPlugin = function() {
57
57
  }
58
58
  return function() {
59
59
  var _ref2 = _async_to_generator(function(param) {
60
- var htmlWebpackPlugin, _tsConfig, config, documentParams, tempTsConfigFile, userTsConfigFilePath, tsConfig, err, htmlOutputFile, Document, HTMLElement, html, scripts, links, metas, nonce, nonceAttr, finalHtml;
60
+ var htmlWebpackPlugin, _tsConfig, _partialsByEntrypoint, config, documentParams, tempTsConfigFile, userTsConfigFilePath, tsConfig, err, htmlOutputFile, Document, HTMLElement, html, partialsByEntrypoint, scripts, partialsTop, partialsHead, partialsBody, links, metas, nonce, nonceAttr, finalHtml;
61
61
  return _ts_generator(this, function(_state2) {
62
62
  switch (_state2.label) {
63
63
  case 0:
@@ -156,12 +156,19 @@ export var documentPlugin = function() {
156
156
  }, React.createElement(Document, null));
157
157
  html = ReactDomServer.renderToStaticMarkup(HTMLElement);
158
158
  debug("entry %s's document jsx rendered html: %o", entryName, html);
159
+ partialsByEntrypoint = api.useAppContext().partialsByEntrypoint;
159
160
  scripts = [
160
161
  htmlWebpackPlugin.tags.headTags.filter(function(item) {
161
162
  return item.tagName === "script";
162
163
  }).join(""),
163
164
  htmlWebpackPlugin.tags.bodyTags.toString()
164
165
  ].join("");
166
+ if ((_partialsByEntrypoint = partialsByEntrypoint) === null || _partialsByEntrypoint === void 0 ? void 0 : _partialsByEntrypoint[entryName]) {
167
+ partialsTop = partialsByEntrypoint[entryName].top.join("\n");
168
+ partialsHead = partialsByEntrypoint[entryName].head.join("\n");
169
+ partialsBody = partialsByEntrypoint[entryName].body.join("\n");
170
+ html = html.replace(TOP_PARTICALS_SEPARATOR, partialsTop).replace(HEAD_PARTICALS_SEPARATOR, partialsHead).replace(BODY_PARTICALS_SEPARATOR, partialsBody);
171
+ }
165
172
  links = [
166
173
  htmlWebpackPlugin.tags.headTags.filter(function(item) {
167
174
  return item.tagName === "link";
@@ -8,6 +8,9 @@ export var DOC_EXT = [
8
8
  ];
9
9
  export var DOCUMENT_META_PLACEHOLDER = encodeURIComponent("<%= meta %>");
10
10
  export var HTML_SEPARATOR = "<!--<?- html ?>-->";
11
+ export var HEAD_PARTICALS_SEPARATOR = encodeURIComponent("<!--<?- partials.head ?>-->");
12
+ export var BODY_PARTICALS_SEPARATOR = encodeURIComponent("<!--<?- partials.body ?>-->");
13
+ export var TOP_PARTICALS_SEPARATOR = encodeURIComponent("<!--<?- partials.top ?>-->");
11
14
  export var HTML_SSRDATASCRIPT_SEPARATOR = "<!--<?- SSRDataScript ?>-->";
12
15
  export var DOCUMENT_SSR_PLACEHOLDER = encodeURIComponent(HTML_SEPARATOR);
13
16
  export var DOCUMENT_CHUNKSMAP_PLACEHOLDER = encodeURIComponent(HTML_CHUNKSMAP_SEPARATOR);
@@ -15,7 +18,6 @@ export var DOCUMENT_SSRDATASCRIPT_PLACEHOLDER = encodeURIComponent(HTML_SSRDATAS
15
18
  export var DOCUMENT_FILE_NAME = "Document";
16
19
  export var DOCUMENT_SCRIPTS_PLACEHOLDER = encodeURIComponent("<!-- chunk scripts placeholder -->");
17
20
  export var DOCUMENT_LINKS_PLACEHOLDER = encodeURIComponent("<!-- chunk links placeholder -->");
18
- export var DOCUMENT_NO_SCRIPTE_PLACEHOLDER = encodeURIComponent("<!-- no-script -->");
19
21
  export var DOCUMENT_SCRIPT_PLACEHOLDER_START = encodeURIComponent("<!-- script-start -->");
20
22
  export var DOCUMENT_SCRIPT_PLACEHOLDER_END = encodeURIComponent("<!-- script-end -->");
21
23
  export var DOCUMENT_STYLE_PLACEHOLDER_START = encodeURIComponent("<!-- style-start -->");
@@ -23,4 +25,4 @@ export var DOCUMENT_STYLE_PLACEHOLDER_END = encodeURIComponent("<!-- style-end -
23
25
  export var DOCUMENT_COMMENT_PLACEHOLDER_START = encodeURIComponent("<!-- comment-start -->");
24
26
  export var DOCUMENT_COMMENT_PLACEHOLDER_END = encodeURIComponent("<!-- comment-end -->");
25
27
  var _obj;
26
- export var PLACEHOLDER_REPLACER_MAP = (_obj = {}, _define_property(_obj, DOCUMENT_NO_SCRIPTE_PLACEHOLDER, "We're sorry but react app doesn't work properly without JavaScript enabled. Please enable it to continue."), _define_property(_obj, DOCUMENT_SSR_PLACEHOLDER, HTML_SEPARATOR), _define_property(_obj, DOCUMENT_CHUNKSMAP_PLACEHOLDER, HTML_CHUNKSMAP_SEPARATOR), _define_property(_obj, DOCUMENT_SSRDATASCRIPT_PLACEHOLDER, HTML_SSRDATASCRIPT_SEPARATOR), _obj);
28
+ export var PLACEHOLDER_REPLACER_MAP = (_obj = {}, _define_property(_obj, DOCUMENT_SSR_PLACEHOLDER, HTML_SEPARATOR), _define_property(_obj, DOCUMENT_CHUNKSMAP_PLACEHOLDER, HTML_CHUNKSMAP_SEPARATOR), _define_property(_obj, DOCUMENT_SSRDATASCRIPT_PLACEHOLDER, HTML_SSRDATASCRIPT_SEPARATOR), _obj);