@modern-js/server-core 2.58.3 → 2.59.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.
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
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
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
  var customServer_exports = {};
30
20
  __export(customServer_exports, {
@@ -175,7 +165,8 @@ async function createMiddlewareContextFromHono(c) {
175
165
  "GET",
176
166
  "HEAD"
177
167
  ].includes(method) && !rawRequest.body && c.env.node.req) {
178
- const { createReadableStreamFromReadable } = await import("../../adapters/node/polyfills/stream.js");
168
+ const streamModulePath = "../../adapters/node/polyfills/stream.js";
169
+ const { createReadableStreamFromReadable } = await import(streamModulePath);
179
170
  const init = {
180
171
  body: createReadableStreamFromReadable(c.env.node.req),
181
172
  headers: rawRequest.headers,
@@ -31,16 +31,25 @@ const injectRenderHandlerPlugin = ({ staticGenerate, cacheConfig }) => ({
31
31
  var _config_render;
32
32
  const { distDirectory: pwd, routes, metaName } = api.useAppContext();
33
33
  const config = api.useConfigContext();
34
+ const hookRunner = api.useHookRunners();
34
35
  if (!routes) {
35
36
  return;
36
37
  }
38
+ const onFallback = async (reason, utils, error) => {
39
+ await hookRunner.fallback({
40
+ reason,
41
+ ...utils,
42
+ error
43
+ });
44
+ };
37
45
  const getRenderHandlerOptions = {
38
46
  pwd,
39
47
  routes,
40
48
  config,
41
49
  metaName,
42
50
  cacheConfig: ((_config_render = config.render) === null || _config_render === void 0 ? void 0 : _config_render.cache) || cacheConfig,
43
- staticGenerate
51
+ staticGenerate,
52
+ onFallback
44
53
  };
45
54
  const render = await getRenderHandler(getRenderHandlerOptions);
46
55
  api.setAppContext({
@@ -52,7 +61,7 @@ const injectRenderHandlerPlugin = ({ staticGenerate, cacheConfig }) => ({
52
61
  };
53
62
  }
54
63
  });
55
- async function getRenderHandler({ pwd, routes, config, cacheConfig, metaName, staticGenerate }) {
64
+ async function getRenderHandler({ pwd, routes, config, cacheConfig, metaName, staticGenerate, onFallback }) {
56
65
  var _config_server, _config_security;
57
66
  const ssrConfig = (_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.ssr;
58
67
  const forceCSR = typeof ssrConfig === "object" ? ssrConfig.forceCSR : false;
@@ -64,7 +73,8 @@ async function getRenderHandler({ pwd, routes, config, cacheConfig, metaName, st
64
73
  cacheConfig,
65
74
  forceCSR,
66
75
  nonce: (_config_security = config.security) === null || _config_security === void 0 ? void 0 : _config_security.nonce,
67
- metaName: metaName || "modern-js"
76
+ metaName: metaName || "modern-js",
77
+ onFallback
68
78
  });
69
79
  return render;
70
80
  }
@@ -31,11 +31,10 @@ __export(render_exports, {
31
31
  createRender: () => createRender
32
32
  });
33
33
  module.exports = __toCommonJS(render_exports);
34
- var import_utils = require("@modern-js/utils");
35
34
  var import_universal = require("@modern-js/utils/universal");
36
35
  var import_trie_router = require("hono/router/trie-router");
37
36
  var import_constants = require("../../constants");
38
- var import_utils2 = require("../../utils");
37
+ var import_utils = require("../../utils");
39
38
  var import_dataHandler = require("./dataHandler");
40
39
  var import_ssrRender = require("./ssrRender");
41
40
  const DYNAMIC_ROUTE_REG = /\/:./;
@@ -50,8 +49,8 @@ function getRouter(routes) {
50
49
  }
51
50
  });
52
51
  const finalRoutes = [
53
- ...normalRoutes.sort(import_utils2.sortRoutes),
54
- ...dynamicRoutes.sort(import_utils2.sortRoutes)
52
+ ...normalRoutes.sort(import_utils.sortRoutes),
53
+ ...dynamicRoutes.sort(import_utils.sortRoutes)
55
54
  ];
56
55
  const router = new import_trie_router.TrieRouter();
57
56
  for (const route of finalRoutes) {
@@ -77,9 +76,13 @@ function getHeadersWithoutCookie(headers) {
77
76
  async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig, forceCSR, config, onFallback: onFallbackFn }) {
78
77
  const router = getRouter(routes);
79
78
  return async (req, { logger, reporter, metrics, monitors, nodeReq, templates, serverManifest, locals, matchPathname, loaderContext }) => {
80
- const forMatchpathname = matchPathname !== null && matchPathname !== void 0 ? matchPathname : (0, import_utils2.getPathname)(req);
79
+ const forMatchpathname = matchPathname !== null && matchPathname !== void 0 ? matchPathname : (0, import_utils.getPathname)(req);
81
80
  const [routeInfo, params] = matchRoute(router, forMatchpathname);
81
+ const framework = metaName || "modern-js";
82
+ const fallbackHeader = `x-${(0, import_universal.cutNameByHyphen)(framework)}-ssr-fallback`;
83
+ let fallbackReason = null;
82
84
  const onFallback = async (reason, error) => {
85
+ fallbackReason = reason;
83
86
  return onFallbackFn === null || onFallbackFn === void 0 ? void 0 : onFallbackFn(reason, {
84
87
  logger,
85
88
  reporter,
@@ -87,7 +90,7 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
87
90
  }, error);
88
91
  };
89
92
  if (!routeInfo) {
90
- return new Response((0, import_utils2.createErrorHtml)(404), {
93
+ return new Response((0, import_utils.createErrorHtml)(404), {
91
94
  status: 404,
92
95
  headers: {
93
96
  "content-type": "text/html; charset=UTF-8"
@@ -96,16 +99,15 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
96
99
  }
97
100
  const html = templates[routeInfo.entryName];
98
101
  if (!html) {
99
- return new Response((0, import_utils2.createErrorHtml)(404), {
102
+ return new Response((0, import_utils.createErrorHtml)(404), {
100
103
  status: 404,
101
104
  headers: {
102
105
  "content-type": "text/html; charset=UTF-8"
103
106
  }
104
107
  });
105
108
  }
106
- const renderMode = await getRenderMode(req, metaName || "modern-js", routeInfo.isSSR, forceCSR, nodeReq, onFallback);
107
- const pathname = (0, import_utils2.getPathname)(req);
108
- const headerData = (0, import_utils2.parseHeaders)(req);
109
+ const renderMode = await getRenderMode(req, fallbackHeader, routeInfo.isSSR, forceCSR, nodeReq, onFallback);
110
+ const headerData = (0, import_utils.parseHeaders)(req);
109
111
  const onError = (e) => {
110
112
  monitors === null || monitors === void 0 ? void 0 : monitors.error(`SSR Error - ${e instanceof Error ? e.name : e}, error = %s, req.url = %s, req.headers = %o`, e instanceof Error ? e.stack || e.message : e, forMatchpathname, getHeadersWithoutCookie(headerData));
111
113
  };
@@ -113,7 +115,7 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
113
115
  monitors === null || monitors === void 0 ? void 0 : monitors.timing(name, dur, "SSR");
114
116
  };
115
117
  const onBoundError = async (e) => {
116
- (0, import_utils2.onError)(import_utils2.ErrorDigest.ERENDER, e, monitors, req);
118
+ (0, import_utils.onError)(import_utils.ErrorDigest.ERENDER, e, monitors, req);
117
119
  await (onFallback === null || onFallback === void 0 ? void 0 : onFallback("error", e));
118
120
  };
119
121
  const renderOptions = {
@@ -147,6 +149,9 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
147
149
  default:
148
150
  throw new Error(`Unknown render mode: ${renderMode}`);
149
151
  }
152
+ if (fallbackReason) {
153
+ response.headers.set(fallbackHeader, `1;reason=${fallbackReason}`);
154
+ }
150
155
  return response;
151
156
  };
152
157
  }
@@ -161,11 +166,14 @@ async function renderHandler(request, options, mode, onError) {
161
166
  let response = null;
162
167
  const { serverManifest } = options;
163
168
  const ssrByRouteIds = (_options_config_server = options.config.server) === null || _options_config_server === void 0 ? void 0 : _options_config_server.ssrByRouteIds;
164
- if (serverManifest.nestedRoutesJson && ssrByRouteIds && (ssrByRouteIds === null || ssrByRouteIds === void 0 ? void 0 : ssrByRouteIds.length) > 0) {
169
+ const runtimeEnv = (0, import_utils.getRuntimeEnv)();
170
+ if (serverManifest.nestedRoutesJson && ssrByRouteIds && (ssrByRouteIds === null || ssrByRouteIds === void 0 ? void 0 : ssrByRouteIds.length) > 0 && runtimeEnv === "node") {
165
171
  const { nestedRoutesJson } = serverManifest;
166
172
  const routes = nestedRoutesJson === null || nestedRoutesJson === void 0 ? void 0 : nestedRoutesJson[options.routeInfo.entryName];
167
173
  if (routes) {
168
- const { matchRoutes } = await (0, import_utils.compatibleRequire)(require.resolve("@modern-js/runtime-utils/remix-router"), false);
174
+ const urlPath = "node:url";
175
+ const { pathToFileURL } = await import(urlPath);
176
+ const { matchRoutes } = await import(pathToFileURL(require.resolve("@modern-js/runtime-utils/remix-router")).href);
169
177
  const url = new URL(request.url);
170
178
  const matchedRoutes = matchRoutes(routes, url.pathname, options.routeInfo.urlPath);
171
179
  if (!matchedRoutes) {
@@ -189,7 +197,7 @@ async function renderHandler(request, options, mode, onError) {
189
197
  } else {
190
198
  response = csrRender(options.html);
191
199
  }
192
- const newRes = (0, import_utils2.transformResponse)(response, injectServerData(serverData));
200
+ const newRes = (0, import_utils.transformResponse)(response, injectServerData(serverData));
193
201
  const { routeInfo } = options;
194
202
  applyExtendHeaders(newRes, routeInfo);
195
203
  return newRes;
@@ -199,9 +207,8 @@ async function renderHandler(request, options, mode, onError) {
199
207
  });
200
208
  }
201
209
  }
202
- async function getRenderMode(req, framework, isSSR, forceCSR, nodeReq, onFallback) {
203
- const query = (0, import_utils2.parseQuery)(req);
204
- const fallbackHeader = `x-${(0, import_universal.cutNameByHyphen)(framework)}-ssr-fallback`;
210
+ async function getRenderMode(req, fallbackHeader, isSSR, forceCSR, nodeReq, onFallback) {
211
+ const query = (0, import_utils.parseQuery)(req);
205
212
  if (isSSR) {
206
213
  if (query.__loader) {
207
214
  return "data";
@@ -100,6 +100,7 @@ function getAppContext() {
100
100
  middlewares: [],
101
101
  appDirectory: (context === null || context === void 0 ? void 0 : context.appDirectory) || "",
102
102
  apiDirectory: context === null || context === void 0 ? void 0 : context.apiDirectory,
103
+ internalDirectory: (context === null || context === void 0 ? void 0 : context.internalDirectory) || "",
103
104
  lambdaDirectory: context === null || context === void 0 ? void 0 : context.lambdaDirectory,
104
105
  sharedDirectory: (context === null || context === void 0 ? void 0 : context.sharedDirectory) || "",
105
106
  distDirectory: pwd,
@@ -278,7 +278,7 @@ function createMiddlewareContextFromHono(c) {
278
278
  }
279
279
  function _createMiddlewareContextFromHono() {
280
280
  _createMiddlewareContextFromHono = _async_to_generator(function(c) {
281
- var loaderContext, rawRequest, method, createReadableStreamFromReadable, init;
281
+ var loaderContext, rawRequest, method, streamModulePath, createReadableStreamFromReadable, init;
282
282
  return _ts_generator(this, function(_state) {
283
283
  switch (_state.label) {
284
284
  case 0:
@@ -293,9 +293,10 @@ function _createMiddlewareContextFromHono() {
293
293
  3,
294
294
  2
295
295
  ];
296
+ streamModulePath = "../../adapters/node/polyfills/stream.js";
296
297
  return [
297
298
  4,
298
- import("../../adapters/node/polyfills/stream.js")
299
+ import(streamModulePath)
299
300
  ];
300
301
  case 1:
301
302
  createReadableStreamFromReadable = _state.sent().createReadableStreamFromReadable;
@@ -11,24 +11,51 @@ var injectRenderHandlerPlugin = function(param) {
11
11
  return {
12
12
  prepare: function prepare() {
13
13
  return _async_to_generator(function() {
14
- var _config_render, _api_useAppContext, pwd, routes, metaName, config, getRenderHandlerOptions, render;
14
+ var _config_render, _api_useAppContext, pwd, routes, metaName, config, hookRunner, onFallback, getRenderHandlerOptions, render;
15
15
  return _ts_generator(this, function(_state) {
16
16
  switch (_state.label) {
17
17
  case 0:
18
18
  _api_useAppContext = api.useAppContext(), pwd = _api_useAppContext.distDirectory, routes = _api_useAppContext.routes, metaName = _api_useAppContext.metaName;
19
19
  config = api.useConfigContext();
20
+ hookRunner = api.useHookRunners();
20
21
  if (!routes) {
21
22
  return [
22
23
  2
23
24
  ];
24
25
  }
26
+ onFallback = function() {
27
+ var _ref = _async_to_generator(function(reason, utils, error) {
28
+ return _ts_generator(this, function(_state2) {
29
+ switch (_state2.label) {
30
+ case 0:
31
+ return [
32
+ 4,
33
+ hookRunner.fallback(_object_spread_props(_object_spread({
34
+ reason
35
+ }, utils), {
36
+ error
37
+ }))
38
+ ];
39
+ case 1:
40
+ _state2.sent();
41
+ return [
42
+ 2
43
+ ];
44
+ }
45
+ });
46
+ });
47
+ return function onFallback2(reason, utils, error) {
48
+ return _ref.apply(this, arguments);
49
+ };
50
+ }();
25
51
  getRenderHandlerOptions = {
26
52
  pwd,
27
53
  routes,
28
54
  config,
29
55
  metaName,
30
56
  cacheConfig: ((_config_render = config.render) === null || _config_render === void 0 ? void 0 : _config_render.cache) || cacheConfig,
31
- staticGenerate
57
+ staticGenerate,
58
+ onFallback
32
59
  };
33
60
  return [
34
61
  4,
@@ -56,9 +83,9 @@ function getRenderHandler(_) {
56
83
  }
57
84
  function _getRenderHandler() {
58
85
  _getRenderHandler = _async_to_generator(function(param) {
59
- var pwd, routes, config, cacheConfig, metaName, staticGenerate, _config_server, _config_security, ssrConfig, forceCSR, render;
86
+ var pwd, routes, config, cacheConfig, metaName, staticGenerate, onFallback, _config_server, _config_security, ssrConfig, forceCSR, render;
60
87
  return _ts_generator(this, function(_state) {
61
- pwd = param.pwd, routes = param.routes, config = param.config, cacheConfig = param.cacheConfig, metaName = param.metaName, staticGenerate = param.staticGenerate;
88
+ pwd = param.pwd, routes = param.routes, config = param.config, cacheConfig = param.cacheConfig, metaName = param.metaName, staticGenerate = param.staticGenerate, onFallback = param.onFallback;
62
89
  ssrConfig = (_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.ssr;
63
90
  forceCSR = typeof ssrConfig === "object" ? ssrConfig.forceCSR : false;
64
91
  render = createRender({
@@ -69,7 +96,8 @@ function _getRenderHandler() {
69
96
  cacheConfig,
70
97
  forceCSR,
71
98
  nonce: (_config_security = config.security) === null || _config_security === void 0 ? void 0 : _config_security.nonce,
72
- metaName: metaName || "modern-js"
99
+ metaName: metaName || "modern-js",
100
+ onFallback
73
101
  });
74
102
  return [
75
103
  2,
@@ -6,11 +6,10 @@ import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props";
6
6
  import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
7
7
  import { _ as _to_consumable_array } from "@swc/helpers/_/_to_consumable_array";
8
8
  import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
9
- import { compatibleRequire } from "@modern-js/utils";
10
9
  import { cutNameByHyphen } from "@modern-js/utils/universal";
11
10
  import { TrieRouter } from "hono/router/trie-router";
12
11
  import { REPLACE_REG, X_MODERNJS_RENDER } from "../../constants";
13
- import { ErrorDigest, createErrorHtml, getPathname, onError as onErrorFn, parseHeaders, parseQuery, sortRoutes, transformResponse } from "../../utils";
12
+ import { ErrorDigest, createErrorHtml, getPathname, getRuntimeEnv, onError as onErrorFn, parseHeaders, parseQuery, sortRoutes, transformResponse } from "../../utils";
14
13
  import { dataHandler } from "./dataHandler";
15
14
  import { ssrRender } from "./ssrRender";
16
15
  var DYNAMIC_ROUTE_REG = /\/:./;
@@ -75,16 +74,20 @@ function _createRender() {
75
74
  2,
76
75
  function() {
77
76
  var _ref = _async_to_generator(function(req, param2) {
78
- var logger, reporter, metrics, monitors, nodeReq, templates, serverManifest, locals, matchPathname, loaderContext, forMatchpathname, _matchRoute, routeInfo, params, onFallback, html, renderMode, pathname, headerData, onError, onTiming, onBoundError, renderOptions, response, _tmp;
77
+ var logger, reporter, metrics, monitors, nodeReq, templates, serverManifest, locals, matchPathname, loaderContext, forMatchpathname, _matchRoute, routeInfo, params, framework, fallbackHeader, fallbackReason, onFallback, html, renderMode, headerData, onError, onTiming, onBoundError, renderOptions, response, _tmp;
79
78
  return _ts_generator(this, function(_state2) {
80
79
  switch (_state2.label) {
81
80
  case 0:
82
81
  logger = param2.logger, reporter = param2.reporter, metrics = param2.metrics, monitors = param2.monitors, nodeReq = param2.nodeReq, templates = param2.templates, serverManifest = param2.serverManifest, locals = param2.locals, matchPathname = param2.matchPathname, loaderContext = param2.loaderContext;
83
82
  forMatchpathname = matchPathname !== null && matchPathname !== void 0 ? matchPathname : getPathname(req);
84
83
  _matchRoute = _sliced_to_array(matchRoute(router, forMatchpathname), 2), routeInfo = _matchRoute[0], params = _matchRoute[1];
84
+ framework = metaName || "modern-js";
85
+ fallbackHeader = "x-".concat(cutNameByHyphen(framework), "-ssr-fallback");
86
+ fallbackReason = null;
85
87
  onFallback = function() {
86
88
  var _ref2 = _async_to_generator(function(reason, error) {
87
89
  return _ts_generator(this, function(_state3) {
90
+ fallbackReason = reason;
88
91
  return [
89
92
  2,
90
93
  onFallbackFn === null || onFallbackFn === void 0 ? void 0 : onFallbackFn(reason, {
@@ -124,11 +127,10 @@ function _createRender() {
124
127
  }
125
128
  return [
126
129
  4,
127
- getRenderMode(req, metaName || "modern-js", routeInfo.isSSR, forceCSR, nodeReq, onFallback)
130
+ getRenderMode(req, fallbackHeader, routeInfo.isSSR, forceCSR, nodeReq, onFallback)
128
131
  ];
129
132
  case 1:
130
133
  renderMode = _state2.sent();
131
- pathname = getPathname(req);
132
134
  headerData = parseHeaders(req);
133
135
  onError = function(e) {
134
136
  monitors === null || monitors === void 0 ? void 0 : monitors.error("SSR Error - ".concat(_instanceof(e, Error) ? e.name : e, ", error = %s, req.url = %s, req.headers = %o"), _instanceof(e, Error) ? e.stack || e.message : e, forMatchpathname, getHeadersWithoutCookie(headerData));
@@ -237,6 +239,9 @@ function _createRender() {
237
239
  case 8:
238
240
  throw new Error("Unknown render mode: ".concat(renderMode));
239
241
  case 9:
242
+ if (fallbackReason) {
243
+ response.headers.set(fallbackHeader, "1;reason=".concat(fallbackReason));
244
+ }
240
245
  return [
241
246
  2,
242
247
  response
@@ -258,7 +263,7 @@ function renderHandler(request, options, mode, onError) {
258
263
  }
259
264
  function _renderHandler() {
260
265
  _renderHandler = _async_to_generator(function(request, options, mode, onError) {
261
- var _options_config_server, serverData, response, serverManifest, ssrByRouteIds, nestedRoutesJson, routes, matchRoutes, url, matchedRoutes, _lastMatch_route, lastMatch, e, newRes, routeInfo;
266
+ var _options_config_server, serverData, response, serverManifest, ssrByRouteIds, runtimeEnv, nestedRoutesJson, routes, urlPath, pathToFileURL, matchRoutes, url, matchedRoutes, _lastMatch_route, lastMatch, e, newRes, routeInfo;
262
267
  function applyExtendHeaders(r, route) {
263
268
  Object.entries(route.responseHeaders || {}).forEach(function(param) {
264
269
  var _param = _sliced_to_array(param, 2), k = _param[0], v = _param[1];
@@ -277,23 +282,31 @@ function _renderHandler() {
277
282
  response = null;
278
283
  serverManifest = options.serverManifest;
279
284
  ssrByRouteIds = (_options_config_server = options.config.server) === null || _options_config_server === void 0 ? void 0 : _options_config_server.ssrByRouteIds;
280
- if (!(serverManifest.nestedRoutesJson && ssrByRouteIds && (ssrByRouteIds === null || ssrByRouteIds === void 0 ? void 0 : ssrByRouteIds.length) > 0))
285
+ runtimeEnv = getRuntimeEnv();
286
+ if (!(serverManifest.nestedRoutesJson && ssrByRouteIds && (ssrByRouteIds === null || ssrByRouteIds === void 0 ? void 0 : ssrByRouteIds.length) > 0 && runtimeEnv === "node"))
281
287
  return [
282
288
  3,
283
- 2
289
+ 3
284
290
  ];
285
291
  nestedRoutesJson = serverManifest.nestedRoutesJson;
286
292
  routes = nestedRoutesJson === null || nestedRoutesJson === void 0 ? void 0 : nestedRoutesJson[options.routeInfo.entryName];
287
293
  if (!routes)
288
294
  return [
289
295
  3,
290
- 2
296
+ 3
291
297
  ];
298
+ urlPath = "node:url";
292
299
  return [
293
300
  4,
294
- compatibleRequire(require.resolve("@modern-js/runtime-utils/remix-router"), false)
301
+ import(urlPath)
295
302
  ];
296
303
  case 1:
304
+ pathToFileURL = _state.sent().pathToFileURL;
305
+ return [
306
+ 4,
307
+ import(pathToFileURL(require.resolve("@modern-js/runtime-utils/remix-router")).href)
308
+ ];
309
+ case 2:
297
310
  matchRoutes = _state.sent().matchRoutes;
298
311
  url = new URL(request.url);
299
312
  matchedRoutes = matchRoutes(routes, url.pathname, options.routeInfo.urlPath);
@@ -306,53 +319,53 @@ function _renderHandler() {
306
319
  response = csrRender(options.html);
307
320
  }
308
321
  }
309
- _state.label = 2;
310
- case 2:
322
+ _state.label = 3;
323
+ case 3:
311
324
  if (!(mode === "ssr" && !response))
312
325
  return [
313
326
  3,
314
- 8
327
+ 9
315
328
  ];
316
- _state.label = 3;
317
- case 3:
329
+ _state.label = 4;
330
+ case 4:
318
331
  _state.trys.push([
319
- 3,
320
- 5,
332
+ 4,
333
+ 6,
321
334
  ,
322
- 7
335
+ 8
323
336
  ]);
324
337
  return [
325
338
  4,
326
339
  ssrRender(request, options)
327
340
  ];
328
- case 4:
341
+ case 5:
329
342
  response = _state.sent();
330
343
  return [
331
344
  3,
332
- 7
345
+ 8
333
346
  ];
334
- case 5:
347
+ case 6:
335
348
  e = _state.sent();
336
349
  return [
337
350
  4,
338
351
  onError(e)
339
352
  ];
340
- case 6:
353
+ case 7:
341
354
  _state.sent();
342
355
  response = csrRender(options.html);
343
356
  return [
344
357
  3,
345
- 7
358
+ 8
346
359
  ];
347
- case 7:
360
+ case 8:
348
361
  return [
349
362
  3,
350
- 9
363
+ 10
351
364
  ];
352
- case 8:
353
- response = csrRender(options.html);
354
- _state.label = 9;
355
365
  case 9:
366
+ response = csrRender(options.html);
367
+ _state.label = 10;
368
+ case 10:
356
369
  newRes = transformResponse(response, injectServerData(serverData));
357
370
  routeInfo = options.routeInfo;
358
371
  applyExtendHeaders(newRes, routeInfo);
@@ -365,17 +378,16 @@ function _renderHandler() {
365
378
  });
366
379
  return _renderHandler.apply(this, arguments);
367
380
  }
368
- function getRenderMode(req, framework, isSSR, forceCSR, nodeReq, onFallback) {
381
+ function getRenderMode(req, fallbackHeader, isSSR, forceCSR, nodeReq, onFallback) {
369
382
  return _getRenderMode.apply(this, arguments);
370
383
  }
371
384
  function _getRenderMode() {
372
- _getRenderMode = _async_to_generator(function(req, framework, isSSR, forceCSR, nodeReq, onFallback) {
373
- var query, fallbackHeader;
385
+ _getRenderMode = _async_to_generator(function(req, fallbackHeader, isSSR, forceCSR, nodeReq, onFallback) {
386
+ var query;
374
387
  return _ts_generator(this, function(_state) {
375
388
  switch (_state.label) {
376
389
  case 0:
377
390
  query = parseQuery(req);
378
- fallbackHeader = "x-".concat(cutNameByHyphen(framework), "-ssr-fallback");
379
391
  if (!isSSR)
380
392
  return [
381
393
  3,
@@ -136,6 +136,7 @@ function getAppContext() {
136
136
  middlewares: [],
137
137
  appDirectory: (context === null || context === void 0 ? void 0 : context.appDirectory) || "",
138
138
  apiDirectory: context === null || context === void 0 ? void 0 : context.apiDirectory,
139
+ internalDirectory: (context === null || context === void 0 ? void 0 : context.internalDirectory) || "",
139
140
  lambdaDirectory: context === null || context === void 0 ? void 0 : context.lambdaDirectory,
140
141
  sharedDirectory: (context === null || context === void 0 ? void 0 : context.sharedDirectory) || "",
141
142
  distDirectory: pwd,
@@ -141,7 +141,8 @@ async function createMiddlewareContextFromHono(c) {
141
141
  "GET",
142
142
  "HEAD"
143
143
  ].includes(method) && !rawRequest.body && c.env.node.req) {
144
- const { createReadableStreamFromReadable } = await import("../../adapters/node/polyfills/stream.js");
144
+ const streamModulePath = "../../adapters/node/polyfills/stream.js";
145
+ const { createReadableStreamFromReadable } = await import(streamModulePath);
145
146
  const init = {
146
147
  body: createReadableStreamFromReadable(c.env.node.req),
147
148
  headers: rawRequest.headers,
@@ -7,16 +7,25 @@ const injectRenderHandlerPlugin = ({ staticGenerate, cacheConfig }) => ({
7
7
  var _config_render;
8
8
  const { distDirectory: pwd, routes, metaName } = api.useAppContext();
9
9
  const config = api.useConfigContext();
10
+ const hookRunner = api.useHookRunners();
10
11
  if (!routes) {
11
12
  return;
12
13
  }
14
+ const onFallback = async (reason, utils, error) => {
15
+ await hookRunner.fallback({
16
+ reason,
17
+ ...utils,
18
+ error
19
+ });
20
+ };
13
21
  const getRenderHandlerOptions = {
14
22
  pwd,
15
23
  routes,
16
24
  config,
17
25
  metaName,
18
26
  cacheConfig: ((_config_render = config.render) === null || _config_render === void 0 ? void 0 : _config_render.cache) || cacheConfig,
19
- staticGenerate
27
+ staticGenerate,
28
+ onFallback
20
29
  };
21
30
  const render = await getRenderHandler(getRenderHandlerOptions);
22
31
  api.setAppContext({
@@ -28,7 +37,7 @@ const injectRenderHandlerPlugin = ({ staticGenerate, cacheConfig }) => ({
28
37
  };
29
38
  }
30
39
  });
31
- async function getRenderHandler({ pwd, routes, config, cacheConfig, metaName, staticGenerate }) {
40
+ async function getRenderHandler({ pwd, routes, config, cacheConfig, metaName, staticGenerate, onFallback }) {
32
41
  var _config_server, _config_security;
33
42
  const ssrConfig = (_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.ssr;
34
43
  const forceCSR = typeof ssrConfig === "object" ? ssrConfig.forceCSR : false;
@@ -40,7 +49,8 @@ async function getRenderHandler({ pwd, routes, config, cacheConfig, metaName, st
40
49
  cacheConfig,
41
50
  forceCSR,
42
51
  nonce: (_config_security = config.security) === null || _config_security === void 0 ? void 0 : _config_security.nonce,
43
- metaName: metaName || "modern-js"
52
+ metaName: metaName || "modern-js",
53
+ onFallback
44
54
  });
45
55
  return render;
46
56
  }
@@ -1,8 +1,7 @@
1
- import { compatibleRequire } from "@modern-js/utils";
2
1
  import { cutNameByHyphen } from "@modern-js/utils/universal";
3
2
  import { TrieRouter } from "hono/router/trie-router";
4
3
  import { REPLACE_REG, X_MODERNJS_RENDER } from "../../constants";
5
- import { ErrorDigest, createErrorHtml, getPathname, onError as onErrorFn, parseHeaders, parseQuery, sortRoutes, transformResponse } from "../../utils";
4
+ import { ErrorDigest, createErrorHtml, getPathname, getRuntimeEnv, onError as onErrorFn, parseHeaders, parseQuery, sortRoutes, transformResponse } from "../../utils";
6
5
  import { dataHandler } from "./dataHandler";
7
6
  import { ssrRender } from "./ssrRender";
8
7
  const DYNAMIC_ROUTE_REG = /\/:./;
@@ -46,7 +45,11 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
46
45
  return async (req, { logger, reporter, metrics, monitors, nodeReq, templates, serverManifest, locals, matchPathname, loaderContext }) => {
47
46
  const forMatchpathname = matchPathname !== null && matchPathname !== void 0 ? matchPathname : getPathname(req);
48
47
  const [routeInfo, params] = matchRoute(router, forMatchpathname);
48
+ const framework = metaName || "modern-js";
49
+ const fallbackHeader = `x-${cutNameByHyphen(framework)}-ssr-fallback`;
50
+ let fallbackReason = null;
49
51
  const onFallback = async (reason, error) => {
52
+ fallbackReason = reason;
50
53
  return onFallbackFn === null || onFallbackFn === void 0 ? void 0 : onFallbackFn(reason, {
51
54
  logger,
52
55
  reporter,
@@ -70,8 +73,7 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
70
73
  }
71
74
  });
72
75
  }
73
- const renderMode = await getRenderMode(req, metaName || "modern-js", routeInfo.isSSR, forceCSR, nodeReq, onFallback);
74
- const pathname = getPathname(req);
76
+ const renderMode = await getRenderMode(req, fallbackHeader, routeInfo.isSSR, forceCSR, nodeReq, onFallback);
75
77
  const headerData = parseHeaders(req);
76
78
  const onError = (e) => {
77
79
  monitors === null || monitors === void 0 ? void 0 : monitors.error(`SSR Error - ${e instanceof Error ? e.name : e}, error = %s, req.url = %s, req.headers = %o`, e instanceof Error ? e.stack || e.message : e, forMatchpathname, getHeadersWithoutCookie(headerData));
@@ -114,6 +116,9 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
114
116
  default:
115
117
  throw new Error(`Unknown render mode: ${renderMode}`);
116
118
  }
119
+ if (fallbackReason) {
120
+ response.headers.set(fallbackHeader, `1;reason=${fallbackReason}`);
121
+ }
117
122
  return response;
118
123
  };
119
124
  }
@@ -128,11 +133,14 @@ async function renderHandler(request, options, mode, onError) {
128
133
  let response = null;
129
134
  const { serverManifest } = options;
130
135
  const ssrByRouteIds = (_options_config_server = options.config.server) === null || _options_config_server === void 0 ? void 0 : _options_config_server.ssrByRouteIds;
131
- if (serverManifest.nestedRoutesJson && ssrByRouteIds && (ssrByRouteIds === null || ssrByRouteIds === void 0 ? void 0 : ssrByRouteIds.length) > 0) {
136
+ const runtimeEnv = getRuntimeEnv();
137
+ if (serverManifest.nestedRoutesJson && ssrByRouteIds && (ssrByRouteIds === null || ssrByRouteIds === void 0 ? void 0 : ssrByRouteIds.length) > 0 && runtimeEnv === "node") {
132
138
  const { nestedRoutesJson } = serverManifest;
133
139
  const routes = nestedRoutesJson === null || nestedRoutesJson === void 0 ? void 0 : nestedRoutesJson[options.routeInfo.entryName];
134
140
  if (routes) {
135
- const { matchRoutes } = await compatibleRequire(require.resolve("@modern-js/runtime-utils/remix-router"), false);
141
+ const urlPath = "node:url";
142
+ const { pathToFileURL } = await import(urlPath);
143
+ const { matchRoutes } = await import(pathToFileURL(require.resolve("@modern-js/runtime-utils/remix-router")).href);
136
144
  const url = new URL(request.url);
137
145
  const matchedRoutes = matchRoutes(routes, url.pathname, options.routeInfo.urlPath);
138
146
  if (!matchedRoutes) {
@@ -166,9 +174,8 @@ async function renderHandler(request, options, mode, onError) {
166
174
  });
167
175
  }
168
176
  }
169
- async function getRenderMode(req, framework, isSSR, forceCSR, nodeReq, onFallback) {
177
+ async function getRenderMode(req, fallbackHeader, isSSR, forceCSR, nodeReq, onFallback) {
170
178
  const query = parseQuery(req);
171
- const fallbackHeader = `x-${cutNameByHyphen(framework)}-ssr-fallback`;
172
179
  if (isSSR) {
173
180
  if (query.__loader) {
174
181
  return "data";
@@ -76,6 +76,7 @@ function getAppContext() {
76
76
  middlewares: [],
77
77
  appDirectory: (context === null || context === void 0 ? void 0 : context.appDirectory) || "",
78
78
  apiDirectory: context === null || context === void 0 ? void 0 : context.apiDirectory,
79
+ internalDirectory: (context === null || context === void 0 ? void 0 : context.internalDirectory) || "",
79
80
  lambdaDirectory: context === null || context === void 0 ? void 0 : context.lambdaDirectory,
80
81
  sharedDirectory: (context === null || context === void 0 ? void 0 : context.sharedDirectory) || "",
81
82
  distDirectory: pwd,
@@ -4,4 +4,4 @@ export interface InjectRenderHandlerOptions {
4
4
  cacheConfig?: CacheConfig;
5
5
  }
6
6
  export declare const injectRenderHandlerPlugin: ({ staticGenerate, cacheConfig, }: InjectRenderHandlerOptions) => ServerPlugin;
7
- export declare function getRenderHandler({ pwd, routes, config, cacheConfig, metaName, staticGenerate, }: GetRenderHandlerOptions): Promise<Render>;
7
+ export declare function getRenderHandler({ pwd, routes, config, cacheConfig, metaName, staticGenerate, onFallback, }: GetRenderHandlerOptions): Promise<Render>;
@@ -1,11 +1,6 @@
1
- import type { Logger, Metrics, Reporter, ServerRoute } from '@modern-js/types';
2
- import type { CacheConfig, FallbackReason, UserConfig } from '../../types';
1
+ import type { ServerRoute } from '@modern-js/types';
2
+ import type { CacheConfig, OnFallback, UserConfig } from '../../types';
3
3
  import type { Render } from '../../types';
4
- export type OnFallback = (reason: FallbackReason, utils: {
5
- logger: Logger;
6
- metrics?: Metrics;
7
- reporter?: Reporter;
8
- }, error?: unknown) => Promise<void>;
9
4
  interface CreateRenderOptions {
10
5
  pwd: string;
11
6
  routes: ServerRoute[];
@@ -27,6 +27,11 @@ type FallbackInput = {
27
27
  metrics?: Metrics;
28
28
  reporter?: Reporter;
29
29
  };
30
+ export type OnFallback = (reason: FallbackReason, utils: {
31
+ logger: Logger;
32
+ metrics?: Metrics;
33
+ reporter?: Reporter;
34
+ }, error?: unknown) => Promise<void>;
30
35
  export type APIServerStartInput = {
31
36
  pwd: string;
32
37
  prefix?: string;
@@ -100,6 +105,7 @@ export interface GetRenderHandlerOptions {
100
105
  pwd: string;
101
106
  routes: ServerRoute[];
102
107
  config: UserConfig;
108
+ onFallback?: OnFallback;
103
109
  cacheConfig?: CacheConfig;
104
110
  staticGenerate?: boolean;
105
111
  metaName?: string;
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "modern",
16
16
  "modern.js"
17
17
  ],
18
- "version": "2.58.3",
18
+ "version": "2.59.0",
19
19
  "jsnext:source": "./src/index.ts",
20
20
  "types": "./dist/types/index.d.ts",
21
21
  "main": "./dist/cjs/index.js",
@@ -53,9 +53,9 @@
53
53
  "flatted": "^3.2.9",
54
54
  "hono": "^3.12.2",
55
55
  "ts-deepmerge": "7.0.0",
56
- "@modern-js/plugin": "2.58.3",
57
- "@modern-js/runtime-utils": "2.58.3",
58
- "@modern-js/utils": "2.58.3"
56
+ "@modern-js/plugin": "2.59.0",
57
+ "@modern-js/utils": "2.59.0",
58
+ "@modern-js/runtime-utils": "2.59.0"
59
59
  },
60
60
  "devDependencies": {
61
61
  "@types/jest": "^29",
@@ -65,9 +65,9 @@
65
65
  "jest": "^29",
66
66
  "ts-jest": "^29.1.0",
67
67
  "typescript": "^5",
68
- "@modern-js/types": "2.58.3",
69
- "@scripts/build": "2.58.3",
70
- "@scripts/jest-config": "2.58.3"
68
+ "@modern-js/types": "2.59.0",
69
+ "@scripts/build": "2.59.0",
70
+ "@scripts/jest-config": "2.59.0"
71
71
  },
72
72
  "sideEffects": false,
73
73
  "publishConfig": {