@modern-js/server-core 2.54.5 → 2.55.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/dist/cjs/index.js +3 -1
- package/dist/cjs/plugins/render/dataHandler.js +3 -2
- package/dist/cjs/plugins/render/index.js +1 -1
- package/dist/cjs/plugins/render/render.js +37 -13
- package/dist/cjs/plugins/render/serverTiming.js +6 -4
- package/dist/cjs/plugins/render/ssrCache.js +72 -83
- package/dist/cjs/plugins/render/ssrRender.js +40 -145
- package/dist/cjs/types/requestHandler.js +16 -0
- package/dist/cjs/utils/transformStream.js +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/plugins/render/dataHandler.js +4 -3
- package/dist/esm/plugins/render/index.js +1 -1
- package/dist/esm/plugins/render/render.js +56 -22
- package/dist/esm/plugins/render/serverTiming.js +12 -4
- package/dist/esm/plugins/render/ssrCache.js +101 -131
- package/dist/esm/plugins/render/ssrRender.js +55 -175
- package/dist/esm/types/requestHandler.js +0 -0
- package/dist/esm/utils/transformStream.js +16 -2
- package/dist/esm-node/index.js +1 -0
- package/dist/esm-node/plugins/render/dataHandler.js +3 -2
- package/dist/esm-node/plugins/render/index.js +1 -1
- package/dist/esm-node/plugins/render/render.js +38 -14
- package/dist/esm-node/plugins/render/serverTiming.js +6 -4
- package/dist/esm-node/plugins/render/ssrCache.js +73 -74
- package/dist/esm-node/plugins/render/ssrRender.js +43 -137
- package/dist/esm-node/types/requestHandler.js +0 -0
- package/dist/esm-node/utils/transformStream.js +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/plugins/render/dataHandler.d.ts +1 -1
- package/dist/types/plugins/render/render.d.ts +3 -2
- package/dist/types/plugins/render/serverTiming.d.ts +3 -2
- package/dist/types/plugins/render/ssrCache.d.ts +7 -11
- package/dist/types/plugins/render/ssrRender.d.ts +10 -10
- package/dist/types/types/config/html.d.ts +11 -0
- package/dist/types/types/config/output.d.ts +8 -0
- package/dist/types/types/requestHandler.d.ts +43 -0
- package/dist/types/types/server.d.ts +7 -2
- package/dist/types/utils/transformStream.d.ts +1 -1
- package/package.json +7 -8
|
@@ -1,42 +1,24 @@
|
|
|
1
1
|
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
|
|
2
2
|
import { _ as _class_call_check } from "@swc/helpers/_/_class_call_check";
|
|
3
|
-
import { _ as _instanceof } from "@swc/helpers/_/_instanceof";
|
|
4
3
|
import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import { X_MODERNJS_RENDER, X_RENDER_CACHE } from "../../constants";
|
|
9
|
-
import { ServerTiming } from "./serverTiming";
|
|
4
|
+
import { MAIN_ENTRY_NAME } from "@modern-js/utils/universal/constants";
|
|
5
|
+
import { parseHeaders, getPathname } from "../../utils";
|
|
6
|
+
import { X_MODERNJS_RENDER } from "../../constants";
|
|
10
7
|
import { matchCacheControl, getCacheResult } from "./ssrCache";
|
|
11
|
-
var
|
|
12
|
-
init: function init() {
|
|
13
|
-
},
|
|
14
|
-
reportError: function reportError() {
|
|
15
|
-
},
|
|
16
|
-
reportTiming: function reportTiming() {
|
|
17
|
-
},
|
|
18
|
-
reportInfo: function reportInfo() {
|
|
19
|
-
},
|
|
20
|
-
reportWarn: function reportWarn() {
|
|
21
|
-
}
|
|
22
|
-
};
|
|
8
|
+
var SERVER_RUNTIME_ENTRY = "requestHandler";
|
|
23
9
|
function ssrRender(request, _) {
|
|
24
10
|
return _ssrRender.apply(this, arguments);
|
|
25
11
|
}
|
|
26
12
|
function _ssrRender() {
|
|
27
13
|
_ssrRender = _async_to_generator(function(request, param) {
|
|
28
|
-
var routeInfo, html,
|
|
14
|
+
var routeInfo, html, userConfig, staticGenerate, nodeReq, serverManifest, locals, params, loaderContext, reporter, cacheConfig, logger, metrics, onError, onTiming, _serverManifest_renderBundles, entryName, loadableStats, routeManifest, headers, key, renderBundle, requestHandler, config, requestHandlerOptions, cacheControl, response;
|
|
29
15
|
return _ts_generator(this, function(_state) {
|
|
30
16
|
switch (_state.label) {
|
|
31
17
|
case 0:
|
|
32
|
-
routeInfo = param.routeInfo, html = param.html, staticGenerate = param.staticGenerate,
|
|
18
|
+
routeInfo = param.routeInfo, html = param.html, userConfig = param.config, staticGenerate = param.staticGenerate, nodeReq = param.nodeReq, serverManifest = param.serverManifest, locals = param.locals, params = param.params, loaderContext = param.loaderContext, reporter = param.reporter, cacheConfig = param.cacheConfig, logger = param.logger, metrics = param.metrics, onError = param.onError, onTiming = param.onTiming;
|
|
33
19
|
entryName = routeInfo.entryName;
|
|
34
20
|
loadableStats = serverManifest.loadableStats || {};
|
|
35
21
|
routeManifest = serverManifest.routeManifest || {};
|
|
36
|
-
host = getHost(request);
|
|
37
|
-
isSpider = isbot.default(request.headers.get("user-agent"));
|
|
38
|
-
responseProxy = new ResponseProxy();
|
|
39
|
-
query = parseQuery(request);
|
|
40
22
|
headers = parseHeaders(request);
|
|
41
23
|
if (nodeReq) {
|
|
42
24
|
for (var key2 in nodeReq.headers) {
|
|
@@ -45,164 +27,82 @@ function _ssrRender() {
|
|
|
45
27
|
}
|
|
46
28
|
}
|
|
47
29
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
30
|
+
renderBundle = (_serverManifest_renderBundles = serverManifest.renderBundles) === null || _serverManifest_renderBundles === void 0 ? void 0 : _serverManifest_renderBundles[entryName || MAIN_ENTRY_NAME];
|
|
31
|
+
if (!renderBundle) {
|
|
32
|
+
throw new Error("Can't found renderBundle ".concat(entryName || MAIN_ENTRY_NAME));
|
|
33
|
+
}
|
|
34
|
+
return [
|
|
35
|
+
4,
|
|
36
|
+
renderBundle[SERVER_RUNTIME_ENTRY]
|
|
37
|
+
];
|
|
38
|
+
case 1:
|
|
39
|
+
requestHandler = _state.sent();
|
|
40
|
+
config = createRequestHandlerConfig(userConfig);
|
|
41
|
+
requestHandlerOptions = {
|
|
42
|
+
resource: {
|
|
43
|
+
route: routeInfo,
|
|
44
|
+
loadableStats,
|
|
45
|
+
routeManifest,
|
|
46
|
+
htmlTemplate: html,
|
|
47
|
+
entryName: entryName || MAIN_ENTRY_NAME
|
|
66
48
|
},
|
|
67
|
-
|
|
68
|
-
template: html,
|
|
69
|
-
loadableStats,
|
|
49
|
+
params,
|
|
70
50
|
loaderContext,
|
|
71
|
-
|
|
72
|
-
|
|
51
|
+
config,
|
|
52
|
+
locals,
|
|
53
|
+
reporter,
|
|
73
54
|
staticGenerate,
|
|
74
55
|
logger,
|
|
75
56
|
metrics,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
/** @deprecated node req */
|
|
79
|
-
req: nodeReq || request,
|
|
80
|
-
/** @deprecated node res */
|
|
81
|
-
res: void 0,
|
|
82
|
-
isSpider,
|
|
83
|
-
nonce
|
|
57
|
+
onError,
|
|
58
|
+
onTiming
|
|
84
59
|
};
|
|
85
|
-
renderBundle = (_serverManifest_renderBundles = serverManifest.renderBundles) === null || _serverManifest_renderBundles === void 0 ? void 0 : _serverManifest_renderBundles[entryName || MAIN_ENTRY_NAME];
|
|
86
|
-
if (!renderBundle) {
|
|
87
|
-
throw new Error("Can't found renderBundle ".concat(entryName || MAIN_ENTRY_NAME));
|
|
88
|
-
}
|
|
89
|
-
runtimeEnv = getRuntimeEnv();
|
|
90
|
-
render = renderBundle[SERVER_RENDER_FUNCTION_NAME];
|
|
91
60
|
return [
|
|
92
61
|
4,
|
|
93
62
|
matchCacheControl(cacheConfig === null || cacheConfig === void 0 ? void 0 : cacheConfig.strategy, nodeReq || new IncomingMessgeProxy(request))
|
|
94
63
|
];
|
|
95
|
-
case
|
|
64
|
+
case 2:
|
|
96
65
|
cacheControl = _state.sent();
|
|
97
66
|
if (!cacheControl)
|
|
98
67
|
return [
|
|
99
68
|
3,
|
|
100
|
-
|
|
69
|
+
4
|
|
101
70
|
];
|
|
102
71
|
return [
|
|
103
72
|
4,
|
|
104
73
|
getCacheResult(request, {
|
|
105
74
|
cacheControl,
|
|
106
75
|
container: cacheConfig === null || cacheConfig === void 0 ? void 0 : cacheConfig.container,
|
|
107
|
-
|
|
108
|
-
|
|
76
|
+
requestHandler,
|
|
77
|
+
requestHandlerOptions
|
|
109
78
|
})
|
|
110
79
|
];
|
|
111
|
-
case 2:
|
|
112
|
-
_ref = _state.sent(), data = _ref.data, status = _ref.status;
|
|
113
|
-
ssrResult = data;
|
|
114
|
-
cacheStatus = status;
|
|
115
|
-
return [
|
|
116
|
-
3,
|
|
117
|
-
5
|
|
118
|
-
];
|
|
119
80
|
case 3:
|
|
81
|
+
response = _state.sent();
|
|
120
82
|
return [
|
|
121
|
-
|
|
122
|
-
|
|
83
|
+
3,
|
|
84
|
+
6
|
|
123
85
|
];
|
|
124
86
|
case 4:
|
|
125
|
-
ssrResult = _state.sent();
|
|
126
|
-
_state.label = 5;
|
|
127
|
-
case 5:
|
|
128
|
-
redirection = ssrContext.redirection;
|
|
129
|
-
if (cacheStatus) {
|
|
130
|
-
responseProxy.headers.set(X_RENDER_CACHE, cacheStatus);
|
|
131
|
-
}
|
|
132
|
-
responseProxy.headers.set(X_MODERNJS_RENDER, "server");
|
|
133
|
-
if (redirection.url) {
|
|
134
|
-
headers1 = responseProxy.headers;
|
|
135
|
-
headers1.set("Location", redirection.url);
|
|
136
|
-
return [
|
|
137
|
-
2,
|
|
138
|
-
new Response(null, {
|
|
139
|
-
status: redirection.status || 302,
|
|
140
|
-
headers: {
|
|
141
|
-
Location: redirection.url
|
|
142
|
-
}
|
|
143
|
-
})
|
|
144
|
-
];
|
|
145
|
-
}
|
|
146
87
|
return [
|
|
147
88
|
4,
|
|
148
|
-
|
|
149
|
-
return {
|
|
150
|
-
Readable: void 0
|
|
151
|
-
};
|
|
152
|
-
})
|
|
89
|
+
requestHandler(request, requestHandlerOptions)
|
|
153
90
|
];
|
|
91
|
+
case 5:
|
|
92
|
+
response = _state.sent();
|
|
93
|
+
_state.label = 6;
|
|
154
94
|
case 6:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (!(runtimeEnv === "node"))
|
|
158
|
-
return [
|
|
159
|
-
3,
|
|
160
|
-
8
|
|
161
|
-
];
|
|
162
|
-
return [
|
|
163
|
-
4,
|
|
164
|
-
import(streamModule).catch(function(_) {
|
|
165
|
-
return {
|
|
166
|
-
createReadableStreamFromReadable: void 0
|
|
167
|
-
};
|
|
168
|
-
})
|
|
169
|
-
];
|
|
170
|
-
case 7:
|
|
171
|
-
_tmp = _state.sent();
|
|
172
|
-
return [
|
|
173
|
-
3,
|
|
174
|
-
9
|
|
175
|
-
];
|
|
176
|
-
case 8:
|
|
177
|
-
_tmp = {
|
|
178
|
-
createReadableStreamFromReadable: void 0
|
|
179
|
-
};
|
|
180
|
-
_state.label = 9;
|
|
181
|
-
case 9:
|
|
182
|
-
createReadableStreamFromReadable = _tmp.createReadableStreamFromReadable;
|
|
183
|
-
data1 = Readable && _instanceof(ssrResult, Readable) ? (createReadableStreamFromReadable === null || createReadableStreamFromReadable === void 0 ? void 0 : createReadableStreamFromReadable(ssrResult)) || "" : ssrResult;
|
|
184
|
-
if (typeof data1 !== "string") {
|
|
185
|
-
responseProxy.headers.set("transfer-encoding", "chunked");
|
|
186
|
-
}
|
|
95
|
+
response.headers.set(X_MODERNJS_RENDER, "server");
|
|
96
|
+
response.headers.set("content-type", "text/html; charset=UTF-8");
|
|
187
97
|
return [
|
|
188
98
|
2,
|
|
189
|
-
|
|
190
|
-
status: responseProxy.status,
|
|
191
|
-
headers: responseProxy.headers
|
|
192
|
-
})
|
|
99
|
+
response
|
|
193
100
|
];
|
|
194
101
|
}
|
|
195
102
|
});
|
|
196
103
|
});
|
|
197
104
|
return _ssrRender.apply(this, arguments);
|
|
198
105
|
}
|
|
199
|
-
var ResponseProxy = function ResponseProxy2() {
|
|
200
|
-
"use strict";
|
|
201
|
-
_class_call_check(this, ResponseProxy2);
|
|
202
|
-
this.headers = new Headers();
|
|
203
|
-
this.status = 200;
|
|
204
|
-
this.headers.set("content-type", "text/html; charset=UTF-8");
|
|
205
|
-
};
|
|
206
106
|
var IncomingMessgeProxy = function IncomingMessgeProxy2(req) {
|
|
207
107
|
"use strict";
|
|
208
108
|
var _this = this;
|
|
@@ -214,38 +114,18 @@ var IncomingMessgeProxy = function IncomingMessgeProxy2(req) {
|
|
|
214
114
|
this.method = req.method;
|
|
215
115
|
this.url = getPathname(req);
|
|
216
116
|
};
|
|
217
|
-
function
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
host = nodeReq.headers.host;
|
|
229
|
-
}
|
|
230
|
-
host = host.split(/\s*,\s*/, 1)[0] || "undefined";
|
|
231
|
-
return host;
|
|
232
|
-
}
|
|
233
|
-
var href = "".concat(getProtocal(), "://").concat(getHost2()).concat(nodeReq.url || "");
|
|
234
|
-
return href;
|
|
235
|
-
}
|
|
236
|
-
function getPathnameFromNodeReq(nodeReq) {
|
|
237
|
-
var url = nodeReq.url;
|
|
238
|
-
if (!url) {
|
|
239
|
-
return "/";
|
|
240
|
-
}
|
|
241
|
-
var match = url.match(/\/[^?]*/);
|
|
242
|
-
var pathname = match ? match[0] : "/";
|
|
243
|
-
if (pathname !== "/" && pathname.endsWith("/")) {
|
|
244
|
-
pathname = pathname.slice(0, -1);
|
|
245
|
-
}
|
|
246
|
-
return pathname;
|
|
117
|
+
function createRequestHandlerConfig(userConfig) {
|
|
118
|
+
var output = userConfig.output, server = userConfig.server, security = userConfig.security, html = userConfig.html;
|
|
119
|
+
return {
|
|
120
|
+
ssr: server === null || server === void 0 ? void 0 : server.ssr,
|
|
121
|
+
ssrByEntries: server === null || server === void 0 ? void 0 : server.ssrByEntries,
|
|
122
|
+
nonce: security === null || security === void 0 ? void 0 : security.nonce,
|
|
123
|
+
enableInlineScripts: output === null || output === void 0 ? void 0 : output.enableInlineScripts,
|
|
124
|
+
enableInlineStyles: output === null || output === void 0 ? void 0 : output.enableInlineStyles,
|
|
125
|
+
crossorigin: html === null || html === void 0 ? void 0 : html.crossorigin,
|
|
126
|
+
scriptLoading: html === null || html === void 0 ? void 0 : html.scriptLoading
|
|
127
|
+
};
|
|
247
128
|
}
|
|
248
129
|
export {
|
|
249
|
-
getPathnameFromNodeReq,
|
|
250
130
|
ssrRender
|
|
251
131
|
};
|
|
File without changes
|
|
@@ -6,17 +6,31 @@ function createTransformStream(fn) {
|
|
|
6
6
|
return new TransformStream({
|
|
7
7
|
transform: function transform(chunk, controller) {
|
|
8
8
|
return _async_to_generator(function() {
|
|
9
|
-
var content, newContent;
|
|
9
|
+
var content, newContent, _tmp;
|
|
10
10
|
return _ts_generator(this, function(_state) {
|
|
11
11
|
switch (_state.label) {
|
|
12
12
|
case 0:
|
|
13
13
|
content = decoder.decode(chunk);
|
|
14
|
+
if (!fn)
|
|
15
|
+
return [
|
|
16
|
+
3,
|
|
17
|
+
2
|
|
18
|
+
];
|
|
14
19
|
return [
|
|
15
20
|
4,
|
|
16
21
|
fn(content)
|
|
17
22
|
];
|
|
18
23
|
case 1:
|
|
19
|
-
|
|
24
|
+
_tmp = _state.sent();
|
|
25
|
+
return [
|
|
26
|
+
3,
|
|
27
|
+
3
|
|
28
|
+
];
|
|
29
|
+
case 2:
|
|
30
|
+
_tmp = content;
|
|
31
|
+
_state.label = 3;
|
|
32
|
+
case 3:
|
|
33
|
+
newContent = _tmp;
|
|
20
34
|
controller.enqueue(encoder.encode(newContent));
|
|
21
35
|
return [
|
|
22
36
|
2
|
package/dist/esm-node/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MAIN_ENTRY_NAME } from "@modern-js/utils/universal/constants";
|
|
2
|
-
const dataHandler = async (request, { routeInfo, serverRoutes, reporter,
|
|
2
|
+
const dataHandler = async (request, { routeInfo, serverRoutes, reporter, onError, onTiming, serverManifest }) => {
|
|
3
3
|
var _serverManifest_loaderBundles;
|
|
4
4
|
const serverLoaderModule = serverManifest === null || serverManifest === void 0 ? void 0 : (_serverManifest_loaderBundles = serverManifest.loaderBundles) === null || _serverManifest_loaderBundles === void 0 ? void 0 : _serverManifest_loaderBundles[routeInfo.entryName || MAIN_ENTRY_NAME];
|
|
5
5
|
if (!serverLoaderModule) {
|
|
@@ -10,9 +10,10 @@ const dataHandler = async (request, { routeInfo, serverRoutes, reporter, logger,
|
|
|
10
10
|
request,
|
|
11
11
|
serverRoutes,
|
|
12
12
|
context: {
|
|
13
|
-
logger,
|
|
14
13
|
reporter
|
|
15
14
|
},
|
|
15
|
+
onTiming,
|
|
16
|
+
onError,
|
|
16
17
|
routes
|
|
17
18
|
});
|
|
18
19
|
return response;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { cutNameByHyphen } from "@modern-js/utils/universal";
|
|
2
2
|
import { TrieRouter } from "hono/router/trie-router";
|
|
3
|
-
import { parseQuery, getPathname, createErrorHtml, sortRoutes, transformResponse, onError as onErrorFn, ErrorDigest } from "../../utils";
|
|
3
|
+
import { parseQuery, getPathname, createErrorHtml, sortRoutes, transformResponse, onError as onErrorFn, ErrorDigest, parseHeaders } from "../../utils";
|
|
4
4
|
import { REPLACE_REG, X_MODERNJS_RENDER } from "../../constants";
|
|
5
5
|
import { dataHandler } from "./dataHandler";
|
|
6
6
|
import { ssrRender } from "./ssrRender";
|
|
7
|
+
import { ServerTiming } from "./serverTiming";
|
|
7
8
|
const DYNAMIC_ROUTE_REG = /\/:./;
|
|
8
9
|
function getRouter(routes) {
|
|
9
10
|
const dynamicRoutes = [];
|
|
@@ -33,7 +34,16 @@ function matchRoute(router, request) {
|
|
|
33
34
|
const result = matched[0][0];
|
|
34
35
|
return result || [];
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
function getHeadersWithoutCookie(headers) {
|
|
38
|
+
const _headers = {
|
|
39
|
+
...headers,
|
|
40
|
+
cookie: void 0
|
|
41
|
+
};
|
|
42
|
+
delete _headers.cookie;
|
|
43
|
+
return _headers;
|
|
44
|
+
}
|
|
45
|
+
const SERVER_TIMING = "Server-Timing";
|
|
46
|
+
async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig, forceCSR, config, onFallback: onFallbackFn }) {
|
|
37
47
|
const router = getRouter(routes);
|
|
38
48
|
return async (req, { logger, nodeReq, reporter, templates, serverManifest, locals, metrics, loaderContext }) => {
|
|
39
49
|
const [routeInfo, params] = matchRoute(router, req);
|
|
@@ -62,7 +72,17 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
|
|
|
62
72
|
});
|
|
63
73
|
}
|
|
64
74
|
const renderMode = await getRenderMode(req, metaName || "modern-js", routeInfo.isSSR, forceCSR, nodeReq, onFallback);
|
|
65
|
-
const
|
|
75
|
+
const pathname = getPathname(req);
|
|
76
|
+
const headerData = parseHeaders(req);
|
|
77
|
+
const serverTimingInstance = new ServerTiming(metaName || "modern");
|
|
78
|
+
const onError = (e) => {
|
|
79
|
+
logger.error(`SSR Error - ${e instanceof Error ? e.name : e}, error = %s, req.url = %s, req.headers = %o`, e instanceof Error ? e.stack || e.message : e, pathname, getHeadersWithoutCookie(headerData));
|
|
80
|
+
};
|
|
81
|
+
const onTiming = (name, dur) => {
|
|
82
|
+
logger.debug(`SSR Debug - ${name}, cost = %s, req.url = %s`, dur, pathname);
|
|
83
|
+
serverTimingInstance.addServeTiming(name, dur);
|
|
84
|
+
};
|
|
85
|
+
const onBoundError = async (e) => {
|
|
66
86
|
onErrorFn(ErrorDigest.ERENDER, e, logger, req);
|
|
67
87
|
await (onFallback === null || onFallback === void 0 ? void 0 : onFallback("error", e));
|
|
68
88
|
};
|
|
@@ -71,32 +91,36 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
|
|
|
71
91
|
html,
|
|
72
92
|
routeInfo,
|
|
73
93
|
staticGenerate: staticGenerate || false,
|
|
74
|
-
|
|
75
|
-
nonce,
|
|
76
|
-
logger,
|
|
94
|
+
config,
|
|
77
95
|
nodeReq,
|
|
78
96
|
cacheConfig,
|
|
79
97
|
reporter,
|
|
80
98
|
serverRoutes: routes,
|
|
81
99
|
params,
|
|
100
|
+
logger,
|
|
101
|
+
metrics,
|
|
82
102
|
locals,
|
|
83
103
|
serverManifest,
|
|
84
|
-
|
|
85
|
-
|
|
104
|
+
loaderContext: loaderContext || /* @__PURE__ */ new Map(),
|
|
105
|
+
onError,
|
|
106
|
+
onTiming
|
|
86
107
|
};
|
|
108
|
+
let response;
|
|
87
109
|
switch (renderMode) {
|
|
88
110
|
case "data":
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
response = await renderHandler(req, renderOptions, "ssr", onError);
|
|
92
|
-
}
|
|
93
|
-
return response;
|
|
111
|
+
response = await dataHandler(req, renderOptions) || await renderHandler(req, renderOptions, "ssr", onBoundError);
|
|
112
|
+
break;
|
|
94
113
|
case "ssr":
|
|
95
114
|
case "csr":
|
|
96
|
-
|
|
115
|
+
response = await renderHandler(req, renderOptions, renderMode, onBoundError);
|
|
116
|
+
break;
|
|
97
117
|
default:
|
|
98
118
|
throw new Error(`Unknown render mode: ${renderMode}`);
|
|
99
119
|
}
|
|
120
|
+
serverTimingInstance.headers.forEach((value) => {
|
|
121
|
+
response.headers.append(SERVER_TIMING, value);
|
|
122
|
+
});
|
|
123
|
+
return response;
|
|
100
124
|
};
|
|
101
125
|
}
|
|
102
126
|
async function renderHandler(request, options, mode, onError) {
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
const SERVER_TIMING = "Server-Timing";
|
|
2
1
|
class ServerTiming {
|
|
2
|
+
get headers() {
|
|
3
|
+
return this.headerList;
|
|
4
|
+
}
|
|
3
5
|
addServeTiming(name, dur, desc) {
|
|
4
6
|
const _name = `bd-${this.meta}-${name}`;
|
|
5
7
|
const value = `${_name};${desc ? `decs="${desc}";` : ""} dur=${dur}`;
|
|
6
|
-
this.
|
|
8
|
+
this.headerList.push(value);
|
|
7
9
|
return this;
|
|
8
10
|
}
|
|
9
|
-
constructor(
|
|
11
|
+
constructor(meta) {
|
|
12
|
+
this.headerList = [];
|
|
10
13
|
this.meta = meta;
|
|
11
|
-
this.headers = headers;
|
|
12
14
|
}
|
|
13
15
|
}
|
|
14
16
|
export {
|
|
@@ -1,70 +1,40 @@
|
|
|
1
1
|
import { createMemoryStorage } from "@modern-js/runtime-utils/storer";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
const cache = {
|
|
12
|
-
val: renderResult,
|
|
13
|
-
cursor: current
|
|
14
|
-
};
|
|
15
|
-
await container.set(key, JSON.stringify(cache), {
|
|
16
|
-
ttl
|
|
17
|
-
});
|
|
18
|
-
return {
|
|
19
|
-
data: renderResult,
|
|
20
|
-
status
|
|
21
|
-
};
|
|
22
|
-
} else {
|
|
23
|
-
const { Readable } = await import("stream").catch((_) => ({
|
|
24
|
-
Readable: void 0
|
|
25
|
-
}));
|
|
26
|
-
const runtimeEnv = getRuntimeEnv();
|
|
27
|
-
const streamModule = "../../adapters/node/polyfills/stream";
|
|
28
|
-
const { createReadableStreamFromReadable } = runtimeEnv === "node" ? await import(streamModule).catch((_) => ({
|
|
29
|
-
createReadableStreamFromReadable: void 0
|
|
30
|
-
})) : {
|
|
31
|
-
createReadableStreamFromReadable: void 0
|
|
32
|
-
};
|
|
33
|
-
const body = (
|
|
34
|
-
// TODO: remove node:stream, move it to ssr entry.
|
|
35
|
-
Readable && renderResult instanceof Readable ? createReadableStreamFromReadable === null || createReadableStreamFromReadable === void 0 ? void 0 : createReadableStreamFromReadable(renderResult) : renderResult
|
|
36
|
-
);
|
|
2
|
+
import { X_RENDER_CACHE } from "../../constants";
|
|
3
|
+
import { createTransformStream, getPathname } from "../../utils";
|
|
4
|
+
async function processCache({ request, key, requestHandler, requestHandlerOptions, ttl, container, cacheStatus }) {
|
|
5
|
+
const response = await requestHandler(request, requestHandlerOptions);
|
|
6
|
+
const decoder = new TextDecoder();
|
|
7
|
+
if (response.body) {
|
|
8
|
+
const stream = createTransformStream();
|
|
9
|
+
const reader = response.body.getReader();
|
|
10
|
+
const writer = stream.writable.getWriter();
|
|
37
11
|
let html = "";
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
12
|
+
const push = () => reader.read().then(({ done, value }) => {
|
|
13
|
+
if (done) {
|
|
14
|
+
const current = Date.now();
|
|
15
|
+
const cache = {
|
|
16
|
+
val: html,
|
|
17
|
+
cursor: current
|
|
18
|
+
};
|
|
19
|
+
container.set(key, JSON.stringify(cache), {
|
|
20
|
+
ttl
|
|
21
|
+
});
|
|
22
|
+
writer.close();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const content = decoder.decode(value);
|
|
26
|
+
html += content;
|
|
27
|
+
writer.write(value);
|
|
28
|
+
push();
|
|
41
29
|
});
|
|
42
|
-
const reader = body.getReader();
|
|
43
|
-
const writer = stream.writable.getWriter();
|
|
44
|
-
const push = () => {
|
|
45
|
-
reader.read().then(({ done, value }) => {
|
|
46
|
-
if (done) {
|
|
47
|
-
const current = Date.now();
|
|
48
|
-
const cache = {
|
|
49
|
-
val: html,
|
|
50
|
-
cursor: current
|
|
51
|
-
};
|
|
52
|
-
container.set(key, JSON.stringify(cache), {
|
|
53
|
-
ttl
|
|
54
|
-
});
|
|
55
|
-
writer.close();
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
writer.write(value);
|
|
59
|
-
push();
|
|
60
|
-
});
|
|
61
|
-
};
|
|
62
30
|
push();
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
status
|
|
66
|
-
|
|
31
|
+
cacheStatus && response.headers.set(X_RENDER_CACHE, cacheStatus);
|
|
32
|
+
return new Response(stream.readable, {
|
|
33
|
+
status: response.status,
|
|
34
|
+
headers: response.headers
|
|
35
|
+
});
|
|
67
36
|
}
|
|
37
|
+
return response;
|
|
68
38
|
}
|
|
69
39
|
const CACHE_NAMESPACE = "__ssr__cache";
|
|
70
40
|
const storage = createMemoryStorage(CACHE_NAMESPACE);
|
|
@@ -111,7 +81,7 @@ function matchCacheControl(cacheOption, req) {
|
|
|
111
81
|
}
|
|
112
82
|
}
|
|
113
83
|
async function getCacheResult(request, options) {
|
|
114
|
-
const { cacheControl,
|
|
84
|
+
const { cacheControl, container = storage, requestHandler, requestHandlerOptions } = options;
|
|
115
85
|
const key = computedKey(request, cacheControl);
|
|
116
86
|
const value = await container.get(key);
|
|
117
87
|
const { maxAge, staleWhileRevalidate } = cacheControl;
|
|
@@ -120,21 +90,50 @@ async function getCacheResult(request, options) {
|
|
|
120
90
|
const cache = JSON.parse(value);
|
|
121
91
|
const interval = Date.now() - cache.cursor;
|
|
122
92
|
if (interval <= maxAge) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
93
|
+
const cacheStatus = "hit";
|
|
94
|
+
return new Response(cache.val, {
|
|
95
|
+
headers: {
|
|
96
|
+
[X_RENDER_CACHE]: cacheStatus
|
|
97
|
+
}
|
|
98
|
+
});
|
|
127
99
|
} else if (interval <= staleWhileRevalidate + maxAge) {
|
|
128
|
-
processCache(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
100
|
+
processCache({
|
|
101
|
+
key,
|
|
102
|
+
request,
|
|
103
|
+
requestHandler,
|
|
104
|
+
requestHandlerOptions,
|
|
105
|
+
ttl,
|
|
106
|
+
container
|
|
107
|
+
}).then(async (response) => {
|
|
108
|
+
await response.text();
|
|
109
|
+
});
|
|
110
|
+
const cacheStatus = "stale";
|
|
111
|
+
return new Response(cache.val, {
|
|
112
|
+
headers: {
|
|
113
|
+
[X_RENDER_CACHE]: cacheStatus
|
|
114
|
+
}
|
|
115
|
+
});
|
|
133
116
|
} else {
|
|
134
|
-
return processCache(
|
|
117
|
+
return processCache({
|
|
118
|
+
key,
|
|
119
|
+
request,
|
|
120
|
+
requestHandler,
|
|
121
|
+
requestHandlerOptions,
|
|
122
|
+
ttl,
|
|
123
|
+
container,
|
|
124
|
+
cacheStatus: "expired"
|
|
125
|
+
});
|
|
135
126
|
}
|
|
136
127
|
} else {
|
|
137
|
-
return processCache(
|
|
128
|
+
return processCache({
|
|
129
|
+
key,
|
|
130
|
+
request,
|
|
131
|
+
requestHandler,
|
|
132
|
+
requestHandlerOptions,
|
|
133
|
+
ttl,
|
|
134
|
+
container,
|
|
135
|
+
cacheStatus: "miss"
|
|
136
|
+
});
|
|
138
137
|
}
|
|
139
138
|
}
|
|
140
139
|
export {
|