@modern-js/runtime 2.29.0 → 2.30.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 +23 -0
- package/dist/cjs/document/constants.js +0 -5
- package/dist/cjs/ssr/cli/index.js +19 -13
- package/dist/cjs/ssr/serverRender/renderToString/entry.js +10 -25
- package/dist/cjs/ssr/serverRender/renderToString/index.js +2 -5
- package/dist/cjs/ssr/serverRender/tracker.js +86 -0
- package/dist/esm/document/constants.js +1 -2
- package/dist/esm/ssr/cli/index.js +19 -13
- package/dist/esm/ssr/serverRender/renderToString/entry.js +10 -25
- package/dist/esm/ssr/serverRender/renderToString/index.js +2 -5
- package/dist/esm/ssr/serverRender/tracker.js +61 -0
- package/dist/esm-node/document/constants.js +0 -2
- package/dist/esm-node/ssr/cli/index.js +19 -13
- package/dist/esm-node/ssr/serverRender/renderToString/entry.js +10 -25
- package/dist/esm-node/ssr/serverRender/renderToString/index.js +2 -5
- package/dist/esm-node/ssr/serverRender/tracker.js +64 -0
- package/dist/types/document/constants.d.ts +0 -1
- package/dist/types/ssr/index.node.d.ts +1 -1
- package/dist/types/ssr/serverRender/renderToString/entry.d.ts +2 -4
- package/dist/types/ssr/serverRender/tracker.d.ts +21 -0
- package/package.json +9 -9
- package/dist/cjs/ssr/serverRender/reporter.js +0 -27
- package/dist/esm/ssr/serverRender/reporter.js +0 -17
- package/dist/esm-node/ssr/serverRender/reporter.js +0 -17
- package/dist/types/ssr/serverRender/reporter.d.ts +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @modern-js/runtime
|
|
2
2
|
|
|
3
|
+
## 2.30.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 855a61e: feat(plugin-runtime): add ssr tracker
|
|
8
|
+
feat(plugin-runtime): 新增 ssr tracker
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- a8a4fd3: fix: ssr plugin use wrong config params
|
|
13
|
+
fix: ssr 插件使用了错误的 config 参数
|
|
14
|
+
- 276ace3: chore: remove noscript tag in html template
|
|
15
|
+
chore: 移除 HTML 模板中的 noscript 标签
|
|
16
|
+
- c731bf3: fix(plugin-runtime): the output maybe undefined;
|
|
17
|
+
fix(plugin-runtime): output 可能是个 undefined
|
|
18
|
+
- 8219d55: fix(plugin-runtime): ssg need use String SSR, so we should inject loadable-component babel plugin when enable ssg
|
|
19
|
+
fix(plugin-runtime): ssg 需要使用 String SSR, 我们需要在开启 SSG 得时候注入 loadbale-compnent babel 插件
|
|
20
|
+
- Updated dependencies [a5ee81a]
|
|
21
|
+
- Updated dependencies [b6ab299]
|
|
22
|
+
- @modern-js/types@2.30.0
|
|
23
|
+
- @modern-js/utils@2.30.0
|
|
24
|
+
- @modern-js/plugin@2.30.0
|
|
25
|
+
|
|
3
26
|
## 2.29.0
|
|
4
27
|
|
|
5
28
|
### Minor Changes
|
|
@@ -40,9 +40,6 @@ _export(exports, {
|
|
|
40
40
|
DOCUMENT_LINKS_PLACEHOLDER: function() {
|
|
41
41
|
return DOCUMENT_LINKS_PLACEHOLDER;
|
|
42
42
|
},
|
|
43
|
-
DOCUMENT_NO_SCRIPTE_PLACEHOLDER: function() {
|
|
44
|
-
return DOCUMENT_NO_SCRIPTE_PLACEHOLDER;
|
|
45
|
-
},
|
|
46
43
|
DOCUMENT_SCRIPT_PLACEHOLDER_START: function() {
|
|
47
44
|
return DOCUMENT_SCRIPT_PLACEHOLDER_START;
|
|
48
45
|
},
|
|
@@ -81,7 +78,6 @@ const DOCUMENT_SSRDATASCRIPT_PLACEHOLDER = encodeURIComponent(HTML_SSRDATASCRIPT
|
|
|
81
78
|
const DOCUMENT_FILE_NAME = "Document";
|
|
82
79
|
const DOCUMENT_SCRIPTS_PLACEHOLDER = encodeURIComponent("<!-- chunk scripts placeholder -->");
|
|
83
80
|
const DOCUMENT_LINKS_PLACEHOLDER = encodeURIComponent("<!-- chunk links placeholder -->");
|
|
84
|
-
const DOCUMENT_NO_SCRIPTE_PLACEHOLDER = encodeURIComponent("<!-- no-script -->");
|
|
85
81
|
const DOCUMENT_SCRIPT_PLACEHOLDER_START = encodeURIComponent("<!-- script-start -->");
|
|
86
82
|
const DOCUMENT_SCRIPT_PLACEHOLDER_END = encodeURIComponent("<!-- script-end -->");
|
|
87
83
|
const DOCUMENT_STYLE_PLACEHOLDER_START = encodeURIComponent("<!-- style-start -->");
|
|
@@ -89,7 +85,6 @@ const DOCUMENT_STYLE_PLACEHOLDER_END = encodeURIComponent("<!-- style-end -->");
|
|
|
89
85
|
const DOCUMENT_COMMENT_PLACEHOLDER_START = encodeURIComponent("<!-- comment-start -->");
|
|
90
86
|
const DOCUMENT_COMMENT_PLACEHOLDER_END = encodeURIComponent("<!-- comment-end -->");
|
|
91
87
|
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
88
|
[DOCUMENT_SSR_PLACEHOLDER]: HTML_SEPARATOR,
|
|
94
89
|
[DOCUMENT_CHUNKSMAP_PLACEHOLDER]: _constants.HTML_CHUNKSMAP_SEPARATOR,
|
|
95
90
|
[DOCUMENT_SSRDATASCRIPT_PLACEHOLDER]: HTML_SSRDATASCRIPT_SEPARATOR
|
|
@@ -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
|
|
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) &&
|
|
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
|
-
|
|
66
|
-
|
|
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 (
|
|
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
|
|
91
|
-
if ((0, _utils.isUseSSRBundle)(
|
|
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:
|
|
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
|
|
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,
|
|
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:
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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, "
|
|
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.
|
|
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
|
|
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.
|
|
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
|
+
}
|
|
@@ -15,7 +15,6 @@ export var DOCUMENT_SSRDATASCRIPT_PLACEHOLDER = encodeURIComponent(HTML_SSRDATAS
|
|
|
15
15
|
export var DOCUMENT_FILE_NAME = "Document";
|
|
16
16
|
export var DOCUMENT_SCRIPTS_PLACEHOLDER = encodeURIComponent("<!-- chunk scripts placeholder -->");
|
|
17
17
|
export var DOCUMENT_LINKS_PLACEHOLDER = encodeURIComponent("<!-- chunk links placeholder -->");
|
|
18
|
-
export var DOCUMENT_NO_SCRIPTE_PLACEHOLDER = encodeURIComponent("<!-- no-script -->");
|
|
19
18
|
export var DOCUMENT_SCRIPT_PLACEHOLDER_START = encodeURIComponent("<!-- script-start -->");
|
|
20
19
|
export var DOCUMENT_SCRIPT_PLACEHOLDER_END = encodeURIComponent("<!-- script-end -->");
|
|
21
20
|
export var DOCUMENT_STYLE_PLACEHOLDER_START = encodeURIComponent("<!-- style-start -->");
|
|
@@ -23,4 +22,4 @@ export var DOCUMENT_STYLE_PLACEHOLDER_END = encodeURIComponent("<!-- style-end -
|
|
|
23
22
|
export var DOCUMENT_COMMENT_PLACEHOLDER_START = encodeURIComponent("<!-- comment-start -->");
|
|
24
23
|
export var DOCUMENT_COMMENT_PLACEHOLDER_END = encodeURIComponent("<!-- comment-end -->");
|
|
25
24
|
var _obj;
|
|
26
|
-
export var PLACEHOLDER_REPLACER_MAP = (_obj = {}, _define_property(_obj,
|
|
25
|
+
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);
|
|
@@ -8,8 +8,8 @@ var hasStringSSREntry = function(userConfig) {
|
|
|
8
8
|
var isStreaming = function(ssr) {
|
|
9
9
|
return ssr && typeof ssr === "object" && ssr.mode === "stream";
|
|
10
10
|
};
|
|
11
|
-
var server = userConfig.server;
|
|
12
|
-
if (((_server = server) === null || _server === void 0 ? void 0 : _server.ssr) && !isStreaming(server.ssr)) {
|
|
11
|
+
var server = userConfig.server, output = userConfig.output;
|
|
12
|
+
if ((((_server = server) === null || _server === void 0 ? void 0 : _server.ssr) || output.ssg) && !isStreaming(server.ssr)) {
|
|
13
13
|
return true;
|
|
14
14
|
}
|
|
15
15
|
if (((_server1 = server) === null || _server1 === void 0 ? void 0 : _server1.ssrByEntries) && typeof server.ssrByEntries === "object") {
|
|
@@ -38,6 +38,11 @@ var hasStringSSREntry = function(userConfig) {
|
|
|
38
38
|
}
|
|
39
39
|
return false;
|
|
40
40
|
};
|
|
41
|
+
var checkUseStringSSR = function(config) {
|
|
42
|
+
var _output;
|
|
43
|
+
var output = config.output;
|
|
44
|
+
return Boolean((_output = output) === null || _output === void 0 ? void 0 : _output.ssg) || hasStringSSREntry(config);
|
|
45
|
+
};
|
|
41
46
|
export var ssrPlugin = function() {
|
|
42
47
|
return {
|
|
43
48
|
name: "@modern-js/plugin-ssr",
|
|
@@ -51,29 +56,30 @@ export var ssrPlugin = function() {
|
|
|
51
56
|
config: function config() {
|
|
52
57
|
var appContext = api.useAppContext();
|
|
53
58
|
pluginsExportsUtils = createRuntimeExportsUtils(appContext.internalDirectory, "plugins");
|
|
54
|
-
var userConfig = api.useConfigContext();
|
|
55
59
|
var _api_useAppContext = api.useAppContext(), _api_useAppContext_bundlerType = _api_useAppContext.bundlerType, bundlerType = _api_useAppContext_bundlerType === void 0 ? "webpack" : _api_useAppContext_bundlerType;
|
|
56
|
-
var
|
|
60
|
+
var babelHandler = function() {
|
|
57
61
|
if (bundlerType === "webpack") {
|
|
58
62
|
return function(config2) {
|
|
59
63
|
var _config_plugins;
|
|
64
|
+
var userConfig = api.useResolvedConfigContext();
|
|
60
65
|
(_config_plugins = config2.plugins) === null || _config_plugins === void 0 ? void 0 : _config_plugins.push(path.join(__dirname, "./babel-plugin-ssr-loader-id"));
|
|
61
|
-
if (isUseSSRBundle(userConfig) &&
|
|
66
|
+
if (isUseSSRBundle(userConfig) && checkUseStringSSR(userConfig)) {
|
|
62
67
|
var _config_plugins1;
|
|
63
68
|
(_config_plugins1 = config2.plugins) === null || _config_plugins1 === void 0 ? void 0 : _config_plugins1.push(require.resolve("@loadable/babel-plugin"));
|
|
64
69
|
}
|
|
65
70
|
};
|
|
66
71
|
} else if (bundlerType === "rspack") {
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
return function(config2) {
|
|
73
|
+
var userConfig = api.useResolvedConfigContext();
|
|
74
|
+
if (isUseSSRBundle(userConfig)) {
|
|
69
75
|
var _config_plugins;
|
|
70
76
|
(_config_plugins = config2.plugins) === null || _config_plugins === void 0 ? void 0 : _config_plugins.push(path.join(__dirname, "./babel-plugin-ssr-loader-id"));
|
|
71
|
-
if (
|
|
77
|
+
if (checkUseStringSSR(userConfig)) {
|
|
72
78
|
var _config_plugins1;
|
|
73
79
|
(_config_plugins1 = config2.plugins) === null || _config_plugins1 === void 0 ? void 0 : _config_plugins1.push(require.resolve("@loadable/babel-plugin"));
|
|
74
80
|
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
77
83
|
}
|
|
78
84
|
}();
|
|
79
85
|
return {
|
|
@@ -91,8 +97,8 @@ export var ssrPlugin = function() {
|
|
|
91
97
|
tools: {
|
|
92
98
|
bundlerChain: function bundlerChain(chain, param) {
|
|
93
99
|
var isServer = param.isServer, isServiceWorker = param.isServiceWorker, CHAIN_ID = param.CHAIN_ID;
|
|
94
|
-
var
|
|
95
|
-
if (isUseSSRBundle(
|
|
100
|
+
var userConfig = api.useResolvedConfigContext();
|
|
101
|
+
if (isUseSSRBundle(userConfig) && !isServer && !isServiceWorker && checkUseStringSSR(userConfig)) {
|
|
96
102
|
var LoadableBundlerPlugin = require("./loadable-bundler-plugin.js");
|
|
97
103
|
chain.plugin(CHAIN_ID.PLUGIN.LOADABLE).use(LoadableBundlerPlugin, [
|
|
98
104
|
{
|
|
@@ -101,7 +107,7 @@ export var ssrPlugin = function() {
|
|
|
101
107
|
]);
|
|
102
108
|
}
|
|
103
109
|
},
|
|
104
|
-
babel:
|
|
110
|
+
babel: babelHandler
|
|
105
111
|
}
|
|
106
112
|
};
|
|
107
113
|
},
|
|
@@ -14,13 +14,12 @@ import helmetReplace from "../helmet";
|
|
|
14
14
|
import { RenderLevel } from "../types";
|
|
15
15
|
import prefetch from "../../prefetch";
|
|
16
16
|
import { ROUTER_DATA_JSON_ID, SSR_DATA_JSON_ID, attributesToString } from "../utils";
|
|
17
|
-
import {
|
|
18
|
-
import { ServerTimingNames } from "../constants";
|
|
17
|
+
import { SSRErrors, SSRTimings, createSSRTracker } from "../tracker";
|
|
19
18
|
import { toFragments } from "./template";
|
|
20
19
|
import { reduce } from "./reduce";
|
|
21
20
|
import * as loadableRenderer from "./loadable";
|
|
22
21
|
import * as styledComponentRenderer from "./styledComponent";
|
|
23
|
-
var buildTemplateData = function(context, data, renderLevel,
|
|
22
|
+
var buildTemplateData = function(context, data, renderLevel, tracker) {
|
|
24
23
|
var request = context.request, enableUnsafeCtx = context.enableUnsafeCtx;
|
|
25
24
|
var unsafeContext = {
|
|
26
25
|
headers: request.headers
|
|
@@ -36,7 +35,7 @@ var buildTemplateData = function(context, data, renderLevel, reporter) {
|
|
|
36
35
|
url: request.url
|
|
37
36
|
}, enableUnsafeCtx ? unsafeContext : {}),
|
|
38
37
|
reporter: {
|
|
39
|
-
sessionId:
|
|
38
|
+
sessionId: tracker.sessionId
|
|
40
39
|
}
|
|
41
40
|
},
|
|
42
41
|
renderLevel: renderLevel
|
|
@@ -49,9 +48,7 @@ var Entry = /* @__PURE__ */ function() {
|
|
|
49
48
|
_define_property(this, "entryName", void 0);
|
|
50
49
|
_define_property(this, "result", void 0);
|
|
51
50
|
_define_property(this, "metrics", void 0);
|
|
52
|
-
_define_property(this, "
|
|
53
|
-
_define_property(this, "severTiming", void 0);
|
|
54
|
-
_define_property(this, "reporter", void 0);
|
|
51
|
+
_define_property(this, "tracker", void 0);
|
|
55
52
|
_define_property(this, "template", void 0);
|
|
56
53
|
_define_property(this, "App", void 0);
|
|
57
54
|
_define_property(this, "fragments", void 0);
|
|
@@ -66,10 +63,8 @@ var Entry = /* @__PURE__ */ function() {
|
|
|
66
63
|
this.host = host;
|
|
67
64
|
this.App = options.App;
|
|
68
65
|
this.pluginConfig = config;
|
|
69
|
-
this.
|
|
70
|
-
this.severTiming = ctx.serverTiming;
|
|
66
|
+
this.tracker = createSSRTracker(ctx);
|
|
71
67
|
this.metrics = ctx.metrics;
|
|
72
|
-
this.logger = ctx.logger;
|
|
73
68
|
this.nonce = nonce;
|
|
74
69
|
this.result = {
|
|
75
70
|
renderLevel: RenderLevel.CLIENT_RENDER,
|
|
@@ -124,7 +119,7 @@ var Entry = /* @__PURE__ */ function() {
|
|
|
124
119
|
errors: serializeErrors(routerContext.errors)
|
|
125
120
|
} : void 0;
|
|
126
121
|
html = "";
|
|
127
|
-
templateData = buildTemplateData(ssrContext, prefetchData, _this.result.renderLevel, _this.
|
|
122
|
+
templateData = buildTemplateData(ssrContext, prefetchData, _this.result.renderLevel, _this.tracker);
|
|
128
123
|
SSRData = _this.getSSRDataScript(templateData, routerData);
|
|
129
124
|
_iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
130
125
|
try {
|
|
@@ -186,10 +181,7 @@ var Entry = /* @__PURE__ */ function() {
|
|
|
186
181
|
prefetchData = _state.sent();
|
|
187
182
|
_this.result.renderLevel = RenderLevel.SERVER_PREFETCH;
|
|
188
183
|
prefetchCost = end();
|
|
189
|
-
_this.
|
|
190
|
-
_this.metrics.emitTimer("app.prefetch.cost", prefetchCost);
|
|
191
|
-
_this.reporter.reportTime("app_prefetch_cost", prefetchCost);
|
|
192
|
-
_this.severTiming.addServeTiming(ServerTimingNames.SSR_PREFETCH, prefetchCost);
|
|
184
|
+
_this.tracker.trackTiming(SSRTimings.SSR_PREFETCH, prefetchCost);
|
|
193
185
|
return [
|
|
194
186
|
3,
|
|
195
187
|
4
|
|
@@ -197,9 +189,7 @@ var Entry = /* @__PURE__ */ function() {
|
|
|
197
189
|
case 3:
|
|
198
190
|
e = _state.sent();
|
|
199
191
|
_this.result.renderLevel = RenderLevel.CLIENT_RENDER;
|
|
200
|
-
_this.
|
|
201
|
-
_this.reporter.reportError("App Prefetch Render", e);
|
|
202
|
-
_this.metrics.emitCounter("app.prefetch.render.error", 1);
|
|
192
|
+
_this.tracker.trackError(SSRErrors.PREFETCH, e);
|
|
203
193
|
return [
|
|
204
194
|
3,
|
|
205
195
|
4
|
|
@@ -243,15 +233,10 @@ var Entry = /* @__PURE__ */ function() {
|
|
|
243
233
|
}
|
|
244
234
|
]);
|
|
245
235
|
var cost = end();
|
|
246
|
-
this.
|
|
247
|
-
this.metrics.emitTimer("app.render.html.cost", cost);
|
|
248
|
-
this.reporter.reportTime("app_render_html_cost", cost);
|
|
249
|
-
this.severTiming.addServeTiming(ServerTimingNames.SSR_RENDER_HTML, cost);
|
|
236
|
+
this.tracker.trackTiming(SSRTimings.SSR_RENDER_HTML, cost);
|
|
250
237
|
this.result.renderLevel = RenderLevel.SERVER_RENDER;
|
|
251
238
|
} catch (e) {
|
|
252
|
-
this.
|
|
253
|
-
this.reporter.reportError("App Render To HTML", e);
|
|
254
|
-
this.metrics.emitCounter("app.render.html.error", 1);
|
|
239
|
+
this.tracker.trackError(SSRErrors.RENDER_HTML, e);
|
|
255
240
|
}
|
|
256
241
|
return html;
|
|
257
242
|
}
|
|
@@ -3,7 +3,7 @@ import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
|
|
|
3
3
|
import { run } from "@modern-js/utils/runtime-node";
|
|
4
4
|
import { time } from "@modern-js/utils/universal/time";
|
|
5
5
|
import { PreRender } from "../../react/prerender";
|
|
6
|
-
import {
|
|
6
|
+
import { SSRTimings } from "../tracker";
|
|
7
7
|
import SSREntry from "./entry";
|
|
8
8
|
export var render = function(param) {
|
|
9
9
|
var App = param.App, context = param.context, config = param.config;
|
|
@@ -27,10 +27,7 @@ export var render = function(param) {
|
|
|
27
27
|
case 1:
|
|
28
28
|
html = _state.sent();
|
|
29
29
|
cost = end();
|
|
30
|
-
entry.
|
|
31
|
-
entry.metrics.emitTimer("app.render.cost", cost);
|
|
32
|
-
entry.reporter.reportTime("app_render_cost", cost);
|
|
33
|
-
entry.severTiming.addServeTiming(ServerTimingNames.SSR_RENDER_TOTAL, cost);
|
|
30
|
+
entry.tracker.trackTiming(SSRTimings.SSR_RENDER_TOTAL, cost);
|
|
34
31
|
cacheConfig = PreRender.config();
|
|
35
32
|
if (cacheConfig) {
|
|
36
33
|
context.ssrContext.cacheConfig = cacheConfig;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
2
|
+
export var SSRTimings;
|
|
3
|
+
(function(SSRTimings2) {
|
|
4
|
+
SSRTimings2[SSRTimings2["SSR_RENDER_TOTAL"] = 0] = "SSR_RENDER_TOTAL";
|
|
5
|
+
SSRTimings2[SSRTimings2["SSR_PREFETCH"] = 1] = "SSR_PREFETCH";
|
|
6
|
+
SSRTimings2[SSRTimings2["SSR_RENDER_HTML"] = 2] = "SSR_RENDER_HTML";
|
|
7
|
+
})(SSRTimings || (SSRTimings = {}));
|
|
8
|
+
export var SSRErrors;
|
|
9
|
+
(function(SSRErrors2) {
|
|
10
|
+
SSRErrors2[SSRErrors2["PREFETCH"] = 0] = "PREFETCH";
|
|
11
|
+
SSRErrors2[SSRErrors2["RENDER_HTML"] = 1] = "RENDER_HTML";
|
|
12
|
+
})(SSRErrors || (SSRErrors = {}));
|
|
13
|
+
var _obj;
|
|
14
|
+
var errors = (_obj = {}, _define_property(_obj, SSRErrors.PREFETCH, {
|
|
15
|
+
reporter: "SSR Error - App Prefetch Render",
|
|
16
|
+
logger: "App Prefetch Render",
|
|
17
|
+
metrics: "app.prefetch.render.error"
|
|
18
|
+
}), _define_property(_obj, SSRErrors.RENDER_HTML, {
|
|
19
|
+
reporter: "SSR Error - App Render To HTML",
|
|
20
|
+
logger: "App Render To HTML",
|
|
21
|
+
metrics: "app.render.html.error"
|
|
22
|
+
}), _obj);
|
|
23
|
+
var _obj1;
|
|
24
|
+
var timings = (_obj1 = {}, _define_property(_obj1, SSRTimings.SSR_PREFETCH, {
|
|
25
|
+
reporter: "ssr-prefetch",
|
|
26
|
+
serverTiming: "ssr-prefetch",
|
|
27
|
+
metrics: "app.prefeth.cost",
|
|
28
|
+
logger: "App Prefetch cost = %d ms"
|
|
29
|
+
}), _define_property(_obj1, SSRTimings.SSR_RENDER_HTML, {
|
|
30
|
+
reporter: "ssr-render-html",
|
|
31
|
+
serverTiming: "ssr-render-html",
|
|
32
|
+
metrics: "app.render.html.cost",
|
|
33
|
+
logger: "App Render To HTML cost = %d ms"
|
|
34
|
+
}), _define_property(_obj1, SSRTimings.SSR_RENDER_TOTAL, {
|
|
35
|
+
reporter: "ssr-render-total",
|
|
36
|
+
serverTiming: "ssr-render-total",
|
|
37
|
+
metrics: "app.render.cost",
|
|
38
|
+
logger: "App Render Total cost = %d ms"
|
|
39
|
+
}), _obj1);
|
|
40
|
+
export function createSSRTracker(param) {
|
|
41
|
+
var reporter = param.reporter, serverTiming = param.serverTiming, metrics = param.metrics, logger = param.logger;
|
|
42
|
+
var tracker = {
|
|
43
|
+
get sessionId() {
|
|
44
|
+
return reporter.sessionId;
|
|
45
|
+
},
|
|
46
|
+
trackError: function trackError(key, e) {
|
|
47
|
+
var _errors_key = errors[key], reporterContent = _errors_key.reporter, metricsContent = _errors_key.metrics, loggerContent = _errors_key.logger;
|
|
48
|
+
reporterContent && reporter.reportError(reporterContent, e);
|
|
49
|
+
metricsContent && metrics.emitCounter(metricsContent, 1);
|
|
50
|
+
loggerContent && logger.error(loggerContent, e);
|
|
51
|
+
},
|
|
52
|
+
trackTiming: function trackTiming(key, cost) {
|
|
53
|
+
var _timings_key = timings[key], reporterName = _timings_key.reporter, serverTimingName = _timings_key.serverTiming, loggerName = _timings_key.logger, metricsName = _timings_key.metrics;
|
|
54
|
+
reporterName && reporter.reportTiming(reporterName, cost);
|
|
55
|
+
serverTimingName && serverTiming.addServeTiming(serverTimingName, cost);
|
|
56
|
+
metricsName && metrics.emitTimer(metricsName, cost);
|
|
57
|
+
loggerName && logger.debug(loggerName, cost);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
return tracker;
|
|
61
|
+
}
|
|
@@ -14,7 +14,6 @@ export const DOCUMENT_SSRDATASCRIPT_PLACEHOLDER = encodeURIComponent(HTML_SSRDAT
|
|
|
14
14
|
export const DOCUMENT_FILE_NAME = "Document";
|
|
15
15
|
export const DOCUMENT_SCRIPTS_PLACEHOLDER = encodeURIComponent("<!-- chunk scripts placeholder -->");
|
|
16
16
|
export const DOCUMENT_LINKS_PLACEHOLDER = encodeURIComponent("<!-- chunk links placeholder -->");
|
|
17
|
-
export const DOCUMENT_NO_SCRIPTE_PLACEHOLDER = encodeURIComponent("<!-- no-script -->");
|
|
18
17
|
export const DOCUMENT_SCRIPT_PLACEHOLDER_START = encodeURIComponent("<!-- script-start -->");
|
|
19
18
|
export const DOCUMENT_SCRIPT_PLACEHOLDER_END = encodeURIComponent("<!-- script-end -->");
|
|
20
19
|
export const DOCUMENT_STYLE_PLACEHOLDER_START = encodeURIComponent("<!-- style-start -->");
|
|
@@ -22,7 +21,6 @@ export const DOCUMENT_STYLE_PLACEHOLDER_END = encodeURIComponent("<!-- style-end
|
|
|
22
21
|
export const DOCUMENT_COMMENT_PLACEHOLDER_START = encodeURIComponent("<!-- comment-start -->");
|
|
23
22
|
export const DOCUMENT_COMMENT_PLACEHOLDER_END = encodeURIComponent("<!-- comment-end -->");
|
|
24
23
|
export const PLACEHOLDER_REPLACER_MAP = {
|
|
25
|
-
[DOCUMENT_NO_SCRIPTE_PLACEHOLDER]: `We're sorry but react app doesn't work properly without JavaScript enabled. Please enable it to continue.`,
|
|
26
24
|
[DOCUMENT_SSR_PLACEHOLDER]: HTML_SEPARATOR,
|
|
27
25
|
[DOCUMENT_CHUNKSMAP_PLACEHOLDER]: HTML_CHUNKSMAP_SEPARATOR,
|
|
28
26
|
[DOCUMENT_SSRDATASCRIPT_PLACEHOLDER]: HTML_SSRDATASCRIPT_SEPARATOR
|
|
@@ -4,8 +4,8 @@ const PLUGIN_IDENTIFIER = "ssr";
|
|
|
4
4
|
const hasStringSSREntry = (userConfig) => {
|
|
5
5
|
var _server, _server1;
|
|
6
6
|
const isStreaming = (ssr) => ssr && typeof ssr === "object" && ssr.mode === "stream";
|
|
7
|
-
const { server } = userConfig;
|
|
8
|
-
if (((_server = server) === null || _server === void 0 ? void 0 : _server.ssr) && !isStreaming(server.ssr)) {
|
|
7
|
+
const { server, output } = userConfig;
|
|
8
|
+
if ((((_server = server) === null || _server === void 0 ? void 0 : _server.ssr) || output.ssg) && !isStreaming(server.ssr)) {
|
|
9
9
|
return true;
|
|
10
10
|
}
|
|
11
11
|
if (((_server1 = server) === null || _server1 === void 0 ? void 0 : _server1.ssrByEntries) && typeof server.ssrByEntries === "object") {
|
|
@@ -17,6 +17,11 @@ const hasStringSSREntry = (userConfig) => {
|
|
|
17
17
|
}
|
|
18
18
|
return false;
|
|
19
19
|
};
|
|
20
|
+
const checkUseStringSSR = (config) => {
|
|
21
|
+
var _output;
|
|
22
|
+
const { output } = config;
|
|
23
|
+
return Boolean((_output = output) === null || _output === void 0 ? void 0 : _output.ssg) || hasStringSSREntry(config);
|
|
24
|
+
};
|
|
20
25
|
export const ssrPlugin = () => ({
|
|
21
26
|
name: "@modern-js/plugin-ssr",
|
|
22
27
|
required: [
|
|
@@ -29,29 +34,30 @@ export const ssrPlugin = () => ({
|
|
|
29
34
|
config() {
|
|
30
35
|
const appContext = api.useAppContext();
|
|
31
36
|
pluginsExportsUtils = createRuntimeExportsUtils(appContext.internalDirectory, "plugins");
|
|
32
|
-
const userConfig = api.useConfigContext();
|
|
33
37
|
const { bundlerType = "webpack" } = api.useAppContext();
|
|
34
|
-
const
|
|
38
|
+
const babelHandler = (() => {
|
|
35
39
|
if (bundlerType === "webpack") {
|
|
36
40
|
return (config) => {
|
|
37
41
|
var _config_plugins;
|
|
42
|
+
const userConfig = api.useResolvedConfigContext();
|
|
38
43
|
(_config_plugins = config.plugins) === null || _config_plugins === void 0 ? void 0 : _config_plugins.push(path.join(__dirname, "./babel-plugin-ssr-loader-id"));
|
|
39
|
-
if (isUseSSRBundle(userConfig) &&
|
|
44
|
+
if (isUseSSRBundle(userConfig) && checkUseStringSSR(userConfig)) {
|
|
40
45
|
var _config_plugins1;
|
|
41
46
|
(_config_plugins1 = config.plugins) === null || _config_plugins1 === void 0 ? void 0 : _config_plugins1.push(require.resolve("@loadable/babel-plugin"));
|
|
42
47
|
}
|
|
43
48
|
};
|
|
44
49
|
} else if (bundlerType === "rspack") {
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
return (config) => {
|
|
51
|
+
const userConfig = api.useResolvedConfigContext();
|
|
52
|
+
if (isUseSSRBundle(userConfig)) {
|
|
47
53
|
var _config_plugins;
|
|
48
54
|
(_config_plugins = config.plugins) === null || _config_plugins === void 0 ? void 0 : _config_plugins.push(path.join(__dirname, "./babel-plugin-ssr-loader-id"));
|
|
49
|
-
if (
|
|
55
|
+
if (checkUseStringSSR(userConfig)) {
|
|
50
56
|
var _config_plugins1;
|
|
51
57
|
(_config_plugins1 = config.plugins) === null || _config_plugins1 === void 0 ? void 0 : _config_plugins1.push(require.resolve("@loadable/babel-plugin"));
|
|
52
58
|
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
55
61
|
}
|
|
56
62
|
})();
|
|
57
63
|
return {
|
|
@@ -67,8 +73,8 @@ export const ssrPlugin = () => ({
|
|
|
67
73
|
},
|
|
68
74
|
tools: {
|
|
69
75
|
bundlerChain(chain, { isServer, isServiceWorker, CHAIN_ID }) {
|
|
70
|
-
const
|
|
71
|
-
if (isUseSSRBundle(
|
|
76
|
+
const userConfig = api.useResolvedConfigContext();
|
|
77
|
+
if (isUseSSRBundle(userConfig) && !isServer && !isServiceWorker && checkUseStringSSR(userConfig)) {
|
|
72
78
|
const LoadableBundlerPlugin = require("./loadable-bundler-plugin.js");
|
|
73
79
|
chain.plugin(CHAIN_ID.PLUGIN.LOADABLE).use(LoadableBundlerPlugin, [
|
|
74
80
|
{
|
|
@@ -77,7 +83,7 @@ export const ssrPlugin = () => ({
|
|
|
77
83
|
]);
|
|
78
84
|
}
|
|
79
85
|
},
|
|
80
|
-
babel:
|
|
86
|
+
babel: babelHandler
|
|
81
87
|
}
|
|
82
88
|
};
|
|
83
89
|
},
|
|
@@ -9,13 +9,12 @@ import helmetReplace from "../helmet";
|
|
|
9
9
|
import { RenderLevel } from "../types";
|
|
10
10
|
import prefetch from "../../prefetch";
|
|
11
11
|
import { ROUTER_DATA_JSON_ID, SSR_DATA_JSON_ID, attributesToString } from "../utils";
|
|
12
|
-
import {
|
|
13
|
-
import { ServerTimingNames } from "../constants";
|
|
12
|
+
import { SSRErrors, SSRTimings, createSSRTracker } from "../tracker";
|
|
14
13
|
import { toFragments } from "./template";
|
|
15
14
|
import { reduce } from "./reduce";
|
|
16
15
|
import * as loadableRenderer from "./loadable";
|
|
17
16
|
import * as styledComponentRenderer from "./styledComponent";
|
|
18
|
-
const buildTemplateData = (context, data, renderLevel,
|
|
17
|
+
const buildTemplateData = (context, data, renderLevel, tracker) => {
|
|
19
18
|
const { request, enableUnsafeCtx } = context;
|
|
20
19
|
const unsafeContext = {
|
|
21
20
|
headers: request.headers
|
|
@@ -32,7 +31,7 @@ const buildTemplateData = (context, data, renderLevel, reporter) => {
|
|
|
32
31
|
...enableUnsafeCtx ? unsafeContext : {}
|
|
33
32
|
},
|
|
34
33
|
reporter: {
|
|
35
|
-
sessionId:
|
|
34
|
+
sessionId: tracker.sessionId
|
|
36
35
|
}
|
|
37
36
|
},
|
|
38
37
|
renderLevel
|
|
@@ -61,7 +60,7 @@ class Entry {
|
|
|
61
60
|
errors: serializeErrors(routerContext.errors)
|
|
62
61
|
} : void 0;
|
|
63
62
|
let html = "";
|
|
64
|
-
const templateData = buildTemplateData(ssrContext, prefetchData, this.result.renderLevel, this.
|
|
63
|
+
const templateData = buildTemplateData(ssrContext, prefetchData, this.result.renderLevel, this.tracker);
|
|
65
64
|
const SSRData = this.getSSRDataScript(templateData, routerData);
|
|
66
65
|
for (const fragment of this.fragments) {
|
|
67
66
|
if (fragment.isVariable && fragment.content === "SSRDataScript") {
|
|
@@ -80,15 +79,10 @@ class Entry {
|
|
|
80
79
|
prefetchData = await prefetch(this.App, context);
|
|
81
80
|
this.result.renderLevel = RenderLevel.SERVER_PREFETCH;
|
|
82
81
|
const prefetchCost = end();
|
|
83
|
-
this.
|
|
84
|
-
this.metrics.emitTimer("app.prefetch.cost", prefetchCost);
|
|
85
|
-
this.reporter.reportTime("app_prefetch_cost", prefetchCost);
|
|
86
|
-
this.severTiming.addServeTiming(ServerTimingNames.SSR_PREFETCH, prefetchCost);
|
|
82
|
+
this.tracker.trackTiming(SSRTimings.SSR_PREFETCH, prefetchCost);
|
|
87
83
|
} catch (e) {
|
|
88
84
|
this.result.renderLevel = RenderLevel.CLIENT_RENDER;
|
|
89
|
-
this.
|
|
90
|
-
this.reporter.reportError("App Prefetch Render", e);
|
|
91
|
-
this.metrics.emitCounter("app.prefetch.render.error", 1);
|
|
85
|
+
this.tracker.trackError(SSRErrors.PREFETCH, e);
|
|
92
86
|
}
|
|
93
87
|
return prefetchData || {};
|
|
94
88
|
}
|
|
@@ -117,15 +111,10 @@ class Entry {
|
|
|
117
111
|
(jsx) => ReactDomServer.renderToString(jsx)
|
|
118
112
|
]);
|
|
119
113
|
const cost = end();
|
|
120
|
-
this.
|
|
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
|
+
this.tracker.trackTiming(SSRTimings.SSR_RENDER_HTML, cost);
|
|
124
115
|
this.result.renderLevel = RenderLevel.SERVER_RENDER;
|
|
125
116
|
} catch (e) {
|
|
126
|
-
this.
|
|
127
|
-
this.reporter.reportError("App Render To HTML", e);
|
|
128
|
-
this.metrics.emitCounter("app.render.html.error", 1);
|
|
117
|
+
this.tracker.trackError(SSRErrors.RENDER_HTML, e);
|
|
129
118
|
}
|
|
130
119
|
return html;
|
|
131
120
|
}
|
|
@@ -150,9 +139,7 @@ class Entry {
|
|
|
150
139
|
_define_property(this, "entryName", void 0);
|
|
151
140
|
_define_property(this, "result", void 0);
|
|
152
141
|
_define_property(this, "metrics", void 0);
|
|
153
|
-
_define_property(this, "
|
|
154
|
-
_define_property(this, "severTiming", void 0);
|
|
155
|
-
_define_property(this, "reporter", void 0);
|
|
142
|
+
_define_property(this, "tracker", void 0);
|
|
156
143
|
_define_property(this, "template", void 0);
|
|
157
144
|
_define_property(this, "App", void 0);
|
|
158
145
|
_define_property(this, "fragments", void 0);
|
|
@@ -167,10 +154,8 @@ class Entry {
|
|
|
167
154
|
this.host = host;
|
|
168
155
|
this.App = options.App;
|
|
169
156
|
this.pluginConfig = config;
|
|
170
|
-
this.
|
|
171
|
-
this.severTiming = ctx.serverTiming;
|
|
157
|
+
this.tracker = createSSRTracker(ctx);
|
|
172
158
|
this.metrics = ctx.metrics;
|
|
173
|
-
this.logger = ctx.logger;
|
|
174
159
|
this.nonce = nonce;
|
|
175
160
|
this.result = {
|
|
176
161
|
renderLevel: RenderLevel.CLIENT_RENDER,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { run } from "@modern-js/utils/runtime-node";
|
|
2
2
|
import { time } from "@modern-js/utils/universal/time";
|
|
3
3
|
import { PreRender } from "../../react/prerender";
|
|
4
|
-
import {
|
|
4
|
+
import { SSRTimings } from "../tracker";
|
|
5
5
|
import SSREntry from "./entry";
|
|
6
6
|
export const render = ({ App, context, config }) => {
|
|
7
7
|
const ssrContext = context.ssrContext;
|
|
@@ -15,10 +15,7 @@ export const render = ({ App, context, config }) => {
|
|
|
15
15
|
const end = time();
|
|
16
16
|
const html = await entry.renderToHtml(context);
|
|
17
17
|
const cost = end();
|
|
18
|
-
entry.
|
|
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);
|
|
18
|
+
entry.tracker.trackTiming(SSRTimings.SSR_RENDER_TOTAL, cost);
|
|
22
19
|
const cacheConfig = PreRender.config();
|
|
23
20
|
if (cacheConfig) {
|
|
24
21
|
context.ssrContext.cacheConfig = cacheConfig;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export var SSRTimings;
|
|
2
|
+
(function(SSRTimings2) {
|
|
3
|
+
SSRTimings2[SSRTimings2["SSR_RENDER_TOTAL"] = 0] = "SSR_RENDER_TOTAL";
|
|
4
|
+
SSRTimings2[SSRTimings2["SSR_PREFETCH"] = 1] = "SSR_PREFETCH";
|
|
5
|
+
SSRTimings2[SSRTimings2["SSR_RENDER_HTML"] = 2] = "SSR_RENDER_HTML";
|
|
6
|
+
})(SSRTimings || (SSRTimings = {}));
|
|
7
|
+
export var SSRErrors;
|
|
8
|
+
(function(SSRErrors2) {
|
|
9
|
+
SSRErrors2[SSRErrors2["PREFETCH"] = 0] = "PREFETCH";
|
|
10
|
+
SSRErrors2[SSRErrors2["RENDER_HTML"] = 1] = "RENDER_HTML";
|
|
11
|
+
})(SSRErrors || (SSRErrors = {}));
|
|
12
|
+
const errors = {
|
|
13
|
+
[SSRErrors.PREFETCH]: {
|
|
14
|
+
reporter: "SSR Error - App Prefetch Render",
|
|
15
|
+
logger: "App Prefetch Render",
|
|
16
|
+
metrics: "app.prefetch.render.error"
|
|
17
|
+
},
|
|
18
|
+
[SSRErrors.RENDER_HTML]: {
|
|
19
|
+
reporter: "SSR Error - App Render To HTML",
|
|
20
|
+
logger: "App Render To HTML",
|
|
21
|
+
metrics: "app.render.html.error"
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const timings = {
|
|
25
|
+
[SSRTimings.SSR_PREFETCH]: {
|
|
26
|
+
reporter: "ssr-prefetch",
|
|
27
|
+
serverTiming: "ssr-prefetch",
|
|
28
|
+
metrics: "app.prefeth.cost",
|
|
29
|
+
logger: "App Prefetch cost = %d ms"
|
|
30
|
+
},
|
|
31
|
+
[SSRTimings.SSR_RENDER_HTML]: {
|
|
32
|
+
reporter: "ssr-render-html",
|
|
33
|
+
serverTiming: "ssr-render-html",
|
|
34
|
+
metrics: "app.render.html.cost",
|
|
35
|
+
logger: "App Render To HTML cost = %d ms"
|
|
36
|
+
},
|
|
37
|
+
[SSRTimings.SSR_RENDER_TOTAL]: {
|
|
38
|
+
reporter: "ssr-render-total",
|
|
39
|
+
serverTiming: "ssr-render-total",
|
|
40
|
+
metrics: "app.render.cost",
|
|
41
|
+
logger: "App Render Total cost = %d ms"
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
export function createSSRTracker({ reporter, serverTiming, metrics, logger }) {
|
|
45
|
+
const tracker = {
|
|
46
|
+
get sessionId() {
|
|
47
|
+
return reporter.sessionId;
|
|
48
|
+
},
|
|
49
|
+
trackError(key, e) {
|
|
50
|
+
const { reporter: reporterContent, metrics: metricsContent, logger: loggerContent } = errors[key];
|
|
51
|
+
reporterContent && reporter.reportError(reporterContent, e);
|
|
52
|
+
metricsContent && metrics.emitCounter(metricsContent, 1);
|
|
53
|
+
loggerContent && logger.error(loggerContent, e);
|
|
54
|
+
},
|
|
55
|
+
trackTiming(key, cost) {
|
|
56
|
+
const { reporter: reporterName, serverTiming: serverTimingName, logger: loggerName, metrics: metricsName } = timings[key];
|
|
57
|
+
reporterName && reporter.reportTiming(reporterName, cost);
|
|
58
|
+
serverTimingName && serverTiming.addServeTiming(serverTimingName, cost);
|
|
59
|
+
metricsName && metrics.emitTimer(metricsName, cost);
|
|
60
|
+
loggerName && logger.debug(loggerName, cost);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
return tracker;
|
|
64
|
+
}
|
|
@@ -8,7 +8,6 @@ export declare const DOCUMENT_SSRDATASCRIPT_PLACEHOLDER: string;
|
|
|
8
8
|
export declare const DOCUMENT_FILE_NAME = "Document";
|
|
9
9
|
export declare const DOCUMENT_SCRIPTS_PLACEHOLDER: string;
|
|
10
10
|
export declare const DOCUMENT_LINKS_PLACEHOLDER: string;
|
|
11
|
-
export declare const DOCUMENT_NO_SCRIPTE_PLACEHOLDER: string;
|
|
12
11
|
export declare const DOCUMENT_SCRIPT_PLACEHOLDER_START: string;
|
|
13
12
|
export declare const DOCUMENT_SCRIPT_PLACEHOLDER_END: string;
|
|
14
13
|
export declare const DOCUMENT_STYLE_PLACEHOLDER_START: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Plugin } from '../core';
|
|
2
|
-
import { SSRPluginConfig } from './serverRender/types';
|
|
2
|
+
import type { SSRPluginConfig } from './serverRender/types';
|
|
3
3
|
export declare const ssr: (config?: SSRPluginConfig) => Plugin;
|
|
4
4
|
export default ssr;
|
|
5
5
|
export * from './react';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RuntimeContext, ModernSSRReactComponent, SSRPluginConfig } from '../types';
|
|
2
|
-
import {
|
|
2
|
+
import { SSRTracker } from '../tracker';
|
|
3
3
|
import { SSRServerContext, RenderResult } from './type';
|
|
4
4
|
type EntryOptions = {
|
|
5
5
|
ctx: SSRServerContext;
|
|
@@ -10,9 +10,7 @@ export default class Entry {
|
|
|
10
10
|
entryName: string;
|
|
11
11
|
result: RenderResult;
|
|
12
12
|
metrics: SSRServerContext['metrics'];
|
|
13
|
-
|
|
14
|
-
severTiming: SSRServerContext['serverTiming'];
|
|
15
|
-
reporter: SSRReporter;
|
|
13
|
+
tracker: SSRTracker;
|
|
16
14
|
private readonly template;
|
|
17
15
|
private readonly App;
|
|
18
16
|
private readonly fragments;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SSRServerContext } from './types';
|
|
2
|
+
export type SSRTracker = ReturnType<typeof createSSRTracker>;
|
|
3
|
+
export declare enum SSRTimings {
|
|
4
|
+
SSR_RENDER_TOTAL = 0,
|
|
5
|
+
SSR_PREFETCH = 1,
|
|
6
|
+
SSR_RENDER_HTML = 2,
|
|
7
|
+
}
|
|
8
|
+
export declare enum SSRErrors {
|
|
9
|
+
PREFETCH = 0,
|
|
10
|
+
RENDER_HTML = 1,
|
|
11
|
+
}
|
|
12
|
+
export declare function createSSRTracker({
|
|
13
|
+
reporter,
|
|
14
|
+
serverTiming,
|
|
15
|
+
metrics,
|
|
16
|
+
logger
|
|
17
|
+
}: SSRServerContext): {
|
|
18
|
+
readonly sessionId: string | undefined;
|
|
19
|
+
trackError(key: SSRErrors, e: Error): void;
|
|
20
|
+
trackTiming(key: SSRTimings, cost: number): void;
|
|
21
|
+
};
|
package/package.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"modern",
|
|
16
16
|
"modern.js"
|
|
17
17
|
],
|
|
18
|
-
"version": "2.
|
|
18
|
+
"version": "2.30.0",
|
|
19
19
|
"engines": {
|
|
20
20
|
"node": ">=14.17.6"
|
|
21
21
|
},
|
|
@@ -173,9 +173,9 @@
|
|
|
173
173
|
"redux-logger": "^3.0.6",
|
|
174
174
|
"styled-components": "^5.3.1",
|
|
175
175
|
"@swc/helpers": "0.5.1",
|
|
176
|
-
"@modern-js/plugin": "2.
|
|
177
|
-
"@modern-js/
|
|
178
|
-
"@modern-js/
|
|
176
|
+
"@modern-js/plugin": "2.30.0",
|
|
177
|
+
"@modern-js/utils": "2.30.0",
|
|
178
|
+
"@modern-js/types": "2.30.0"
|
|
179
179
|
},
|
|
180
180
|
"peerDependencies": {
|
|
181
181
|
"react": ">=17",
|
|
@@ -196,11 +196,11 @@
|
|
|
196
196
|
"ts-jest": "^29.1.0",
|
|
197
197
|
"typescript": "^5",
|
|
198
198
|
"webpack": "^5.88.1",
|
|
199
|
-
"@modern-js/app-tools": "2.
|
|
200
|
-
"@modern-js/core": "2.
|
|
201
|
-
"@modern-js/
|
|
202
|
-
"@scripts/
|
|
203
|
-
"@scripts/
|
|
199
|
+
"@modern-js/app-tools": "2.30.0",
|
|
200
|
+
"@modern-js/server-core": "2.30.0",
|
|
201
|
+
"@modern-js/core": "2.30.0",
|
|
202
|
+
"@scripts/jest-config": "2.30.0",
|
|
203
|
+
"@scripts/build": "2.30.0"
|
|
204
204
|
},
|
|
205
205
|
"sideEffects": false,
|
|
206
206
|
"publishConfig": {
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "createSSRReporter", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return createSSRReporter;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
function createSSRReporter(reporter) {
|
|
12
|
-
const _reporter = {
|
|
13
|
-
get sessionId() {
|
|
14
|
-
return reporter.sessionId;
|
|
15
|
-
},
|
|
16
|
-
get userId() {
|
|
17
|
-
return reporter.userId;
|
|
18
|
-
},
|
|
19
|
-
reportError(content, e) {
|
|
20
|
-
reporter.reportError(`SSR Error - ${content}`, e);
|
|
21
|
-
},
|
|
22
|
-
reportTime(name, cost) {
|
|
23
|
-
reporter.reportTiming(`ssr_${name}`, cost);
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
return _reporter;
|
|
27
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export function createSSRReporter(reporter) {
|
|
2
|
-
var _reporter = {
|
|
3
|
-
get sessionId() {
|
|
4
|
-
return reporter.sessionId;
|
|
5
|
-
},
|
|
6
|
-
get userId() {
|
|
7
|
-
return reporter.userId;
|
|
8
|
-
},
|
|
9
|
-
reportError: function reportError(content, e) {
|
|
10
|
-
reporter.reportError("SSR Error - ".concat(content), e);
|
|
11
|
-
},
|
|
12
|
-
reportTime: function reportTime(name, cost) {
|
|
13
|
-
reporter.reportTiming("ssr_".concat(name), cost);
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
return _reporter;
|
|
17
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
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,8 +0,0 @@
|
|
|
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
|
-
};
|