@modern-js/server-core 2.67.1 → 2.67.2

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.
@@ -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 = matchRoute(c.req, routes);
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 matchRoute(req, routes) {
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, () => ""));
@@ -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
- const customServerHookMiddleware = customServer.getHookMiddleware(entryName, routes);
54
- middlewares.push({
55
- name: "custom-server-hook",
56
- path: urlPath,
57
- handler: customServerHookMiddleware
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-${(0, import_universal.cutNameByHyphen)(framework)}-ssr-fallback`;
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(options.html);
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
- if (forceCSR && (query.csr || req.headers.get(fallbackHeader) || (nodeReq === null || nodeReq === void 0 ? void 0 : nodeReq.headers[fallbackHeader]))) {
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
- await (onFallback === null || onFallback === void 0 ? void 0 : onFallback("header"));
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,
@@ -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 = matchRoute(c.req, routes);
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 matchRoute(req, routes) {
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 [
@@ -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
- customServerHookMiddleware = customServer.getHookMiddleware(entryName, routes);
56
- middlewares.push({
57
- name: "custom-server-hook",
58
- path: urlPath,
59
- handler: customServerHookMiddleware
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(cutNameByHyphen(framework), "-ssr-fallback");
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(options.html);
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
- if (!(forceCSR && (query.csr || req.headers.get(fallbackHeader) || (nodeReq === null || nodeReq === void 0 ? void 0 : nodeReq.headers[fallbackHeader]))))
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,
@@ -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 = matchRoute(c.req, routes);
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 matchRoute(req, routes) {
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, () => ""));
@@ -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
- const customServerHookMiddleware = customServer.getHookMiddleware(entryName, routes);
30
- middlewares.push({
31
- name: "custom-server-hook",
32
- path: urlPath,
33
- handler: customServerHookMiddleware
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-${cutNameByHyphen(framework)}-ssr-fallback`;
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(options.html);
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
- if (forceCSR && (query.csr || req.headers.get(fallbackHeader) || (nodeReq === null || nodeReq === void 0 ? void 0 : nodeReq.headers[fallbackHeader]))) {
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
- await (onFallback === null || onFallback === void 0 ? void 0 : onFallback("header"));
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,
@@ -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;
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "modern",
16
16
  "modern.js"
17
17
  ],
18
- "version": "2.67.1",
18
+ "version": "2.67.2",
19
19
  "jsnext:source": "./src/index.ts",
20
20
  "types": "./dist/types/index.d.ts",
21
21
  "main": "./dist/cjs/index.js",
@@ -53,10 +53,10 @@
53
53
  "flatted": "^3.2.9",
54
54
  "hono": "^3.12.2",
55
55
  "ts-deepmerge": "7.0.2",
56
- "@modern-js/plugin": "2.67.1",
57
- "@modern-js/runtime-utils": "2.67.1",
58
- "@modern-js/utils": "2.67.1",
59
- "@modern-js/plugin-v2": "2.67.1"
56
+ "@modern-js/plugin": "2.67.2",
57
+ "@modern-js/runtime-utils": "2.67.2",
58
+ "@modern-js/plugin-v2": "2.67.2",
59
+ "@modern-js/utils": "2.67.2"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@types/jest": "^29",
@@ -66,9 +66,9 @@
66
66
  "jest": "^29",
67
67
  "ts-jest": "^29.1.0",
68
68
  "typescript": "^5",
69
+ "@modern-js/types": "2.67.2",
69
70
  "@scripts/build": "2.66.0",
70
- "@scripts/jest-config": "2.66.0",
71
- "@modern-js/types": "2.67.1"
71
+ "@scripts/jest-config": "2.66.0"
72
72
  },
73
73
  "sideEffects": false,
74
74
  "publishConfig": {