@modern-js/server-core 2.67.1 → 2.67.3
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/adapters/node/node.js +29 -5
- package/dist/cjs/adapters/node/plugins/resource.js +5 -0
- package/dist/cjs/adapters/node/plugins/static.js +6 -2
- package/dist/cjs/context.js +31 -0
- package/dist/cjs/index.js +7 -1
- package/dist/cjs/plugins/render/index.js +9 -6
- package/dist/cjs/plugins/render/render.js +28 -8
- package/dist/cjs/serverBase.js +2 -0
- package/dist/cjs/utils/storage.js +74 -0
- package/dist/esm/adapters/node/node.js +29 -5
- package/dist/esm/adapters/node/plugins/resource.js +7 -1
- package/dist/esm/adapters/node/plugins/static.js +10 -3
- package/dist/esm/context.js +6 -0
- package/dist/esm/index.js +5 -1
- package/dist/esm/plugins/render/index.js +9 -7
- package/dist/esm/plugins/render/render.js +30 -10
- package/dist/esm/serverBase.js +2 -0
- package/dist/esm/utils/storage.js +38 -0
- package/dist/esm-node/adapters/node/node.js +29 -5
- package/dist/esm-node/adapters/node/plugins/resource.js +5 -0
- package/dist/esm-node/adapters/node/plugins/static.js +6 -2
- package/dist/esm-node/context.js +6 -0
- package/dist/esm-node/index.js +5 -1
- package/dist/esm-node/plugins/render/index.js +9 -6
- package/dist/esm-node/plugins/render/render.js +28 -8
- package/dist/esm-node/serverBase.js +2 -0
- package/dist/esm-node/utils/storage.js +40 -0
- package/dist/types/context.d.ts +3 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/types/config/server.d.ts +5 -0
- package/dist/types/types/plugins/base.d.ts +2 -1
- package/dist/types/types/plugins/index.d.ts +1 -1
- package/dist/types/utils/storage.d.ts +5 -0
- package/package.json +10 -8
|
@@ -35,6 +35,7 @@ __export(node_exports, {
|
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(node_exports);
|
|
37
37
|
var import_node_http = require("node:http");
|
|
38
|
+
var import_cloneable_readable = __toESM(require("cloneable-readable"));
|
|
38
39
|
var import_helper = require("./helper");
|
|
39
40
|
var import_install = require("./polyfills/install");
|
|
40
41
|
var import_stream = require("./polyfills/stream");
|
|
@@ -61,13 +62,36 @@ const createWebRequest = (req, res, body) => {
|
|
|
61
62
|
};
|
|
62
63
|
res.on("close", () => controller.abort("res closed"));
|
|
63
64
|
const url = `http://${req.headers.host}${req.url}`;
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
const needsRequestBody = body || !(method === "GET" || method === "HEAD");
|
|
66
|
+
const cloneableReq = needsRequestBody ? (0, import_cloneable_readable.default)(req) : null;
|
|
67
|
+
if (needsRequestBody) {
|
|
68
|
+
if (body) {
|
|
69
|
+
init.body = body;
|
|
70
|
+
} else {
|
|
71
|
+
const stream = cloneableReq.clone();
|
|
72
|
+
init.body = (0, import_stream.createReadableStreamFromReadable)(stream);
|
|
73
|
+
}
|
|
67
74
|
init.duplex = "half";
|
|
68
75
|
}
|
|
69
|
-
const
|
|
70
|
-
|
|
76
|
+
const originalRequest = new Request(url, init);
|
|
77
|
+
if (needsRequestBody) {
|
|
78
|
+
return new Proxy(originalRequest, {
|
|
79
|
+
get(target, prop) {
|
|
80
|
+
if ([
|
|
81
|
+
"json",
|
|
82
|
+
"text",
|
|
83
|
+
"blob",
|
|
84
|
+
"arrayBuffer",
|
|
85
|
+
"formData",
|
|
86
|
+
"body"
|
|
87
|
+
].includes(prop)) {
|
|
88
|
+
cloneableReq.resume();
|
|
89
|
+
}
|
|
90
|
+
return target[prop];
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return originalRequest;
|
|
71
95
|
};
|
|
72
96
|
const sendResponse = async (response, res) => {
|
|
73
97
|
var _response_headers_get;
|
|
@@ -134,7 +134,12 @@ const injectRscManifestPlugin = () => ({
|
|
|
134
134
|
setup(api) {
|
|
135
135
|
return {
|
|
136
136
|
async prepare() {
|
|
137
|
+
var _config_server;
|
|
137
138
|
const { middlewares, distDirectory: pwd } = api.useAppContext();
|
|
139
|
+
const config = api.useConfigContext();
|
|
140
|
+
if (!((_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.rsc)) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
138
143
|
middlewares.push({
|
|
139
144
|
name: "inject-rsc-manifest",
|
|
140
145
|
handler: async (c, next) => {
|
|
@@ -61,7 +61,7 @@ const serverStaticPlugin = () => ({
|
|
|
61
61
|
});
|
|
62
62
|
function createPublicMiddleware({ pwd, routes }) {
|
|
63
63
|
return async (c, next) => {
|
|
64
|
-
const route =
|
|
64
|
+
const route = matchPublicRoute(c.req, routes);
|
|
65
65
|
if (route) {
|
|
66
66
|
const { entryPath } = route;
|
|
67
67
|
const filename = import_path.default.join(pwd, entryPath);
|
|
@@ -80,7 +80,7 @@ function createPublicMiddleware({ pwd, routes }) {
|
|
|
80
80
|
return await next();
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
|
-
function
|
|
83
|
+
function matchPublicRoute(req, routes) {
|
|
84
84
|
for (const route of routes.sort(import_utils2.sortRoutes)) {
|
|
85
85
|
if (!route.isSSR && route.entryPath.startsWith("public") && req.path.startsWith(route.urlPath)) {
|
|
86
86
|
return route;
|
|
@@ -115,7 +115,11 @@ function createStaticMiddleware(options) {
|
|
|
115
115
|
...iconReg
|
|
116
116
|
].join("|")})`);
|
|
117
117
|
return async (c, next) => {
|
|
118
|
+
const pageRoute = c.get("route");
|
|
118
119
|
const pathname = c.req.path;
|
|
120
|
+
if (pageRoute && import_path.default.extname(pathname) === "") {
|
|
121
|
+
return next();
|
|
122
|
+
}
|
|
119
123
|
const hit = staticPathRegExp.test(pathname);
|
|
120
124
|
if (hit) {
|
|
121
125
|
const filepath = import_path.default.join(pwd, pathname.replace(prefix, () => ""));
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var context_exports = {};
|
|
20
|
+
__export(context_exports, {
|
|
21
|
+
run: () => run,
|
|
22
|
+
useHonoContext: () => useHonoContext
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(context_exports);
|
|
25
|
+
var import_storage = require("./utils/storage");
|
|
26
|
+
const { run, useHonoContext } = (0, import_storage.createStorage)();
|
|
27
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
28
|
+
0 && (module.exports = {
|
|
29
|
+
run,
|
|
30
|
+
useHonoContext
|
|
31
|
+
});
|
package/dist/cjs/index.js
CHANGED
|
@@ -21,15 +21,19 @@ var src_exports = {};
|
|
|
21
21
|
__export(src_exports, {
|
|
22
22
|
AGGRED_DIR: () => import_constants.AGGRED_DIR,
|
|
23
23
|
ErrorDigest: () => import_utils.ErrorDigest,
|
|
24
|
+
Hono: () => import_hono.Hono,
|
|
24
25
|
createErrorHtml: () => import_utils.createErrorHtml,
|
|
25
26
|
createServerBase: () => import_serverBase.createServerBase,
|
|
26
27
|
getLoaderCtx: () => import_helper.getLoaderCtx,
|
|
27
|
-
onError: () => import_utils.onError
|
|
28
|
+
onError: () => import_utils.onError,
|
|
29
|
+
useHonoContext: () => import_context.useHonoContext
|
|
28
30
|
});
|
|
29
31
|
module.exports = __toCommonJS(src_exports);
|
|
30
32
|
var import_utils = require("./utils");
|
|
31
33
|
var import_constants = require("./constants");
|
|
32
34
|
var import_serverBase = require("./serverBase");
|
|
35
|
+
var import_context = require("./context");
|
|
36
|
+
var import_hono = require("hono");
|
|
33
37
|
var import_helper = require("./helper");
|
|
34
38
|
__reExport(src_exports, require("./plugins"), module.exports);
|
|
35
39
|
__reExport(src_exports, require("./types/plugins"), module.exports);
|
|
@@ -41,10 +45,12 @@ __reExport(src_exports, require("./types/requestHandler"), module.exports);
|
|
|
41
45
|
0 && (module.exports = {
|
|
42
46
|
AGGRED_DIR,
|
|
43
47
|
ErrorDigest,
|
|
48
|
+
Hono,
|
|
44
49
|
createErrorHtml,
|
|
45
50
|
createServerBase,
|
|
46
51
|
getLoaderCtx,
|
|
47
52
|
onError,
|
|
53
|
+
useHonoContext,
|
|
48
54
|
...require("./plugins"),
|
|
49
55
|
...require("./types/plugins"),
|
|
50
56
|
...require("./types/render"),
|
|
@@ -48,14 +48,17 @@ const renderPlugin = () => ({
|
|
|
48
48
|
handler: (0, import_monitors.requestLatencyMiddleware)()
|
|
49
49
|
});
|
|
50
50
|
for (const route of pageRoutes) {
|
|
51
|
+
var _config_server;
|
|
51
52
|
const { urlPath: originUrlPath, entryName = import_constants.MAIN_ENTRY_NAME } = route;
|
|
52
53
|
const urlPath = originUrlPath.endsWith("/") ? `${originUrlPath}*` : `${originUrlPath}/*`;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
if (((_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.disableHook) !== true) {
|
|
55
|
+
const customServerHookMiddleware = customServer.getHookMiddleware(entryName, routes);
|
|
56
|
+
middlewares.push({
|
|
57
|
+
name: "custom-server-hook",
|
|
58
|
+
path: urlPath,
|
|
59
|
+
handler: customServerHookMiddleware
|
|
60
|
+
});
|
|
61
|
+
}
|
|
59
62
|
const customServerMiddleware = await customServer.getServerMiddleware(serverMiddleware);
|
|
60
63
|
customServerMiddleware && middlewares.push({
|
|
61
64
|
name: "custom-server-middleware",
|
|
@@ -87,8 +87,8 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
|
|
|
87
87
|
return async (req, { logger, reporter, metrics, monitors, nodeReq, templates, serverManifest, rscClientManifest, rscSSRManifest, rscServerManifest, locals, matchEntryName, matchPathname, loaderContext }) => {
|
|
88
88
|
const forMatchpathname = matchPathname !== null && matchPathname !== void 0 ? matchPathname : (0, import_utils2.getPathname)(req);
|
|
89
89
|
const [routeInfo, params] = matchRoute(router, forMatchpathname, matchEntryName);
|
|
90
|
-
const framework = metaName || "modern-js";
|
|
91
|
-
const fallbackHeader = `x-${
|
|
90
|
+
const framework = (0, import_universal.cutNameByHyphen)(metaName || "modern-js");
|
|
91
|
+
const fallbackHeader = `x-${framework}-ssr-fallback`;
|
|
92
92
|
let fallbackReason = null;
|
|
93
93
|
const fallbackWrapper = async (reason, error) => {
|
|
94
94
|
fallbackReason = reason;
|
|
@@ -146,10 +146,17 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
|
|
|
146
146
|
onError,
|
|
147
147
|
onTiming
|
|
148
148
|
};
|
|
149
|
+
if (fallbackReason) {
|
|
150
|
+
renderOptions.html = injectFallbackReasonToHtml({
|
|
151
|
+
html: renderOptions.html,
|
|
152
|
+
reason: fallbackReason,
|
|
153
|
+
framework
|
|
154
|
+
});
|
|
155
|
+
}
|
|
149
156
|
let response;
|
|
150
157
|
switch (renderMode) {
|
|
151
158
|
case "data":
|
|
152
|
-
response = await (0, import_dataHandler.dataHandler)(req, renderOptions) || await renderHandler(req, renderOptions, "ssr", fallbackWrapper);
|
|
159
|
+
response = await (0, import_dataHandler.dataHandler)(req, renderOptions) || await renderHandler(req, renderOptions, "ssr", fallbackWrapper, framework);
|
|
153
160
|
break;
|
|
154
161
|
case "rsc-tree":
|
|
155
162
|
response = await (0, import_renderRscHandler.renderRscHandler)(req, renderOptions);
|
|
@@ -159,7 +166,7 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
|
|
|
159
166
|
break;
|
|
160
167
|
case "ssr":
|
|
161
168
|
case "csr":
|
|
162
|
-
response = await renderHandler(req, renderOptions, renderMode, fallbackWrapper);
|
|
169
|
+
response = await renderHandler(req, renderOptions, renderMode, fallbackWrapper, framework);
|
|
163
170
|
break;
|
|
164
171
|
default:
|
|
165
172
|
throw new Error(`Unknown render mode: ${renderMode}`);
|
|
@@ -170,7 +177,7 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
|
|
|
170
177
|
return response;
|
|
171
178
|
};
|
|
172
179
|
}
|
|
173
|
-
async function renderHandler(request, options, mode, fallbackWrapper) {
|
|
180
|
+
async function renderHandler(request, options, mode, fallbackWrapper, framework) {
|
|
174
181
|
var _options_config_server;
|
|
175
182
|
let response = null;
|
|
176
183
|
const { serverManifest } = options;
|
|
@@ -202,7 +209,11 @@ async function renderHandler(request, options, mode, fallbackWrapper) {
|
|
|
202
209
|
} catch (e) {
|
|
203
210
|
options.onError(e, import_utils2.ErrorDigest.ERENDER);
|
|
204
211
|
await fallbackWrapper("error", e);
|
|
205
|
-
response = csrRender(
|
|
212
|
+
response = csrRender(injectFallbackReasonToHtml({
|
|
213
|
+
html: options.html,
|
|
214
|
+
reason: "error",
|
|
215
|
+
framework
|
|
216
|
+
}));
|
|
206
217
|
}
|
|
207
218
|
} else {
|
|
208
219
|
response = csrRender(options.html);
|
|
@@ -228,11 +239,14 @@ async function getRenderMode(req, fallbackHeader, isSSR, forceCSR, nodeReq, onFa
|
|
|
228
239
|
if (query.__loader) {
|
|
229
240
|
return "data";
|
|
230
241
|
}
|
|
231
|
-
|
|
242
|
+
const fallbackHeaderValue = req.headers.get(fallbackHeader) || (nodeReq === null || nodeReq === void 0 ? void 0 : nodeReq.headers[fallbackHeader]);
|
|
243
|
+
if (forceCSR && (query.csr || fallbackHeaderValue)) {
|
|
232
244
|
if (query.csr) {
|
|
233
245
|
await (onFallback === null || onFallback === void 0 ? void 0 : onFallback("query"));
|
|
234
246
|
} else {
|
|
235
|
-
|
|
247
|
+
var _fallbackHeaderValue_split_;
|
|
248
|
+
const reason = fallbackHeaderValue === null || fallbackHeaderValue === void 0 ? void 0 : (_fallbackHeaderValue_split_ = fallbackHeaderValue.split(";")[1]) === null || _fallbackHeaderValue_split_ === void 0 ? void 0 : _fallbackHeaderValue_split_.split("=")[1];
|
|
249
|
+
await (onFallback === null || onFallback === void 0 ? void 0 : onFallback(reason ? `header,${reason}` : "header"));
|
|
236
250
|
}
|
|
237
251
|
return "csr";
|
|
238
252
|
}
|
|
@@ -241,6 +255,12 @@ async function getRenderMode(req, fallbackHeader, isSSR, forceCSR, nodeReq, onFa
|
|
|
241
255
|
return "csr";
|
|
242
256
|
}
|
|
243
257
|
}
|
|
258
|
+
function injectFallbackReasonToHtml({ html, reason, framework }) {
|
|
259
|
+
const tag = `<script id="__${framework}_ssr_fallback_reason__" type="application/json">${JSON.stringify({
|
|
260
|
+
reason
|
|
261
|
+
})}</script>`;
|
|
262
|
+
return html.replace(/<\/head>/, `${tag}</head>`);
|
|
263
|
+
}
|
|
244
264
|
function csrRender(html) {
|
|
245
265
|
return new Response(html, {
|
|
246
266
|
status: 200,
|
package/dist/cjs/serverBase.js
CHANGED
|
@@ -26,6 +26,7 @@ var import_class_private_method_get = require("@swc/helpers/_/_class_private_met
|
|
|
26
26
|
var import_class_private_method_init = require("@swc/helpers/_/_class_private_method_init");
|
|
27
27
|
var import_server = require("@modern-js/plugin-v2/server");
|
|
28
28
|
var import_hono = require("hono");
|
|
29
|
+
var import_context = require("./context");
|
|
29
30
|
var import_hooks = require("./plugins/compat/hooks");
|
|
30
31
|
var import_utils = require("./utils");
|
|
31
32
|
var _applyMiddlewares = /* @__PURE__ */ new WeakSet();
|
|
@@ -99,6 +100,7 @@ class ServerBase {
|
|
|
99
100
|
this.serverContext = null;
|
|
100
101
|
this.options = options;
|
|
101
102
|
this.app = new import_hono.Hono();
|
|
103
|
+
this.app.use("*", import_context.run);
|
|
102
104
|
}
|
|
103
105
|
}
|
|
104
106
|
function applyMiddlewares() {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var storage_exports = {};
|
|
30
|
+
__export(storage_exports, {
|
|
31
|
+
createStorage: () => createStorage
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(storage_exports);
|
|
34
|
+
var ah = __toESM(require("async_hooks"));
|
|
35
|
+
const createStorage = () => {
|
|
36
|
+
let storage;
|
|
37
|
+
if (typeof ah.AsyncLocalStorage !== "undefined") {
|
|
38
|
+
storage = new ah.AsyncLocalStorage();
|
|
39
|
+
}
|
|
40
|
+
const run = (context, cb) => {
|
|
41
|
+
if (!storage) {
|
|
42
|
+
throw new Error(`Unable to use async_hook, please confirm the node version >= 12.17
|
|
43
|
+
`);
|
|
44
|
+
}
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
storage.run(context, () => {
|
|
47
|
+
try {
|
|
48
|
+
return resolve(cb());
|
|
49
|
+
} catch (error) {
|
|
50
|
+
return reject(error);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
const useHonoContext = () => {
|
|
56
|
+
if (!storage) {
|
|
57
|
+
throw new Error(`Unable to use async_hook, please confirm the node version >= 12.17
|
|
58
|
+
`);
|
|
59
|
+
}
|
|
60
|
+
const context = storage.getStore();
|
|
61
|
+
if (!context) {
|
|
62
|
+
throw new Error(`Can't call useContext out of server scope`);
|
|
63
|
+
}
|
|
64
|
+
return context;
|
|
65
|
+
};
|
|
66
|
+
return {
|
|
67
|
+
run,
|
|
68
|
+
useHonoContext
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
72
|
+
0 && (module.exports = {
|
|
73
|
+
createStorage
|
|
74
|
+
});
|
|
@@ -4,6 +4,7 @@ import { _ as _object_spread } from "@swc/helpers/_/_object_spread";
|
|
|
4
4
|
import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
|
|
5
5
|
import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
|
|
6
6
|
import { ServerResponse } from "node:http";
|
|
7
|
+
import cloneable from "cloneable-readable";
|
|
7
8
|
import { isResFinalized } from "./helper";
|
|
8
9
|
import { installGlobals } from "./polyfills/install";
|
|
9
10
|
import { createReadableStreamFromReadable, writeReadableStreamToWritable } from "./polyfills/stream";
|
|
@@ -32,13 +33,36 @@ var createWebRequest = function(req, res, body) {
|
|
|
32
33
|
return controller.abort("res closed");
|
|
33
34
|
});
|
|
34
35
|
var url = "http://".concat(req.headers.host).concat(req.url);
|
|
35
|
-
var
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
var needsRequestBody = body || !(method === "GET" || method === "HEAD");
|
|
37
|
+
var cloneableReq = needsRequestBody ? cloneable(req) : null;
|
|
38
|
+
if (needsRequestBody) {
|
|
39
|
+
if (body) {
|
|
40
|
+
init.body = body;
|
|
41
|
+
} else {
|
|
42
|
+
var stream = cloneableReq.clone();
|
|
43
|
+
init.body = createReadableStreamFromReadable(stream);
|
|
44
|
+
}
|
|
38
45
|
init.duplex = "half";
|
|
39
46
|
}
|
|
40
|
-
var
|
|
41
|
-
|
|
47
|
+
var originalRequest = new Request(url, init);
|
|
48
|
+
if (needsRequestBody) {
|
|
49
|
+
return new Proxy(originalRequest, {
|
|
50
|
+
get: function get(target, prop) {
|
|
51
|
+
if ([
|
|
52
|
+
"json",
|
|
53
|
+
"text",
|
|
54
|
+
"blob",
|
|
55
|
+
"arrayBuffer",
|
|
56
|
+
"formData",
|
|
57
|
+
"body"
|
|
58
|
+
].includes(prop)) {
|
|
59
|
+
cloneableReq.resume();
|
|
60
|
+
}
|
|
61
|
+
return target[prop];
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return originalRequest;
|
|
42
66
|
};
|
|
43
67
|
var sendResponse = function() {
|
|
44
68
|
var _ref = _async_to_generator(function(response, res) {
|
|
@@ -409,9 +409,15 @@ var injectRscManifestPlugin = function() {
|
|
|
409
409
|
return {
|
|
410
410
|
prepare: function prepare() {
|
|
411
411
|
return _async_to_generator(function() {
|
|
412
|
-
var _api_useAppContext, middlewares, pwd;
|
|
412
|
+
var _config_server, _api_useAppContext, middlewares, pwd, config;
|
|
413
413
|
return _ts_generator(this, function(_state) {
|
|
414
414
|
_api_useAppContext = api.useAppContext(), middlewares = _api_useAppContext.middlewares, pwd = _api_useAppContext.distDirectory;
|
|
415
|
+
config = api.useConfigContext();
|
|
416
|
+
if (!((_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.rsc)) {
|
|
417
|
+
return [
|
|
418
|
+
2
|
|
419
|
+
];
|
|
420
|
+
}
|
|
415
421
|
middlewares.push({
|
|
416
422
|
name: "inject-rsc-manifest",
|
|
417
423
|
handler: function() {
|
|
@@ -38,7 +38,7 @@ function createPublicMiddleware(param) {
|
|
|
38
38
|
return _ts_generator(this, function(_state) {
|
|
39
39
|
switch (_state.label) {
|
|
40
40
|
case 0:
|
|
41
|
-
route =
|
|
41
|
+
route = matchPublicRoute(c.req, routes);
|
|
42
42
|
if (!route)
|
|
43
43
|
return [
|
|
44
44
|
3,
|
|
@@ -85,7 +85,7 @@ function createPublicMiddleware(param) {
|
|
|
85
85
|
};
|
|
86
86
|
}();
|
|
87
87
|
}
|
|
88
|
-
function
|
|
88
|
+
function matchPublicRoute(req, routes) {
|
|
89
89
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
90
90
|
try {
|
|
91
91
|
for (var _iterator = routes.sort(sortRoutes)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
@@ -135,11 +135,18 @@ function createStaticMiddleware(options) {
|
|
|
135
135
|
var staticPathRegExp = new RegExp("^".concat(regPrefix, "(").concat(_to_consumable_array(staticReg).concat(_to_consumable_array(iconReg)).join("|"), ")"));
|
|
136
136
|
return function() {
|
|
137
137
|
var _ref2 = _async_to_generator(function(c, next) {
|
|
138
|
-
var pathname, hit, filepath, mimeType, stat, size, chunk;
|
|
138
|
+
var pageRoute, pathname, hit, filepath, mimeType, stat, size, chunk;
|
|
139
139
|
return _ts_generator(this, function(_state) {
|
|
140
140
|
switch (_state.label) {
|
|
141
141
|
case 0:
|
|
142
|
+
pageRoute = c.get("route");
|
|
142
143
|
pathname = c.req.path;
|
|
144
|
+
if (pageRoute && path.extname(pathname) === "") {
|
|
145
|
+
return [
|
|
146
|
+
2,
|
|
147
|
+
next()
|
|
148
|
+
];
|
|
149
|
+
}
|
|
143
150
|
hit = staticPathRegExp.test(pathname);
|
|
144
151
|
if (!hit)
|
|
145
152
|
return [
|
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createErrorHtml, onError, ErrorDigest } from "./utils";
|
|
2
2
|
import { AGGRED_DIR } from "./constants";
|
|
3
3
|
import { createServerBase } from "./serverBase";
|
|
4
|
+
import { useHonoContext } from "./context";
|
|
5
|
+
import { Hono } from "hono";
|
|
4
6
|
import { getLoaderCtx } from "./helper";
|
|
5
7
|
export * from "./plugins";
|
|
6
8
|
export * from "./types/plugins";
|
|
@@ -11,8 +13,10 @@ export * from "./types/requestHandler";
|
|
|
11
13
|
export {
|
|
12
14
|
AGGRED_DIR,
|
|
13
15
|
ErrorDigest,
|
|
16
|
+
Hono,
|
|
14
17
|
createErrorHtml,
|
|
15
18
|
createServerBase,
|
|
16
19
|
getLoaderCtx,
|
|
17
|
-
onError
|
|
20
|
+
onError,
|
|
21
|
+
useHonoContext
|
|
18
22
|
};
|
|
@@ -13,7 +13,7 @@ var renderPlugin = function() {
|
|
|
13
13
|
return {
|
|
14
14
|
prepare: function prepare() {
|
|
15
15
|
return _async_to_generator(function() {
|
|
16
|
-
var _config_render, _api_useAppContext, middlewares, routes, render, pwd, serverBase, hooks, config, customServer, serverMiddleware, pageRoutes, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, route, originUrlPath, _route_entryName, entryName, urlPath, customServerHookMiddleware, customServerMiddleware, err;
|
|
16
|
+
var _config_render, _api_useAppContext, middlewares, routes, render, pwd, serverBase, hooks, config, customServer, serverMiddleware, pageRoutes, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, route, _config_server, originUrlPath, _route_entryName, entryName, urlPath, customServerHookMiddleware, customServerMiddleware, err;
|
|
17
17
|
return _ts_generator(this, function(_state) {
|
|
18
18
|
switch (_state.label) {
|
|
19
19
|
case 0:
|
|
@@ -52,12 +52,14 @@ var renderPlugin = function() {
|
|
|
52
52
|
route = _step.value;
|
|
53
53
|
originUrlPath = route.urlPath, _route_entryName = route.entryName, entryName = _route_entryName === void 0 ? MAIN_ENTRY_NAME : _route_entryName;
|
|
54
54
|
urlPath = originUrlPath.endsWith("/") ? "".concat(originUrlPath, "*") : "".concat(originUrlPath, "/*");
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
if (((_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.disableHook) !== true) {
|
|
56
|
+
customServerHookMiddleware = customServer.getHookMiddleware(entryName, routes);
|
|
57
|
+
middlewares.push({
|
|
58
|
+
name: "custom-server-hook",
|
|
59
|
+
path: urlPath,
|
|
60
|
+
handler: customServerHookMiddleware
|
|
61
|
+
});
|
|
62
|
+
}
|
|
61
63
|
return [
|
|
62
64
|
4,
|
|
63
65
|
customServer.getServerMiddleware(serverMiddleware)
|
|
@@ -93,8 +93,8 @@ function _createRender() {
|
|
|
93
93
|
logger = param2.logger, reporter = param2.reporter, metrics = param2.metrics, monitors = param2.monitors, nodeReq = param2.nodeReq, templates = param2.templates, serverManifest = param2.serverManifest, rscClientManifest = param2.rscClientManifest, rscSSRManifest = param2.rscSSRManifest, rscServerManifest = param2.rscServerManifest, locals = param2.locals, matchEntryName = param2.matchEntryName, matchPathname = param2.matchPathname, loaderContext = param2.loaderContext;
|
|
94
94
|
forMatchpathname = matchPathname !== null && matchPathname !== void 0 ? matchPathname : getPathname(req);
|
|
95
95
|
_matchRoute = _sliced_to_array(matchRoute(router, forMatchpathname, matchEntryName), 2), routeInfo = _matchRoute[0], params = _matchRoute[1];
|
|
96
|
-
framework = metaName || "modern-js";
|
|
97
|
-
fallbackHeader = "x-".concat(
|
|
96
|
+
framework = cutNameByHyphen(metaName || "modern-js");
|
|
97
|
+
fallbackHeader = "x-".concat(framework, "-ssr-fallback");
|
|
98
98
|
fallbackReason = null;
|
|
99
99
|
fallbackWrapper = function() {
|
|
100
100
|
var _ref2 = _async_to_generator(function(reason, error) {
|
|
@@ -173,6 +173,13 @@ function _createRender() {
|
|
|
173
173
|
onError,
|
|
174
174
|
onTiming
|
|
175
175
|
};
|
|
176
|
+
if (fallbackReason) {
|
|
177
|
+
renderOptions.html = injectFallbackReasonToHtml({
|
|
178
|
+
html: renderOptions.html,
|
|
179
|
+
reason: fallbackReason,
|
|
180
|
+
framework
|
|
181
|
+
});
|
|
182
|
+
}
|
|
176
183
|
switch (renderMode) {
|
|
177
184
|
case "data":
|
|
178
185
|
return [
|
|
@@ -218,7 +225,7 @@ function _createRender() {
|
|
|
218
225
|
];
|
|
219
226
|
return [
|
|
220
227
|
4,
|
|
221
|
-
renderHandler(req, renderOptions, "ssr", fallbackWrapper)
|
|
228
|
+
renderHandler(req, renderOptions, "ssr", fallbackWrapper, framework)
|
|
222
229
|
];
|
|
223
230
|
case 4:
|
|
224
231
|
_tmp = _state2.sent();
|
|
@@ -254,7 +261,7 @@ function _createRender() {
|
|
|
254
261
|
case 10:
|
|
255
262
|
return [
|
|
256
263
|
4,
|
|
257
|
-
renderHandler(req, renderOptions, renderMode, fallbackWrapper)
|
|
264
|
+
renderHandler(req, renderOptions, renderMode, fallbackWrapper, framework)
|
|
258
265
|
];
|
|
259
266
|
case 11:
|
|
260
267
|
response = _state2.sent();
|
|
@@ -284,11 +291,11 @@ function _createRender() {
|
|
|
284
291
|
});
|
|
285
292
|
return _createRender.apply(this, arguments);
|
|
286
293
|
}
|
|
287
|
-
function renderHandler(request, options, mode, fallbackWrapper) {
|
|
294
|
+
function renderHandler(request, options, mode, fallbackWrapper, framework) {
|
|
288
295
|
return _renderHandler.apply(this, arguments);
|
|
289
296
|
}
|
|
290
297
|
function _renderHandler() {
|
|
291
|
-
_renderHandler = _async_to_generator(function(request, options, mode, fallbackWrapper) {
|
|
298
|
+
_renderHandler = _async_to_generator(function(request, options, mode, fallbackWrapper, framework) {
|
|
292
299
|
var _options_config_server, response, serverManifest, ssrByRouteIds, runtimeEnv, nestedRoutesJson, routes, urlPath, pathToFileURL, matchRoutes, url, matchedRoutes, _lastMatch_route, lastMatch, e, routeInfo;
|
|
293
300
|
function applyExtendHeaders(r, route) {
|
|
294
301
|
Object.entries(route.responseHeaders || {}).forEach(function(param) {
|
|
@@ -373,7 +380,11 @@ function _renderHandler() {
|
|
|
373
380
|
];
|
|
374
381
|
case 7:
|
|
375
382
|
_state.sent();
|
|
376
|
-
response = csrRender(
|
|
383
|
+
response = csrRender(injectFallbackReasonToHtml({
|
|
384
|
+
html: options.html,
|
|
385
|
+
reason: "error",
|
|
386
|
+
framework
|
|
387
|
+
}));
|
|
377
388
|
return [
|
|
378
389
|
3,
|
|
379
390
|
8
|
|
@@ -403,7 +414,7 @@ function getRenderMode(req, fallbackHeader, isSSR, forceCSR, nodeReq, onFallback
|
|
|
403
414
|
}
|
|
404
415
|
function _getRenderMode() {
|
|
405
416
|
_getRenderMode = _async_to_generator(function(req, fallbackHeader, isSSR, forceCSR, nodeReq, onFallback) {
|
|
406
|
-
var query;
|
|
417
|
+
var query, fallbackHeaderValue, _fallbackHeaderValue_split_, reason;
|
|
407
418
|
return _ts_generator(this, function(_state) {
|
|
408
419
|
switch (_state.label) {
|
|
409
420
|
case 0:
|
|
@@ -431,7 +442,8 @@ function _getRenderMode() {
|
|
|
431
442
|
"data"
|
|
432
443
|
];
|
|
433
444
|
}
|
|
434
|
-
|
|
445
|
+
fallbackHeaderValue = req.headers.get(fallbackHeader) || (nodeReq === null || nodeReq === void 0 ? void 0 : nodeReq.headers[fallbackHeader]);
|
|
446
|
+
if (!(forceCSR && (query.csr || fallbackHeaderValue)))
|
|
435
447
|
return [
|
|
436
448
|
3,
|
|
437
449
|
5
|
|
@@ -452,9 +464,10 @@ function _getRenderMode() {
|
|
|
452
464
|
4
|
|
453
465
|
];
|
|
454
466
|
case 2:
|
|
467
|
+
reason = fallbackHeaderValue === null || fallbackHeaderValue === void 0 ? void 0 : (_fallbackHeaderValue_split_ = fallbackHeaderValue.split(";")[1]) === null || _fallbackHeaderValue_split_ === void 0 ? void 0 : _fallbackHeaderValue_split_.split("=")[1];
|
|
455
468
|
return [
|
|
456
469
|
4,
|
|
457
|
-
onFallback === null || onFallback === void 0 ? void 0 : onFallback("header")
|
|
470
|
+
onFallback === null || onFallback === void 0 ? void 0 : onFallback(reason ? "header,".concat(reason) : "header")
|
|
458
471
|
];
|
|
459
472
|
case 3:
|
|
460
473
|
_state.sent();
|
|
@@ -483,6 +496,13 @@ function _getRenderMode() {
|
|
|
483
496
|
});
|
|
484
497
|
return _getRenderMode.apply(this, arguments);
|
|
485
498
|
}
|
|
499
|
+
function injectFallbackReasonToHtml(param) {
|
|
500
|
+
var html = param.html, reason = param.reason, framework = param.framework;
|
|
501
|
+
var tag = '<script id="__'.concat(framework, '_ssr_fallback_reason__" type="application/json">').concat(JSON.stringify({
|
|
502
|
+
reason
|
|
503
|
+
}), "</script>");
|
|
504
|
+
return html.replace(/<\/head>/, "".concat(tag, "</head>"));
|
|
505
|
+
}
|
|
486
506
|
function csrRender(html) {
|
|
487
507
|
return new Response(html, {
|
|
488
508
|
status: 200,
|
package/dist/esm/serverBase.js
CHANGED
|
@@ -7,6 +7,7 @@ import { _ as _to_consumable_array } from "@swc/helpers/_/_to_consumable_array";
|
|
|
7
7
|
import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
|
|
8
8
|
import { server } from "@modern-js/plugin-v2/server";
|
|
9
9
|
import { Hono } from "hono";
|
|
10
|
+
import { run } from "./context";
|
|
10
11
|
import { handleSetupResult } from "./plugins/compat/hooks";
|
|
11
12
|
import { loadConfig } from "./utils";
|
|
12
13
|
var _applyMiddlewares = /* @__PURE__ */ new WeakSet();
|
|
@@ -19,6 +20,7 @@ var ServerBase = /* @__PURE__ */ function() {
|
|
|
19
20
|
this.serverContext = null;
|
|
20
21
|
this.options = options;
|
|
21
22
|
this.app = new Hono();
|
|
23
|
+
this.app.use("*", run);
|
|
22
24
|
}
|
|
23
25
|
var _proto = ServerBase2.prototype;
|
|
24
26
|
_proto.init = function init() {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as ah from "async_hooks";
|
|
2
|
+
var createStorage = function() {
|
|
3
|
+
var storage;
|
|
4
|
+
if (typeof ah.AsyncLocalStorage !== "undefined") {
|
|
5
|
+
storage = new ah.AsyncLocalStorage();
|
|
6
|
+
}
|
|
7
|
+
var run = function(context, cb) {
|
|
8
|
+
if (!storage) {
|
|
9
|
+
throw new Error("Unable to use async_hook, please confirm the node version >= 12.17\n ");
|
|
10
|
+
}
|
|
11
|
+
return new Promise(function(resolve, reject) {
|
|
12
|
+
storage.run(context, function() {
|
|
13
|
+
try {
|
|
14
|
+
return resolve(cb());
|
|
15
|
+
} catch (error) {
|
|
16
|
+
return reject(error);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
var useHonoContext = function() {
|
|
22
|
+
if (!storage) {
|
|
23
|
+
throw new Error("Unable to use async_hook, please confirm the node version >= 12.17\n ");
|
|
24
|
+
}
|
|
25
|
+
var context = storage.getStore();
|
|
26
|
+
if (!context) {
|
|
27
|
+
throw new Error("Can't call useContext out of server scope");
|
|
28
|
+
}
|
|
29
|
+
return context;
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
run,
|
|
33
|
+
useHonoContext
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export {
|
|
37
|
+
createStorage
|
|
38
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ServerResponse } from "node:http";
|
|
2
|
+
import cloneable from "cloneable-readable";
|
|
2
3
|
import { isResFinalized } from "./helper";
|
|
3
4
|
import { installGlobals } from "./polyfills/install";
|
|
4
5
|
import { createReadableStreamFromReadable, writeReadableStreamToWritable } from "./polyfills/stream";
|
|
@@ -25,13 +26,36 @@ const createWebRequest = (req, res, body) => {
|
|
|
25
26
|
};
|
|
26
27
|
res.on("close", () => controller.abort("res closed"));
|
|
27
28
|
const url = `http://${req.headers.host}${req.url}`;
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
const needsRequestBody = body || !(method === "GET" || method === "HEAD");
|
|
30
|
+
const cloneableReq = needsRequestBody ? cloneable(req) : null;
|
|
31
|
+
if (needsRequestBody) {
|
|
32
|
+
if (body) {
|
|
33
|
+
init.body = body;
|
|
34
|
+
} else {
|
|
35
|
+
const stream = cloneableReq.clone();
|
|
36
|
+
init.body = createReadableStreamFromReadable(stream);
|
|
37
|
+
}
|
|
31
38
|
init.duplex = "half";
|
|
32
39
|
}
|
|
33
|
-
const
|
|
34
|
-
|
|
40
|
+
const originalRequest = new Request(url, init);
|
|
41
|
+
if (needsRequestBody) {
|
|
42
|
+
return new Proxy(originalRequest, {
|
|
43
|
+
get(target, prop) {
|
|
44
|
+
if ([
|
|
45
|
+
"json",
|
|
46
|
+
"text",
|
|
47
|
+
"blob",
|
|
48
|
+
"arrayBuffer",
|
|
49
|
+
"formData",
|
|
50
|
+
"body"
|
|
51
|
+
].includes(prop)) {
|
|
52
|
+
cloneableReq.resume();
|
|
53
|
+
}
|
|
54
|
+
return target[prop];
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return originalRequest;
|
|
35
59
|
};
|
|
36
60
|
const sendResponse = async (response, res) => {
|
|
37
61
|
var _response_headers_get;
|
|
@@ -93,7 +93,12 @@ const injectRscManifestPlugin = () => ({
|
|
|
93
93
|
setup(api) {
|
|
94
94
|
return {
|
|
95
95
|
async prepare() {
|
|
96
|
+
var _config_server;
|
|
96
97
|
const { middlewares, distDirectory: pwd } = api.useAppContext();
|
|
98
|
+
const config = api.useConfigContext();
|
|
99
|
+
if (!((_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.rsc)) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
97
102
|
middlewares.push({
|
|
98
103
|
name: "inject-rsc-manifest",
|
|
99
104
|
handler: async (c, next) => {
|
|
@@ -26,7 +26,7 @@ const serverStaticPlugin = () => ({
|
|
|
26
26
|
});
|
|
27
27
|
function createPublicMiddleware({ pwd, routes }) {
|
|
28
28
|
return async (c, next) => {
|
|
29
|
-
const route =
|
|
29
|
+
const route = matchPublicRoute(c.req, routes);
|
|
30
30
|
if (route) {
|
|
31
31
|
const { entryPath } = route;
|
|
32
32
|
const filename = path.join(pwd, entryPath);
|
|
@@ -45,7 +45,7 @@ function createPublicMiddleware({ pwd, routes }) {
|
|
|
45
45
|
return await next();
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
-
function
|
|
48
|
+
function matchPublicRoute(req, routes) {
|
|
49
49
|
for (const route of routes.sort(sortRoutes)) {
|
|
50
50
|
if (!route.isSSR && route.entryPath.startsWith("public") && req.path.startsWith(route.urlPath)) {
|
|
51
51
|
return route;
|
|
@@ -80,7 +80,11 @@ function createStaticMiddleware(options) {
|
|
|
80
80
|
...iconReg
|
|
81
81
|
].join("|")})`);
|
|
82
82
|
return async (c, next) => {
|
|
83
|
+
const pageRoute = c.get("route");
|
|
83
84
|
const pathname = c.req.path;
|
|
85
|
+
if (pageRoute && path.extname(pathname) === "") {
|
|
86
|
+
return next();
|
|
87
|
+
}
|
|
84
88
|
const hit = staticPathRegExp.test(pathname);
|
|
85
89
|
if (hit) {
|
|
86
90
|
const filepath = path.join(pwd, pathname.replace(prefix, () => ""));
|
package/dist/esm-node/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createErrorHtml, onError, ErrorDigest } from "./utils";
|
|
2
2
|
import { AGGRED_DIR } from "./constants";
|
|
3
3
|
import { createServerBase } from "./serverBase";
|
|
4
|
+
import { useHonoContext } from "./context";
|
|
5
|
+
import { Hono } from "hono";
|
|
4
6
|
import { getLoaderCtx } from "./helper";
|
|
5
7
|
export * from "./plugins";
|
|
6
8
|
export * from "./types/plugins";
|
|
@@ -11,8 +13,10 @@ export * from "./types/requestHandler";
|
|
|
11
13
|
export {
|
|
12
14
|
AGGRED_DIR,
|
|
13
15
|
ErrorDigest,
|
|
16
|
+
Hono,
|
|
14
17
|
createErrorHtml,
|
|
15
18
|
createServerBase,
|
|
16
19
|
getLoaderCtx,
|
|
17
|
-
onError
|
|
20
|
+
onError,
|
|
21
|
+
useHonoContext
|
|
18
22
|
};
|
|
@@ -24,14 +24,17 @@ const renderPlugin = () => ({
|
|
|
24
24
|
handler: requestLatencyMiddleware()
|
|
25
25
|
});
|
|
26
26
|
for (const route of pageRoutes) {
|
|
27
|
+
var _config_server;
|
|
27
28
|
const { urlPath: originUrlPath, entryName = MAIN_ENTRY_NAME } = route;
|
|
28
29
|
const urlPath = originUrlPath.endsWith("/") ? `${originUrlPath}*` : `${originUrlPath}/*`;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
if (((_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.disableHook) !== true) {
|
|
31
|
+
const customServerHookMiddleware = customServer.getHookMiddleware(entryName, routes);
|
|
32
|
+
middlewares.push({
|
|
33
|
+
name: "custom-server-hook",
|
|
34
|
+
path: urlPath,
|
|
35
|
+
handler: customServerHookMiddleware
|
|
36
|
+
});
|
|
37
|
+
}
|
|
35
38
|
const customServerMiddleware = await customServer.getServerMiddleware(serverMiddleware);
|
|
36
39
|
customServerMiddleware && middlewares.push({
|
|
37
40
|
name: "custom-server-middleware",
|
|
@@ -54,8 +54,8 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
|
|
|
54
54
|
return async (req, { logger, reporter, metrics, monitors, nodeReq, templates, serverManifest, rscClientManifest, rscSSRManifest, rscServerManifest, locals, matchEntryName, matchPathname, loaderContext }) => {
|
|
55
55
|
const forMatchpathname = matchPathname !== null && matchPathname !== void 0 ? matchPathname : getPathname(req);
|
|
56
56
|
const [routeInfo, params] = matchRoute(router, forMatchpathname, matchEntryName);
|
|
57
|
-
const framework = metaName || "modern-js";
|
|
58
|
-
const fallbackHeader = `x-${
|
|
57
|
+
const framework = cutNameByHyphen(metaName || "modern-js");
|
|
58
|
+
const fallbackHeader = `x-${framework}-ssr-fallback`;
|
|
59
59
|
let fallbackReason = null;
|
|
60
60
|
const fallbackWrapper = async (reason, error) => {
|
|
61
61
|
fallbackReason = reason;
|
|
@@ -113,10 +113,17 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
|
|
|
113
113
|
onError,
|
|
114
114
|
onTiming
|
|
115
115
|
};
|
|
116
|
+
if (fallbackReason) {
|
|
117
|
+
renderOptions.html = injectFallbackReasonToHtml({
|
|
118
|
+
html: renderOptions.html,
|
|
119
|
+
reason: fallbackReason,
|
|
120
|
+
framework
|
|
121
|
+
});
|
|
122
|
+
}
|
|
116
123
|
let response;
|
|
117
124
|
switch (renderMode) {
|
|
118
125
|
case "data":
|
|
119
|
-
response = await dataHandler(req, renderOptions) || await renderHandler(req, renderOptions, "ssr", fallbackWrapper);
|
|
126
|
+
response = await dataHandler(req, renderOptions) || await renderHandler(req, renderOptions, "ssr", fallbackWrapper, framework);
|
|
120
127
|
break;
|
|
121
128
|
case "rsc-tree":
|
|
122
129
|
response = await renderRscHandler(req, renderOptions);
|
|
@@ -126,7 +133,7 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
|
|
|
126
133
|
break;
|
|
127
134
|
case "ssr":
|
|
128
135
|
case "csr":
|
|
129
|
-
response = await renderHandler(req, renderOptions, renderMode, fallbackWrapper);
|
|
136
|
+
response = await renderHandler(req, renderOptions, renderMode, fallbackWrapper, framework);
|
|
130
137
|
break;
|
|
131
138
|
default:
|
|
132
139
|
throw new Error(`Unknown render mode: ${renderMode}`);
|
|
@@ -137,7 +144,7 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
|
|
|
137
144
|
return response;
|
|
138
145
|
};
|
|
139
146
|
}
|
|
140
|
-
async function renderHandler(request, options, mode, fallbackWrapper) {
|
|
147
|
+
async function renderHandler(request, options, mode, fallbackWrapper, framework) {
|
|
141
148
|
var _options_config_server;
|
|
142
149
|
let response = null;
|
|
143
150
|
const { serverManifest } = options;
|
|
@@ -169,7 +176,11 @@ async function renderHandler(request, options, mode, fallbackWrapper) {
|
|
|
169
176
|
} catch (e) {
|
|
170
177
|
options.onError(e, ErrorDigest.ERENDER);
|
|
171
178
|
await fallbackWrapper("error", e);
|
|
172
|
-
response = csrRender(
|
|
179
|
+
response = csrRender(injectFallbackReasonToHtml({
|
|
180
|
+
html: options.html,
|
|
181
|
+
reason: "error",
|
|
182
|
+
framework
|
|
183
|
+
}));
|
|
173
184
|
}
|
|
174
185
|
} else {
|
|
175
186
|
response = csrRender(options.html);
|
|
@@ -195,11 +206,14 @@ async function getRenderMode(req, fallbackHeader, isSSR, forceCSR, nodeReq, onFa
|
|
|
195
206
|
if (query.__loader) {
|
|
196
207
|
return "data";
|
|
197
208
|
}
|
|
198
|
-
|
|
209
|
+
const fallbackHeaderValue = req.headers.get(fallbackHeader) || (nodeReq === null || nodeReq === void 0 ? void 0 : nodeReq.headers[fallbackHeader]);
|
|
210
|
+
if (forceCSR && (query.csr || fallbackHeaderValue)) {
|
|
199
211
|
if (query.csr) {
|
|
200
212
|
await (onFallback === null || onFallback === void 0 ? void 0 : onFallback("query"));
|
|
201
213
|
} else {
|
|
202
|
-
|
|
214
|
+
var _fallbackHeaderValue_split_;
|
|
215
|
+
const reason = fallbackHeaderValue === null || fallbackHeaderValue === void 0 ? void 0 : (_fallbackHeaderValue_split_ = fallbackHeaderValue.split(";")[1]) === null || _fallbackHeaderValue_split_ === void 0 ? void 0 : _fallbackHeaderValue_split_.split("=")[1];
|
|
216
|
+
await (onFallback === null || onFallback === void 0 ? void 0 : onFallback(reason ? `header,${reason}` : "header"));
|
|
203
217
|
}
|
|
204
218
|
return "csr";
|
|
205
219
|
}
|
|
@@ -208,6 +222,12 @@ async function getRenderMode(req, fallbackHeader, isSSR, forceCSR, nodeReq, onFa
|
|
|
208
222
|
return "csr";
|
|
209
223
|
}
|
|
210
224
|
}
|
|
225
|
+
function injectFallbackReasonToHtml({ html, reason, framework }) {
|
|
226
|
+
const tag = `<script id="__${framework}_ssr_fallback_reason__" type="application/json">${JSON.stringify({
|
|
227
|
+
reason
|
|
228
|
+
})}</script>`;
|
|
229
|
+
return html.replace(/<\/head>/, `${tag}</head>`);
|
|
230
|
+
}
|
|
211
231
|
function csrRender(html) {
|
|
212
232
|
return new Response(html, {
|
|
213
233
|
status: 200,
|
|
@@ -2,6 +2,7 @@ import { _ as _class_private_method_get } from "@swc/helpers/_/_class_private_me
|
|
|
2
2
|
import { _ as _class_private_method_init } from "@swc/helpers/_/_class_private_method_init";
|
|
3
3
|
import { server } from "@modern-js/plugin-v2/server";
|
|
4
4
|
import { Hono } from "hono";
|
|
5
|
+
import { run } from "./context";
|
|
5
6
|
import { handleSetupResult } from "./plugins/compat/hooks";
|
|
6
7
|
import { loadConfig } from "./utils";
|
|
7
8
|
var _applyMiddlewares = /* @__PURE__ */ new WeakSet();
|
|
@@ -75,6 +76,7 @@ class ServerBase {
|
|
|
75
76
|
this.serverContext = null;
|
|
76
77
|
this.options = options;
|
|
77
78
|
this.app = new Hono();
|
|
79
|
+
this.app.use("*", run);
|
|
78
80
|
}
|
|
79
81
|
}
|
|
80
82
|
function applyMiddlewares() {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as ah from "async_hooks";
|
|
2
|
+
const createStorage = () => {
|
|
3
|
+
let storage;
|
|
4
|
+
if (typeof ah.AsyncLocalStorage !== "undefined") {
|
|
5
|
+
storage = new ah.AsyncLocalStorage();
|
|
6
|
+
}
|
|
7
|
+
const run = (context, cb) => {
|
|
8
|
+
if (!storage) {
|
|
9
|
+
throw new Error(`Unable to use async_hook, please confirm the node version >= 12.17
|
|
10
|
+
`);
|
|
11
|
+
}
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
storage.run(context, () => {
|
|
14
|
+
try {
|
|
15
|
+
return resolve(cb());
|
|
16
|
+
} catch (error) {
|
|
17
|
+
return reject(error);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
const useHonoContext = () => {
|
|
23
|
+
if (!storage) {
|
|
24
|
+
throw new Error(`Unable to use async_hook, please confirm the node version >= 12.17
|
|
25
|
+
`);
|
|
26
|
+
}
|
|
27
|
+
const context = storage.getStore();
|
|
28
|
+
if (!context) {
|
|
29
|
+
throw new Error(`Can't call useContext out of server scope`);
|
|
30
|
+
}
|
|
31
|
+
return context;
|
|
32
|
+
};
|
|
33
|
+
return {
|
|
34
|
+
run,
|
|
35
|
+
useHonoContext
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
export {
|
|
39
|
+
createStorage
|
|
40
|
+
};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export { createErrorHtml, onError, ErrorDigest } from './utils';
|
|
|
2
2
|
export { AGGRED_DIR } from './constants';
|
|
3
3
|
export type { ServerBase, ServerBaseOptions } from './serverBase';
|
|
4
4
|
export { createServerBase } from './serverBase';
|
|
5
|
+
export { useHonoContext } from './context';
|
|
6
|
+
export { Hono, type MiddlewareHandler } from 'hono';
|
|
5
7
|
export type { Middleware, Context, Next, HonoRequest as InternalRequest, ServerEnv, ServerManifest, ServerLoaderBundle, } from './types';
|
|
6
8
|
export { getLoaderCtx } from './helper';
|
|
7
9
|
export * from './plugins';
|
|
@@ -36,6 +36,11 @@ export interface ServerUserConfig {
|
|
|
36
36
|
*/
|
|
37
37
|
useJsonScript?: boolean;
|
|
38
38
|
logger?: boolean | Record<string, unknown>;
|
|
39
|
+
/**
|
|
40
|
+
* @description disable hook middleware for performance
|
|
41
|
+
* @default false
|
|
42
|
+
*/
|
|
43
|
+
disableHook?: boolean;
|
|
39
44
|
}
|
|
40
45
|
export type ServerNormalizedConfig = ServerUserConfig;
|
|
41
46
|
export {};
|
|
@@ -7,7 +7,7 @@ import type { Render } from '../render';
|
|
|
7
7
|
import type { ServerPlugin } from './new';
|
|
8
8
|
import type { ServerPluginLegacy } from './old';
|
|
9
9
|
export type { FileChangeEvent, ResetEvent } from '@modern-js/plugin-v2';
|
|
10
|
-
export type FallbackReason = 'error' | 'header' | 'query'
|
|
10
|
+
export type FallbackReason = 'error' | 'header' | 'query' | `header,${string}`;
|
|
11
11
|
export type FallbackInput = {
|
|
12
12
|
reason: FallbackReason;
|
|
13
13
|
error: unknown;
|
|
@@ -44,6 +44,7 @@ export type Middleware = {
|
|
|
44
44
|
before?: Array<Middleware['name']>;
|
|
45
45
|
order?: MiddlewareOrder;
|
|
46
46
|
};
|
|
47
|
+
export type ServerMiddleware = Middleware;
|
|
47
48
|
export interface GetRenderHandlerOptions {
|
|
48
49
|
pwd: string;
|
|
49
50
|
routes: ServerRoute[];
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export * from './new';
|
|
2
2
|
export * from './old';
|
|
3
|
-
export type { ServerConfig, CacheConfig, OnFallback, FallbackReason, GetRenderHandlerOptions, FileChangeEvent, FallbackInput, WebServerStartInput, APIServerStartInput, } from './base';
|
|
3
|
+
export type { ServerConfig, CacheConfig, OnFallback, FallbackReason, GetRenderHandlerOptions, FileChangeEvent, FallbackInput, WebServerStartInput, APIServerStartInput, ServerMiddleware, } from './base';
|
package/package.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"modern",
|
|
16
16
|
"modern.js"
|
|
17
17
|
],
|
|
18
|
-
"version": "2.67.
|
|
18
|
+
"version": "2.67.3",
|
|
19
19
|
"jsnext:source": "./src/index.ts",
|
|
20
20
|
"types": "./dist/types/index.d.ts",
|
|
21
21
|
"main": "./dist/cjs/index.js",
|
|
@@ -50,25 +50,27 @@
|
|
|
50
50
|
"@web-std/fetch": "^4.2.1",
|
|
51
51
|
"@web-std/file": "^3.0.3",
|
|
52
52
|
"@web-std/stream": "^1.0.3",
|
|
53
|
+
"cloneable-readable": "^3.0.0",
|
|
53
54
|
"flatted": "^3.2.9",
|
|
54
55
|
"hono": "^3.12.2",
|
|
55
56
|
"ts-deepmerge": "7.0.2",
|
|
56
|
-
"@modern-js/plugin": "2.67.
|
|
57
|
-
"@modern-js/
|
|
58
|
-
"@modern-js/utils": "2.67.
|
|
59
|
-
"@modern-js/
|
|
57
|
+
"@modern-js/plugin": "2.67.3",
|
|
58
|
+
"@modern-js/plugin-v2": "2.67.3",
|
|
59
|
+
"@modern-js/runtime-utils": "2.67.3",
|
|
60
|
+
"@modern-js/utils": "2.67.3"
|
|
60
61
|
},
|
|
61
62
|
"devDependencies": {
|
|
63
|
+
"@types/cloneable-readable": "^2.0.3",
|
|
62
64
|
"@types/jest": "^29",
|
|
63
65
|
"@types/merge-deep": "^3.0.0",
|
|
64
66
|
"@types/node": "^14",
|
|
65
|
-
"http-proxy-middleware": "^2.0.
|
|
67
|
+
"http-proxy-middleware": "^2.0.9",
|
|
66
68
|
"jest": "^29",
|
|
67
69
|
"ts-jest": "^29.1.0",
|
|
68
70
|
"typescript": "^5",
|
|
69
|
-
"@
|
|
71
|
+
"@modern-js/types": "2.67.3",
|
|
70
72
|
"@scripts/jest-config": "2.66.0",
|
|
71
|
-
"@
|
|
73
|
+
"@scripts/build": "2.66.0"
|
|
72
74
|
},
|
|
73
75
|
"sideEffects": false,
|
|
74
76
|
"publishConfig": {
|