@modern-js/server-core 2.49.1 → 2.49.3-alpha.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/base/adapters/node/bff.js +1 -1
- package/dist/cjs/base/adapters/node/middlewares/serverManifest.js +26 -25
- package/dist/cjs/base/index.js +4 -0
- package/dist/cjs/base/middlewares/customServer/context.js +3 -4
- package/dist/cjs/base/middlewares/renderHandler/index.js +11 -3
- package/dist/cjs/base/middlewares/renderHandler/render.js +33 -7
- package/dist/cjs/base/utils/error.js +17 -2
- package/dist/cjs/core/plugin.js +2 -0
- package/dist/esm/base/adapters/node/bff.js +1 -1
- package/dist/esm/base/adapters/node/middlewares/serverManifest.js +60 -30
- package/dist/esm/base/index.js +3 -1
- package/dist/esm/base/middlewares/customServer/context.js +3 -3
- package/dist/esm/base/middlewares/renderHandler/index.js +31 -5
- package/dist/esm/base/middlewares/renderHandler/render.js +181 -39
- package/dist/esm/base/utils/error.js +15 -1
- package/dist/esm/core/plugin.js +2 -0
- package/dist/esm-node/base/adapters/node/bff.js +1 -1
- package/dist/esm-node/base/adapters/node/middlewares/serverManifest.js +27 -26
- package/dist/esm-node/base/index.js +3 -1
- package/dist/esm-node/base/middlewares/customServer/context.js +3 -4
- package/dist/esm-node/base/middlewares/renderHandler/index.js +11 -3
- package/dist/esm-node/base/middlewares/renderHandler/render.js +34 -8
- package/dist/esm-node/base/utils/error.js +14 -1
- package/dist/esm-node/core/plugin.js +2 -0
- package/dist/types/base/adapters/node/middlewares/serverManifest.d.ts +2 -2
- package/dist/types/base/index.d.ts +1 -1
- package/dist/types/base/middlewares/renderHandler/index.d.ts +1 -1
- package/dist/types/base/middlewares/renderHandler/render.d.ts +9 -2
- package/dist/types/base/utils/error.d.ts +7 -0
- package/dist/types/core/plugin.d.ts +51 -2
- package/package.json +7 -7
|
@@ -2,7 +2,7 @@ import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
|
|
|
2
2
|
import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
|
|
3
3
|
import { cutNameByHyphen } from "@modern-js/utils/universal";
|
|
4
4
|
import { REPLACE_REG } from "../../../base/constants";
|
|
5
|
-
import { createErrorHtml, sortRoutes, parseQuery, transformResponse, getPathname } from "../../utils";
|
|
5
|
+
import { createErrorHtml, sortRoutes, parseQuery, transformResponse, getPathname, onError as onErrorFn, ErrorDigest } from "../../utils";
|
|
6
6
|
import { dataHandler } from "./dataHandler";
|
|
7
7
|
import { ssrRender } from "./ssrRender";
|
|
8
8
|
function createRender(_) {
|
|
@@ -10,19 +10,36 @@ function createRender(_) {
|
|
|
10
10
|
}
|
|
11
11
|
function _createRender() {
|
|
12
12
|
_createRender = _async_to_generator(function(param) {
|
|
13
|
-
var routes, pwd, metaName, staticGenerate, forceCSR, nonce;
|
|
13
|
+
var routes, pwd, metaName, staticGenerate, forceCSR, nonce, onFallbackFn;
|
|
14
14
|
return _ts_generator(this, function(_state) {
|
|
15
|
-
routes = param.routes, pwd = param.pwd, metaName = param.metaName, staticGenerate = param.staticGenerate, forceCSR = param.forceCSR, nonce = param.nonce;
|
|
15
|
+
routes = param.routes, pwd = param.pwd, metaName = param.metaName, staticGenerate = param.staticGenerate, forceCSR = param.forceCSR, nonce = param.nonce, onFallbackFn = param.onFallback;
|
|
16
16
|
return [
|
|
17
17
|
2,
|
|
18
18
|
function() {
|
|
19
19
|
var _ref = _async_to_generator(function(req, param2) {
|
|
20
|
-
var logger, nodeReq, reporter, templates, serverManifest, locals, metrics, routeInfo, html, renderMode, renderOptions, response;
|
|
20
|
+
var logger, nodeReq, reporter, templates, serverManifest, locals, metrics, routeInfo, onFallback, html, renderMode, onError, renderOptions, response;
|
|
21
21
|
return _ts_generator(this, function(_state2) {
|
|
22
22
|
switch (_state2.label) {
|
|
23
23
|
case 0:
|
|
24
24
|
logger = param2.logger, nodeReq = param2.nodeReq, reporter = param2.reporter, templates = param2.templates, serverManifest = param2.serverManifest, locals = param2.locals, metrics = param2.metrics;
|
|
25
25
|
routeInfo = matchRoute(req, routes);
|
|
26
|
+
onFallback = function() {
|
|
27
|
+
var _ref2 = _async_to_generator(function(reason, error) {
|
|
28
|
+
return _ts_generator(this, function(_state3) {
|
|
29
|
+
return [
|
|
30
|
+
2,
|
|
31
|
+
onFallbackFn === null || onFallbackFn === void 0 ? void 0 : onFallbackFn(reason, {
|
|
32
|
+
logger,
|
|
33
|
+
reporter,
|
|
34
|
+
metrics
|
|
35
|
+
}, error)
|
|
36
|
+
];
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
return function onFallback2(reason, error) {
|
|
40
|
+
return _ref2.apply(this, arguments);
|
|
41
|
+
};
|
|
42
|
+
}();
|
|
26
43
|
if (!routeInfo) {
|
|
27
44
|
return [
|
|
28
45
|
2,
|
|
@@ -46,7 +63,34 @@ function _createRender() {
|
|
|
46
63
|
})
|
|
47
64
|
];
|
|
48
65
|
}
|
|
49
|
-
|
|
66
|
+
return [
|
|
67
|
+
4,
|
|
68
|
+
getRenderMode(req, metaName || "modern-js", routeInfo.isSSR, forceCSR, nodeReq, onFallback)
|
|
69
|
+
];
|
|
70
|
+
case 1:
|
|
71
|
+
renderMode = _state2.sent();
|
|
72
|
+
onError = function() {
|
|
73
|
+
var _ref2 = _async_to_generator(function(e) {
|
|
74
|
+
return _ts_generator(this, function(_state3) {
|
|
75
|
+
switch (_state3.label) {
|
|
76
|
+
case 0:
|
|
77
|
+
onErrorFn(logger, ErrorDigest.ERENDER, e, req);
|
|
78
|
+
return [
|
|
79
|
+
4,
|
|
80
|
+
onFallback === null || onFallback === void 0 ? void 0 : onFallback("error", e)
|
|
81
|
+
];
|
|
82
|
+
case 1:
|
|
83
|
+
_state3.sent();
|
|
84
|
+
return [
|
|
85
|
+
2
|
|
86
|
+
];
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
return function onError2(e) {
|
|
91
|
+
return _ref2.apply(this, arguments);
|
|
92
|
+
};
|
|
93
|
+
}();
|
|
50
94
|
renderOptions = {
|
|
51
95
|
pwd,
|
|
52
96
|
html,
|
|
@@ -66,55 +110,55 @@ function _createRender() {
|
|
|
66
110
|
case "data":
|
|
67
111
|
return [
|
|
68
112
|
3,
|
|
69
|
-
|
|
113
|
+
2
|
|
70
114
|
];
|
|
71
115
|
case "ssr":
|
|
72
116
|
return [
|
|
73
117
|
3,
|
|
74
|
-
|
|
118
|
+
6
|
|
75
119
|
];
|
|
76
120
|
case "csr":
|
|
77
121
|
return [
|
|
78
122
|
3,
|
|
79
|
-
|
|
123
|
+
6
|
|
80
124
|
];
|
|
81
125
|
}
|
|
82
126
|
return [
|
|
83
127
|
3,
|
|
84
|
-
|
|
128
|
+
7
|
|
85
129
|
];
|
|
86
|
-
case
|
|
130
|
+
case 2:
|
|
87
131
|
return [
|
|
88
132
|
4,
|
|
89
133
|
dataHandler(req, renderOptions)
|
|
90
134
|
];
|
|
91
|
-
case
|
|
135
|
+
case 3:
|
|
92
136
|
response = _state2.sent();
|
|
93
137
|
if (!!response)
|
|
94
138
|
return [
|
|
95
139
|
3,
|
|
96
|
-
|
|
140
|
+
5
|
|
97
141
|
];
|
|
98
142
|
return [
|
|
99
143
|
4,
|
|
100
|
-
renderHandler(req, renderOptions, "ssr")
|
|
144
|
+
renderHandler(req, renderOptions, "ssr", onError)
|
|
101
145
|
];
|
|
102
|
-
case 3:
|
|
103
|
-
response = _state2.sent();
|
|
104
|
-
_state2.label = 4;
|
|
105
146
|
case 4:
|
|
147
|
+
response = _state2.sent();
|
|
148
|
+
_state2.label = 5;
|
|
149
|
+
case 5:
|
|
106
150
|
return [
|
|
107
151
|
2,
|
|
108
152
|
response
|
|
109
153
|
];
|
|
110
|
-
case
|
|
154
|
+
case 6:
|
|
111
155
|
return [
|
|
112
156
|
2,
|
|
113
|
-
renderHandler(req, renderOptions, renderMode)
|
|
157
|
+
renderHandler(req, renderOptions, renderMode, onError)
|
|
114
158
|
];
|
|
115
|
-
case 6:
|
|
116
|
-
throw new Error("Unknown render mode: ".concat(renderMode));
|
|
117
159
|
case 7:
|
|
160
|
+
throw new Error("Unknown render mode: ".concat(renderMode));
|
|
161
|
+
case 8:
|
|
118
162
|
return [
|
|
119
163
|
2
|
|
120
164
|
];
|
|
@@ -130,12 +174,12 @@ function _createRender() {
|
|
|
130
174
|
});
|
|
131
175
|
return _createRender.apply(this, arguments);
|
|
132
176
|
}
|
|
133
|
-
function renderHandler(request, options, mode) {
|
|
177
|
+
function renderHandler(request, options, mode, onError) {
|
|
134
178
|
return _renderHandler.apply(this, arguments);
|
|
135
179
|
}
|
|
136
180
|
function _renderHandler() {
|
|
137
|
-
_renderHandler = _async_to_generator(function(request, options, mode) {
|
|
138
|
-
var serverData, response;
|
|
181
|
+
_renderHandler = _async_to_generator(function(request, options, mode, onError) {
|
|
182
|
+
var serverData, response, e;
|
|
139
183
|
return _ts_generator(this, function(_state) {
|
|
140
184
|
switch (_state.label) {
|
|
141
185
|
case 0:
|
|
@@ -145,12 +189,51 @@ function _renderHandler() {
|
|
|
145
189
|
params: {}
|
|
146
190
|
}
|
|
147
191
|
};
|
|
192
|
+
if (!(mode === "ssr"))
|
|
193
|
+
return [
|
|
194
|
+
3,
|
|
195
|
+
6
|
|
196
|
+
];
|
|
197
|
+
_state.label = 1;
|
|
198
|
+
case 1:
|
|
199
|
+
_state.trys.push([
|
|
200
|
+
1,
|
|
201
|
+
3,
|
|
202
|
+
,
|
|
203
|
+
5
|
|
204
|
+
]);
|
|
148
205
|
return [
|
|
149
206
|
4,
|
|
150
|
-
|
|
207
|
+
ssrRender(request, options)
|
|
151
208
|
];
|
|
152
|
-
case
|
|
209
|
+
case 2:
|
|
153
210
|
response = _state.sent();
|
|
211
|
+
return [
|
|
212
|
+
3,
|
|
213
|
+
5
|
|
214
|
+
];
|
|
215
|
+
case 3:
|
|
216
|
+
e = _state.sent();
|
|
217
|
+
return [
|
|
218
|
+
4,
|
|
219
|
+
onError(e)
|
|
220
|
+
];
|
|
221
|
+
case 4:
|
|
222
|
+
_state.sent();
|
|
223
|
+
response = csrRender(options.html);
|
|
224
|
+
return [
|
|
225
|
+
3,
|
|
226
|
+
5
|
|
227
|
+
];
|
|
228
|
+
case 5:
|
|
229
|
+
return [
|
|
230
|
+
3,
|
|
231
|
+
7
|
|
232
|
+
];
|
|
233
|
+
case 6:
|
|
234
|
+
response = csrRender(options.html);
|
|
235
|
+
_state.label = 7;
|
|
236
|
+
case 7:
|
|
154
237
|
return [
|
|
155
238
|
2,
|
|
156
239
|
transformResponse(response, injectServerData(serverData))
|
|
@@ -187,20 +270,79 @@ function matchRoute(req, routes) {
|
|
|
187
270
|
}
|
|
188
271
|
return void 0;
|
|
189
272
|
}
|
|
190
|
-
function getRenderMode(req, framework, isSSR, forceCSR, nodeReq) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
273
|
+
function getRenderMode(req, framework, isSSR, forceCSR, nodeReq, onFallback) {
|
|
274
|
+
return _getRenderMode.apply(this, arguments);
|
|
275
|
+
}
|
|
276
|
+
function _getRenderMode() {
|
|
277
|
+
_getRenderMode = _async_to_generator(function(req, framework, isSSR, forceCSR, nodeReq, onFallback) {
|
|
278
|
+
var query, fallbackHeader;
|
|
279
|
+
return _ts_generator(this, function(_state) {
|
|
280
|
+
switch (_state.label) {
|
|
281
|
+
case 0:
|
|
282
|
+
query = parseQuery(req);
|
|
283
|
+
fallbackHeader = "x-".concat(cutNameByHyphen(framework), "-ssr-fallback");
|
|
284
|
+
if (!isSSR)
|
|
285
|
+
return [
|
|
286
|
+
3,
|
|
287
|
+
6
|
|
288
|
+
];
|
|
289
|
+
if (query.__loader) {
|
|
290
|
+
return [
|
|
291
|
+
2,
|
|
292
|
+
"data"
|
|
293
|
+
];
|
|
294
|
+
}
|
|
295
|
+
if (!(forceCSR && (query.csr || req.headers.get(fallbackHeader) || (nodeReq === null || nodeReq === void 0 ? void 0 : nodeReq.headers[fallbackHeader]))))
|
|
296
|
+
return [
|
|
297
|
+
3,
|
|
298
|
+
5
|
|
299
|
+
];
|
|
300
|
+
if (!query.csr)
|
|
301
|
+
return [
|
|
302
|
+
3,
|
|
303
|
+
2
|
|
304
|
+
];
|
|
305
|
+
return [
|
|
306
|
+
4,
|
|
307
|
+
onFallback === null || onFallback === void 0 ? void 0 : onFallback("query")
|
|
308
|
+
];
|
|
309
|
+
case 1:
|
|
310
|
+
_state.sent();
|
|
311
|
+
return [
|
|
312
|
+
3,
|
|
313
|
+
4
|
|
314
|
+
];
|
|
315
|
+
case 2:
|
|
316
|
+
return [
|
|
317
|
+
4,
|
|
318
|
+
onFallback === null || onFallback === void 0 ? void 0 : onFallback("header")
|
|
319
|
+
];
|
|
320
|
+
case 3:
|
|
321
|
+
_state.sent();
|
|
322
|
+
_state.label = 4;
|
|
323
|
+
case 4:
|
|
324
|
+
return [
|
|
325
|
+
2,
|
|
326
|
+
"csr"
|
|
327
|
+
];
|
|
328
|
+
case 5:
|
|
329
|
+
return [
|
|
330
|
+
2,
|
|
331
|
+
"ssr"
|
|
332
|
+
];
|
|
333
|
+
case 6:
|
|
334
|
+
return [
|
|
335
|
+
2,
|
|
336
|
+
"csr"
|
|
337
|
+
];
|
|
338
|
+
case 7:
|
|
339
|
+
return [
|
|
340
|
+
2
|
|
341
|
+
];
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
return _getRenderMode.apply(this, arguments);
|
|
204
346
|
}
|
|
205
347
|
function csrRender(html) {
|
|
206
348
|
return new Response(html, {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { _ as _instanceof } from "@swc/helpers/_/_instanceof";
|
|
1
2
|
var ERROR_PAGE_TEXT = {
|
|
2
3
|
404: "This page could not be found.",
|
|
3
4
|
500: "Internal Server Error."
|
|
@@ -7,6 +8,19 @@ var createErrorHtml = function(status) {
|
|
|
7
8
|
var title = "".concat(status, ": ").concat(text);
|
|
8
9
|
return '<!DOCTYPE html>\n <html lang="en">\n <head>\n <meta charset="utf-8">\n <meta name="viewport" content="width=device-width">\n <title>'.concat(title, '</title>\n <style>\n html,body {\n margin: 0;\n }\n\n .page-container {\n color: #000;\n background: #fff;\n height: 100vh;\n text-align: center;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n }\n </style>\n </head>\n <body>\n <div class="page-container">\n <h1>').concat(status, "</h1>\n <div>").concat(text, "</div>\n </body>\n </html>\n ");
|
|
9
10
|
};
|
|
11
|
+
var ErrorDigest;
|
|
12
|
+
(function(ErrorDigest2) {
|
|
13
|
+
ErrorDigest2["ENOTF"] = "Page could not be found";
|
|
14
|
+
ErrorDigest2["EINTER"] = "Internal server error";
|
|
15
|
+
ErrorDigest2["ERENDER"] = "SSR render failed";
|
|
16
|
+
})(ErrorDigest || (ErrorDigest = {}));
|
|
17
|
+
function onError(logger, digest, error, req) {
|
|
18
|
+
var headers = req === null || req === void 0 ? void 0 : req.headers;
|
|
19
|
+
headers === null || headers === void 0 ? void 0 : headers.delete("cookie");
|
|
20
|
+
logger.error(req ? "Server Error - ".concat(digest, ", error = %s, req.url = %s, req.headers = %o") : "Server Error - ".concat(digest, ", error = %s"), _instanceof(error, Error) ? error.stack || error.message : error, req === null || req === void 0 ? void 0 : req.url, headers);
|
|
21
|
+
}
|
|
10
22
|
export {
|
|
11
|
-
|
|
23
|
+
ErrorDigest,
|
|
24
|
+
createErrorHtml,
|
|
25
|
+
onError
|
|
12
26
|
};
|
package/dist/esm/core/plugin.js
CHANGED
|
@@ -3,6 +3,7 @@ var gather = createParallelWorkflow();
|
|
|
3
3
|
var config = createWaterfall();
|
|
4
4
|
var prepare = createWaterfall();
|
|
5
5
|
var prepareWebServer = createAsyncPipeline();
|
|
6
|
+
var fallback = createParallelWorkflow();
|
|
6
7
|
var prepareApiServer = createAsyncPipeline();
|
|
7
8
|
var onApiChange = createAsyncWaterfall();
|
|
8
9
|
var repack = createWaterfall();
|
|
@@ -32,6 +33,7 @@ var serverHooks = {
|
|
|
32
33
|
gather,
|
|
33
34
|
config,
|
|
34
35
|
prepare,
|
|
36
|
+
fallback,
|
|
35
37
|
prepareWebServer,
|
|
36
38
|
prepareApiServer,
|
|
37
39
|
repack,
|
|
@@ -21,7 +21,7 @@ const bindBFFHandler = async (server, options) => {
|
|
|
21
21
|
await next();
|
|
22
22
|
};
|
|
23
23
|
} else {
|
|
24
|
-
const renderHandler = enableHandleWeb ? await getRenderHandler(options) : null;
|
|
24
|
+
const renderHandler = enableHandleWeb ? await getRenderHandler(options, server) : null;
|
|
25
25
|
handler = await server.runner.prepareApiServer({
|
|
26
26
|
pwd: options.pwd,
|
|
27
27
|
prefix,
|
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
-
import { LOADABLE_STATS_FILE, MAIN_ENTRY_NAME, ROUTE_MANIFEST_FILE, SERVER_BUNDLE_DIRECTORY } from "@modern-js/utils";
|
|
3
|
-
|
|
2
|
+
import { LOADABLE_STATS_FILE, MAIN_ENTRY_NAME, ROUTE_MANIFEST_FILE, SERVER_BUNDLE_DIRECTORY, fs } from "@modern-js/utils";
|
|
3
|
+
const dynamicImport = (filePath) => {
|
|
4
|
+
try {
|
|
5
|
+
const module = require(filePath);
|
|
6
|
+
return Promise.resolve(module);
|
|
7
|
+
} catch (e) {
|
|
8
|
+
return Promise.reject(e);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
const loadBundle = async (filepath, logger) => {
|
|
12
|
+
if (!await fs.pathExists(filepath)) {
|
|
13
|
+
return void 0;
|
|
14
|
+
}
|
|
15
|
+
return dynamicImport(filepath).catch((e) => {
|
|
16
|
+
logger.error(`Load ${filepath} bundle failed, error = %s`, e instanceof Error ? e.stack || e.message : e);
|
|
17
|
+
return void 0;
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
async function getServerManifest(pwd, routes, logger) {
|
|
4
21
|
const loaderBundles = {};
|
|
5
22
|
const renderBundles = {};
|
|
6
|
-
await Promise.all(routes.map(async (route) => {
|
|
23
|
+
await Promise.all(routes.filter((route) => Boolean(route.bundle)).map(async (route) => {
|
|
7
24
|
const entryName = route.entryName || MAIN_ENTRY_NAME;
|
|
8
|
-
const loaderBundlePath = path.join(pwd, SERVER_BUNDLE_DIRECTORY, `${entryName}-server-loaders.js`);
|
|
9
25
|
const renderBundlePath = path.join(pwd, route.bundle || "");
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return Promise.reject(e);
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
await Promise.allSettled([
|
|
19
|
-
dynamicImport(loaderBundlePath),
|
|
20
|
-
dynamicImport(renderBundlePath)
|
|
21
|
-
]).then((results) => {
|
|
22
|
-
const { status: loaderStatus } = results[0];
|
|
23
|
-
if (loaderStatus === "fulfilled") {
|
|
24
|
-
loaderBundles[entryName] = results[0].value;
|
|
25
|
-
}
|
|
26
|
-
const { status: renderStatus } = results[1];
|
|
27
|
-
if (renderStatus === "fulfilled") {
|
|
28
|
-
renderBundles[entryName] = results[1].value;
|
|
29
|
-
}
|
|
30
|
-
});
|
|
26
|
+
const loaderBundlePath = path.join(pwd, SERVER_BUNDLE_DIRECTORY, `${entryName}-server-loaders.js`);
|
|
27
|
+
const renderBundle = await loadBundle(renderBundlePath, logger);
|
|
28
|
+
const loaderBundle = await loadBundle(loaderBundlePath, logger);
|
|
29
|
+
renderBundle && (renderBundles[entryName] = renderBundle);
|
|
30
|
+
loaderBundle && (loaderBundles[entryName] = loaderBundle);
|
|
31
31
|
}));
|
|
32
32
|
const loadableUri = path.join(pwd, LOADABLE_STATS_FILE);
|
|
33
33
|
const loadableStats = await import(loadableUri).catch((_) => ({}));
|
|
@@ -43,7 +43,8 @@ async function getServerManifest(pwd, routes) {
|
|
|
43
43
|
function injectServerManifest(pwd, routes) {
|
|
44
44
|
return async (c, next) => {
|
|
45
45
|
if (routes && !c.get("serverManifest")) {
|
|
46
|
-
const
|
|
46
|
+
const logger = c.get("logger");
|
|
47
|
+
const serverManifest = await getServerManifest(pwd, routes, logger);
|
|
47
48
|
c.set("serverManifest", serverManifest);
|
|
48
49
|
}
|
|
49
50
|
await next();
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { createErrorHtml } from "./utils";
|
|
1
|
+
import { createErrorHtml, onError, ErrorDigest } from "./utils";
|
|
2
2
|
import { AGGRED_DIR } from "./constants";
|
|
3
3
|
import { favionFallbackMiddleware, injectReporter, injectLogger, getRenderHandler, bindRenderHandler, logHandler, processedBy } from "./middlewares";
|
|
4
4
|
import { createServerBase } from "./serverBase";
|
|
5
5
|
export {
|
|
6
6
|
AGGRED_DIR,
|
|
7
|
+
ErrorDigest,
|
|
7
8
|
bindRenderHandler,
|
|
8
9
|
createErrorHtml,
|
|
9
10
|
createServerBase,
|
|
@@ -12,5 +13,6 @@ export {
|
|
|
12
13
|
injectLogger,
|
|
13
14
|
injectReporter,
|
|
14
15
|
logHandler,
|
|
16
|
+
onError,
|
|
15
17
|
processedBy
|
|
16
18
|
};
|
|
@@ -17,13 +17,12 @@ function createCustomMiddlewaresCtx(c, locals) {
|
|
|
17
17
|
var _c_env_node, _c_env_node1;
|
|
18
18
|
const baseContext = createBaseHookContext(c);
|
|
19
19
|
const reporter = c.get("reporter");
|
|
20
|
+
const response = baseContext.response;
|
|
21
|
+
response.locals = locals;
|
|
20
22
|
return {
|
|
21
23
|
...baseContext,
|
|
22
24
|
reporter,
|
|
23
|
-
response
|
|
24
|
-
...baseContext.response,
|
|
25
|
-
locals
|
|
26
|
-
},
|
|
25
|
+
response,
|
|
27
26
|
source: {
|
|
28
27
|
req: (_c_env_node = c.env.node) === null || _c_env_node === void 0 ? void 0 : _c_env_node.req,
|
|
29
28
|
res: (_c_env_node1 = c.env.node) === null || _c_env_node1 === void 0 ? void 0 : _c_env_node1.res
|
|
@@ -25,8 +25,15 @@ function createRenderHandler(render) {
|
|
|
25
25
|
return res;
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
async function getRenderHandler(options) {
|
|
28
|
+
async function getRenderHandler(options, serverBase) {
|
|
29
29
|
const { routes, pwd, config } = options;
|
|
30
|
+
const onFallback = async (reason, utils, error) => {
|
|
31
|
+
await (serverBase === null || serverBase === void 0 ? void 0 : serverBase.runner.fallback({
|
|
32
|
+
reason,
|
|
33
|
+
error,
|
|
34
|
+
...utils
|
|
35
|
+
}));
|
|
36
|
+
};
|
|
30
37
|
if (routes && routes.length > 0) {
|
|
31
38
|
var _config_server, _options_config_security;
|
|
32
39
|
const ssrConfig = (_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.ssr;
|
|
@@ -37,7 +44,8 @@ async function getRenderHandler(options) {
|
|
|
37
44
|
staticGenerate: options.staticGenerate,
|
|
38
45
|
metaName: options.metaName || "modern-js",
|
|
39
46
|
forceCSR,
|
|
40
|
-
nonce: (_options_config_security = options.config.security) === null || _options_config_security === void 0 ? void 0 : _options_config_security.nonce
|
|
47
|
+
nonce: (_options_config_security = options.config.security) === null || _options_config_security === void 0 ? void 0 : _options_config_security.nonce,
|
|
48
|
+
onFallback
|
|
41
49
|
});
|
|
42
50
|
return render;
|
|
43
51
|
}
|
|
@@ -54,7 +62,7 @@ async function bindRenderHandler(server, options) {
|
|
|
54
62
|
await ssrCache.loadCacheMod(checkIsProd() ? pwd : void 0);
|
|
55
63
|
}
|
|
56
64
|
const pageRoutes = routes.filter((route) => !route.isApi).sort(sortRoutes);
|
|
57
|
-
const render = await getRenderHandler(options);
|
|
65
|
+
const render = await getRenderHandler(options, server);
|
|
58
66
|
for (const route of pageRoutes) {
|
|
59
67
|
const { urlPath: originUrlPath, entryName } = route;
|
|
60
68
|
const urlPath = originUrlPath.endsWith("/") ? `${originUrlPath}*` : `${originUrlPath}/*`;
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { cutNameByHyphen } from "@modern-js/utils/universal";
|
|
2
2
|
import { REPLACE_REG } from "../../../base/constants";
|
|
3
|
-
import { createErrorHtml, sortRoutes, parseQuery, transformResponse, getPathname } from "../../utils";
|
|
3
|
+
import { createErrorHtml, sortRoutes, parseQuery, transformResponse, getPathname, onError as onErrorFn, ErrorDigest } from "../../utils";
|
|
4
4
|
import { dataHandler } from "./dataHandler";
|
|
5
5
|
import { ssrRender } from "./ssrRender";
|
|
6
|
-
async function createRender({ routes, pwd, metaName, staticGenerate, forceCSR, nonce }) {
|
|
6
|
+
async function createRender({ routes, pwd, metaName, staticGenerate, forceCSR, nonce, onFallback: onFallbackFn }) {
|
|
7
7
|
return async (req, { logger, nodeReq, reporter, templates, serverManifest, locals, metrics }) => {
|
|
8
8
|
const routeInfo = matchRoute(req, routes);
|
|
9
|
+
const onFallback = async (reason, error) => {
|
|
10
|
+
return onFallbackFn === null || onFallbackFn === void 0 ? void 0 : onFallbackFn(reason, {
|
|
11
|
+
logger,
|
|
12
|
+
reporter,
|
|
13
|
+
metrics
|
|
14
|
+
}, error);
|
|
15
|
+
};
|
|
9
16
|
if (!routeInfo) {
|
|
10
17
|
return new Response(createErrorHtml(404), {
|
|
11
18
|
status: 404,
|
|
@@ -23,7 +30,11 @@ async function createRender({ routes, pwd, metaName, staticGenerate, forceCSR, n
|
|
|
23
30
|
}
|
|
24
31
|
});
|
|
25
32
|
}
|
|
26
|
-
const renderMode = getRenderMode(req, metaName || "modern-js", routeInfo.isSSR, forceCSR, nodeReq);
|
|
33
|
+
const renderMode = await getRenderMode(req, metaName || "modern-js", routeInfo.isSSR, forceCSR, nodeReq, onFallback);
|
|
34
|
+
const onError = async (e) => {
|
|
35
|
+
onErrorFn(logger, ErrorDigest.ERENDER, e, req);
|
|
36
|
+
await (onFallback === null || onFallback === void 0 ? void 0 : onFallback("error", e));
|
|
37
|
+
};
|
|
27
38
|
const renderOptions = {
|
|
28
39
|
pwd,
|
|
29
40
|
html,
|
|
@@ -43,25 +54,35 @@ async function createRender({ routes, pwd, metaName, staticGenerate, forceCSR, n
|
|
|
43
54
|
case "data":
|
|
44
55
|
let response = await dataHandler(req, renderOptions);
|
|
45
56
|
if (!response) {
|
|
46
|
-
response = await renderHandler(req, renderOptions, "ssr");
|
|
57
|
+
response = await renderHandler(req, renderOptions, "ssr", onError);
|
|
47
58
|
}
|
|
48
59
|
return response;
|
|
49
60
|
case "ssr":
|
|
50
61
|
case "csr":
|
|
51
|
-
return renderHandler(req, renderOptions, renderMode);
|
|
62
|
+
return renderHandler(req, renderOptions, renderMode, onError);
|
|
52
63
|
default:
|
|
53
64
|
throw new Error(`Unknown render mode: ${renderMode}`);
|
|
54
65
|
}
|
|
55
66
|
};
|
|
56
67
|
}
|
|
57
|
-
async function renderHandler(request, options, mode) {
|
|
68
|
+
async function renderHandler(request, options, mode, onError) {
|
|
58
69
|
const serverData = {
|
|
59
70
|
router: {
|
|
60
71
|
baseUrl: options.routeInfo.urlPath,
|
|
61
72
|
params: {}
|
|
62
73
|
}
|
|
63
74
|
};
|
|
64
|
-
|
|
75
|
+
let response;
|
|
76
|
+
if (mode === "ssr") {
|
|
77
|
+
try {
|
|
78
|
+
response = await ssrRender(request, options);
|
|
79
|
+
} catch (e) {
|
|
80
|
+
await onError(e);
|
|
81
|
+
response = csrRender(options.html);
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
response = csrRender(options.html);
|
|
85
|
+
}
|
|
65
86
|
return transformResponse(response, injectServerData(serverData));
|
|
66
87
|
}
|
|
67
88
|
function matchRoute(req, routes) {
|
|
@@ -74,7 +95,7 @@ function matchRoute(req, routes) {
|
|
|
74
95
|
}
|
|
75
96
|
return void 0;
|
|
76
97
|
}
|
|
77
|
-
function getRenderMode(req, framework, isSSR, forceCSR, nodeReq) {
|
|
98
|
+
async function getRenderMode(req, framework, isSSR, forceCSR, nodeReq, onFallback) {
|
|
78
99
|
const query = parseQuery(req);
|
|
79
100
|
const fallbackHeader = `x-${cutNameByHyphen(framework)}-ssr-fallback`;
|
|
80
101
|
if (isSSR) {
|
|
@@ -82,6 +103,11 @@ function getRenderMode(req, framework, isSSR, forceCSR, nodeReq) {
|
|
|
82
103
|
return "data";
|
|
83
104
|
}
|
|
84
105
|
if (forceCSR && (query.csr || req.headers.get(fallbackHeader) || (nodeReq === null || nodeReq === void 0 ? void 0 : nodeReq.headers[fallbackHeader]))) {
|
|
106
|
+
if (query.csr) {
|
|
107
|
+
await (onFallback === null || onFallback === void 0 ? void 0 : onFallback("query"));
|
|
108
|
+
} else {
|
|
109
|
+
await (onFallback === null || onFallback === void 0 ? void 0 : onFallback("header"));
|
|
110
|
+
}
|
|
85
111
|
return "csr";
|
|
86
112
|
}
|
|
87
113
|
return "ssr";
|
|
@@ -36,6 +36,19 @@ const createErrorHtml = (status) => {
|
|
|
36
36
|
</html>
|
|
37
37
|
`;
|
|
38
38
|
};
|
|
39
|
+
var ErrorDigest;
|
|
40
|
+
(function(ErrorDigest2) {
|
|
41
|
+
ErrorDigest2["ENOTF"] = "Page could not be found";
|
|
42
|
+
ErrorDigest2["EINTER"] = "Internal server error";
|
|
43
|
+
ErrorDigest2["ERENDER"] = "SSR render failed";
|
|
44
|
+
})(ErrorDigest || (ErrorDigest = {}));
|
|
45
|
+
function onError(logger, digest, error, req) {
|
|
46
|
+
const headers = req === null || req === void 0 ? void 0 : req.headers;
|
|
47
|
+
headers === null || headers === void 0 ? void 0 : headers.delete("cookie");
|
|
48
|
+
logger.error(req ? `Server Error - ${digest}, error = %s, req.url = %s, req.headers = %o` : `Server Error - ${digest}, error = %s`, error instanceof Error ? error.stack || error.message : error, req === null || req === void 0 ? void 0 : req.url, headers);
|
|
49
|
+
}
|
|
39
50
|
export {
|
|
40
|
-
|
|
51
|
+
ErrorDigest,
|
|
52
|
+
createErrorHtml,
|
|
53
|
+
onError
|
|
41
54
|
};
|
|
@@ -3,6 +3,7 @@ const gather = createParallelWorkflow();
|
|
|
3
3
|
const config = createWaterfall();
|
|
4
4
|
const prepare = createWaterfall();
|
|
5
5
|
const prepareWebServer = createAsyncPipeline();
|
|
6
|
+
const fallback = createParallelWorkflow();
|
|
6
7
|
const prepareApiServer = createAsyncPipeline();
|
|
7
8
|
const onApiChange = createAsyncWaterfall();
|
|
8
9
|
const repack = createWaterfall();
|
|
@@ -26,6 +27,7 @@ const serverHooks = {
|
|
|
26
27
|
gather,
|
|
27
28
|
config,
|
|
28
29
|
prepare,
|
|
30
|
+
fallback,
|
|
29
31
|
prepareWebServer,
|
|
30
32
|
prepareApiServer,
|
|
31
33
|
repack,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ServerRoute } from '@modern-js/types';
|
|
1
|
+
import type { ServerRoute, Logger } from '@modern-js/types';
|
|
2
2
|
import { Middleware, ServerEnv, ServerManifest } from '../../../../core/server';
|
|
3
|
-
export declare function getServerManifest(pwd: string, routes: ServerRoute[]): Promise<ServerManifest>;
|
|
3
|
+
export declare function getServerManifest(pwd: string, routes: ServerRoute[], logger: Logger): Promise<ServerManifest>;
|
|
4
4
|
export declare function injectServerManifest(pwd: string, routes?: ServerRoute[]): Middleware<ServerEnv>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { createErrorHtml } from './utils';
|
|
1
|
+
export { createErrorHtml, onError, ErrorDigest } from './utils';
|
|
2
2
|
export { AGGRED_DIR } from './constants';
|
|
3
3
|
export { favionFallbackMiddleware, injectReporter, injectLogger, getRenderHandler, bindRenderHandler, logHandler, processedBy, } from './middlewares';
|
|
4
4
|
export type { BindRenderHandleOptions } from './middlewares';
|
|
@@ -5,5 +5,5 @@ export type BindRenderHandleOptions = {
|
|
|
5
5
|
staticGenerate?: boolean;
|
|
6
6
|
disableCustomHook?: boolean;
|
|
7
7
|
};
|
|
8
|
-
export declare function getRenderHandler(options: ServerBaseOptions & BindRenderHandleOptions): Promise<Render | null>;
|
|
8
|
+
export declare function getRenderHandler(options: ServerBaseOptions & BindRenderHandleOptions, serverBase?: ServerBase): Promise<Render | null>;
|
|
9
9
|
export declare function bindRenderHandler(server: ServerBase, options: ServerBaseOptions & BindRenderHandleOptions): Promise<void>;
|