@modern-js/prod-server 2.27.0 → 2.29.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/cjs/index.js +4 -0
  3. package/dist/cjs/libs/context/context.js +10 -4
  4. package/dist/cjs/libs/hook-api/index.js +2 -1
  5. package/dist/cjs/libs/hook-api/index.worker.js +2 -1
  6. package/dist/cjs/libs/render/cache/__tests__/cache.test.js +12 -7
  7. package/dist/cjs/libs/render/cache/index.js +2 -1
  8. package/dist/cjs/libs/render/cache/spr.js +2 -1
  9. package/dist/cjs/libs/render/index.js +12 -3
  10. package/dist/cjs/libs/render/reader.js +2 -1
  11. package/dist/cjs/libs/render/ssr.js +3 -20
  12. package/dist/cjs/libs/reporter.js +22 -0
  13. package/dist/cjs/libs/route/matcher.js +2 -2
  14. package/dist/cjs/libs/serverTiming.js +27 -0
  15. package/dist/cjs/server/index.js +6 -4
  16. package/dist/cjs/server/modernServer.js +44 -16
  17. package/dist/cjs/utils.js +33 -0
  18. package/dist/cjs/workerServer.js +15 -6
  19. package/dist/esm/index.js +1 -0
  20. package/dist/esm/libs/context/context.js +8 -2
  21. package/dist/esm/libs/hook-api/index.js +2 -1
  22. package/dist/esm/libs/hook-api/index.worker.js +2 -1
  23. package/dist/esm/libs/render/cache/__tests__/cache.test.js +12 -12
  24. package/dist/esm/libs/render/cache/index.js +2 -2
  25. package/dist/esm/libs/render/cache/spr.js +2 -2
  26. package/dist/esm/libs/render/index.js +12 -3
  27. package/dist/esm/libs/render/reader.js +2 -2
  28. package/dist/esm/libs/render/ssr.js +6 -28
  29. package/dist/esm/libs/reporter.js +12 -0
  30. package/dist/esm/libs/route/matcher.js +2 -2
  31. package/dist/esm/libs/serverTiming.js +27 -0
  32. package/dist/esm/renderHtml.js +6 -6
  33. package/dist/esm/server/index.js +6 -4
  34. package/dist/esm/server/modernServer.js +84 -44
  35. package/dist/esm/server/modernServerSplit.js +6 -6
  36. package/dist/esm/utils.js +57 -0
  37. package/dist/esm/workerServer.js +14 -5
  38. package/dist/esm-node/index.js +1 -0
  39. package/dist/esm-node/libs/context/context.js +8 -2
  40. package/dist/esm-node/libs/hook-api/index.js +2 -1
  41. package/dist/esm-node/libs/hook-api/index.worker.js +2 -1
  42. package/dist/esm-node/libs/render/cache/__tests__/cache.test.js +12 -7
  43. package/dist/esm-node/libs/render/cache/index.js +2 -1
  44. package/dist/esm-node/libs/render/cache/spr.js +2 -1
  45. package/dist/esm-node/libs/render/index.js +12 -3
  46. package/dist/esm-node/libs/render/reader.js +2 -1
  47. package/dist/esm-node/libs/render/ssr.js +3 -20
  48. package/dist/esm-node/libs/reporter.js +12 -0
  49. package/dist/esm-node/libs/route/matcher.js +2 -2
  50. package/dist/esm-node/libs/serverTiming.js +17 -0
  51. package/dist/esm-node/server/index.js +6 -4
  52. package/dist/esm-node/server/modernServer.js +45 -17
  53. package/dist/esm-node/utils.js +30 -0
  54. package/dist/esm-node/workerServer.js +15 -6
  55. package/dist/types/index.d.ts +1 -0
  56. package/dist/types/libs/context/context.d.ts +5 -2
  57. package/dist/types/libs/hook-api/index.worker.d.ts +2 -1
  58. package/dist/types/libs/render/index.d.ts +13 -18
  59. package/dist/types/libs/reporter.d.ts +2 -0
  60. package/dist/types/libs/serverTiming.d.ts +12 -0
  61. package/dist/types/server/modernServer.d.ts +6 -4
  62. package/dist/types/type.d.ts +1 -0
  63. package/dist/types/utils.d.ts +3 -2
  64. package/package.json +8 -8
@@ -141,9 +141,10 @@ class CacheManager {
141
141
  return maybeSync(doCache)(sync);
142
142
  }
143
143
  async del(context, cacheHash) {
144
+ var _data;
144
145
  const cacheKey = this.generateRequestKey(context);
145
146
  const data = this.cache.get(cacheKey);
146
- data === null || data === void 0 ? void 0 : data.caches.del(cacheHash);
147
+ (_data = data) === null || _data === void 0 ? void 0 : _data.caches.del(cacheHash);
147
148
  }
148
149
  constructor(cacheOptions) {
149
150
  _define_property(this, "cache", void 0);
@@ -5,7 +5,7 @@ import { handleDirectory } from "./static";
5
5
  import { readFile } from "./reader";
6
6
  import * as ssr from "./ssr";
7
7
  import { injectServerData } from "./utils";
8
- export const createRenderHandler = ({ distDir, staticGenerate, forceCSR, nonce, metaName = "modern-js" }) => async function render({ ctx, route, runner }) {
8
+ export const createRenderHandler = ({ distDir, staticGenerate, forceCSR, nonce, ssrRender, metaName = "modern-js" }) => async function render({ ctx, route, runner }) {
9
9
  if (ctx.resHasHandled()) {
10
10
  return null;
11
11
  }
@@ -23,7 +23,7 @@ export const createRenderHandler = ({ distDir, staticGenerate, forceCSR, nonce,
23
23
  const useCSR = forceCSR && (ctx.query.csr || ctx.headers[`x-${cutNameByHyphen(metaName)}-ssr-fallback`]);
24
24
  if (route.isSSR && !useCSR) {
25
25
  try {
26
- const result = await ssr.render(ctx, {
26
+ const ssrRenderOptions = {
27
27
  distDir,
28
28
  entryName: route.entryName,
29
29
  urlPath: route.urlPath,
@@ -31,7 +31,16 @@ export const createRenderHandler = ({ distDir, staticGenerate, forceCSR, nonce,
31
31
  template: content.toString(),
32
32
  staticGenerate,
33
33
  nonce
34
- }, runner);
34
+ };
35
+ const result = await (ssrRender ? ssrRender(ctx, ssrRenderOptions, runner) : ssr.render(ctx, {
36
+ distDir,
37
+ entryName: route.entryName,
38
+ urlPath: route.urlPath,
39
+ bundle: route.bundle,
40
+ template: content.toString(),
41
+ staticGenerate,
42
+ nonce
43
+ }, runner));
35
44
  return result;
36
45
  } catch (err) {
37
46
  ctx.error(ERROR_DIGEST.ERENDER, err.stack || err.message);
@@ -72,8 +72,9 @@ export class LruReader {
72
72
  }
73
73
  const reader = new LruReader();
74
74
  export const readFile = async (filepath) => {
75
+ var _file;
75
76
  const file = await reader.read(filepath);
76
- return file === null || file === void 0 ? void 0 : file.content;
77
+ return (_file = file) === null || _file === void 0 ? void 0 : _file.content;
77
78
  };
78
79
  export const updateFile = () => {
79
80
  reader.update();
@@ -11,7 +11,6 @@ export const render = async (ctx, renderOptions, runner) => {
11
11
  const loadableStats = fs.existsSync(loadableUri) ? require(loadableUri) : "";
12
12
  const routesManifestUri = path.join(distDir, ROUTE_MANIFEST_FILE);
13
13
  const routeManifest = fs.existsSync(routesManifestUri) ? require(routesManifestUri) : void 0;
14
- const body = await getRequestBody(ctx.req);
15
14
  const context = {
16
15
  request: {
17
16
  baseUrl: urlPath,
@@ -21,7 +20,7 @@ export const render = async (ctx, renderOptions, runner) => {
21
20
  query: ctx.query,
22
21
  url: ctx.href,
23
22
  headers: ctx.headers,
24
- body
23
+ body: ctx.req.body
25
24
  },
26
25
  response: {
27
26
  setHeader: (key, value) => {
@@ -40,6 +39,8 @@ export const render = async (ctx, renderOptions, runner) => {
40
39
  staticGenerate,
41
40
  logger: void 0,
42
41
  metrics: void 0,
42
+ reporter: ctx.reporter,
43
+ serverTiming: ctx.serverTiming,
43
44
  req: ctx.req,
44
45
  res: ctx.res,
45
46
  enableUnsafeCtx,
@@ -73,21 +74,3 @@ export const render = async (ctx, renderOptions, runner) => {
73
74
  };
74
75
  }
75
76
  };
76
- const getRequestBody = (req) => {
77
- return new Promise((resolve, reject) => {
78
- if ((req === null || req === void 0 ? void 0 : req.method) && req.method.toLowerCase() !== "get") {
79
- let body = "";
80
- req.on("data", (chunk) => {
81
- body += chunk.toString();
82
- });
83
- req.on("end", () => {
84
- resolve(body);
85
- });
86
- req.on("error", (err) => {
87
- reject(err);
88
- });
89
- } else {
90
- resolve(void 0);
91
- }
92
- });
93
- };
@@ -0,0 +1,12 @@
1
+ export const defaultReporter = {
2
+ init() {
3
+ },
4
+ reportError() {
5
+ },
6
+ reportTiming() {
7
+ },
8
+ reportInfo() {
9
+ },
10
+ reportWarn() {
11
+ }
12
+ };
@@ -39,9 +39,9 @@ export class RouteMatcher {
39
39
  if (!this.urlReg) {
40
40
  return this.urlPath.length;
41
41
  } else {
42
- var _result_;
42
+ var _result_, _result;
43
43
  const result = this.urlReg.exec(pathname);
44
- return (result === null || result === void 0 ? void 0 : (_result_ = result[0]) === null || _result_ === void 0 ? void 0 : _result_.length) || null;
44
+ return ((_result = result) === null || _result === void 0 ? void 0 : (_result_ = _result[0]) === null || _result_ === void 0 ? void 0 : _result_.length) || null;
45
45
  }
46
46
  }
47
47
  // if match url path
@@ -0,0 +1,17 @@
1
+ import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
+ const SERVER_TIMING = "Server-Timing";
3
+ export class ServerTiming {
4
+ addServeTiming(name, dur, desc) {
5
+ const _name = `bd-${this.meta}-${name}`;
6
+ const serverTiming = this.res.getHeader(SERVER_TIMING) || this.res.getHeader(SERVER_TIMING.toLocaleLowerCase());
7
+ const value = `${_name};${desc ? `decs="${desc}";` : ""} dur=${dur}`;
8
+ this.res.setHeader(SERVER_TIMING, serverTiming ? `${serverTiming}, ${value}` : value);
9
+ return this;
10
+ }
11
+ constructor(res, meta) {
12
+ _define_property(this, "meta", void 0);
13
+ _define_property(this, "res", void 0);
14
+ this.meta = meta;
15
+ this.res = res;
16
+ }
17
+ }
@@ -78,7 +78,8 @@ export class Server {
78
78
  }
79
79
  listen(options, listener) {
80
80
  const callback = () => {
81
- listener === null || listener === void 0 ? void 0 : listener();
81
+ var _listener;
82
+ (_listener = listener) === null || _listener === void 0 ? void 0 : _listener();
82
83
  };
83
84
  if (typeof options === "object") {
84
85
  if (process.env.PORT) {
@@ -128,6 +129,7 @@ export class Server {
128
129
  });
129
130
  }
130
131
  initAppContext() {
132
+ var _appContext, _appContext1, _appContext2;
131
133
  const { options } = this;
132
134
  const { pwd: appDirectory, plugins = [], config, appContext } = options;
133
135
  const serverPlugins = plugins.map((p) => ({
@@ -135,9 +137,9 @@ export class Server {
135
137
  }));
136
138
  return {
137
139
  appDirectory,
138
- apiDirectory: appContext === null || appContext === void 0 ? void 0 : appContext.apiDirectory,
139
- lambdaDirectory: appContext === null || appContext === void 0 ? void 0 : appContext.lambdaDirectory,
140
- sharedDirectory: (appContext === null || appContext === void 0 ? void 0 : appContext.sharedDirectory) || path.resolve(appDirectory, SHARED_DIR),
140
+ apiDirectory: (_appContext = appContext) === null || _appContext === void 0 ? void 0 : _appContext.apiDirectory,
141
+ lambdaDirectory: (_appContext1 = appContext) === null || _appContext1 === void 0 ? void 0 : _appContext1.lambdaDirectory,
142
+ sharedDirectory: ((_appContext2 = appContext) === null || _appContext2 === void 0 ? void 0 : _appContext2.sharedDirectory) || path.resolve(appDirectory, SHARED_DIR),
141
143
  distDirectory: path.join(appDirectory, config.output.path || "dist"),
142
144
  plugins: serverPlugins
143
145
  };
@@ -2,10 +2,11 @@ import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
2
  import { createServer } from "http";
3
3
  import path from "path";
4
4
  import { fs, isPromise, isWebOnly, mime, ROUTE_SPEC_FILE } from "@modern-js/utils";
5
+ import { time } from "@modern-js/utils/universal/time";
5
6
  import { RouteMatchManager } from "../libs/route";
6
7
  import { createRenderHandler } from "../libs/render";
7
8
  import { createStaticFileHandler, faviconFallbackHandler } from "../libs/serveFile";
8
- import { createErrorDocument, createMiddlewareCollecter, getStaticReg, mergeExtension, noop, debug, isRedirect } from "../utils";
9
+ import { createErrorDocument, createMiddlewareCollecter, getStaticReg, mergeExtension, noop, debug, isRedirect, bodyParser } from "../utils";
9
10
  import * as reader from "../libs/render/reader";
10
11
  import { createProxyHandler } from "../libs/proxy";
11
12
  import { createContext } from "../libs/context";
@@ -15,9 +16,9 @@ const SERVER_DIR = "./server";
15
16
  export class ModernServer {
16
17
  // server prepare
17
18
  async onInit(runner, app) {
18
- var _conf_bff, _this_conf_server, _conf_security, _this_conf_output;
19
+ var _conf_bff, _app, _this_conf_output;
19
20
  this.runner = runner;
20
- const { distDir, staticGenerate, conf, metaName } = this;
21
+ const { distDir, conf } = this;
21
22
  this.initReader();
22
23
  debug("final server conf", this.conf);
23
24
  this.proxyHandler = createProxyHandler((_conf_bff = conf.bff) === null || _conf_bff === void 0 ? void 0 : _conf_bff.proxy);
@@ -26,7 +27,7 @@ export class ModernServer {
26
27
  this.addHandler(handler);
27
28
  });
28
29
  }
29
- app === null || app === void 0 ? void 0 : app.on("close", () => {
30
+ (_app = app) === null || _app === void 0 ? void 0 : _app.on("close", () => {
30
31
  this.reader.close();
31
32
  });
32
33
  const usageRoutes = this.filterRoutes(this.getRoutes());
@@ -34,20 +35,25 @@ export class ModernServer {
34
35
  this.warmupSSRBundle();
35
36
  await this.prepareFrameHandler();
36
37
  await this.prepareLoaderHandler(usageRoutes, distDir);
38
+ this.routeRenderHandler = this.getRenderHandler();
39
+ await this.setupBeforeProdMiddleware();
40
+ this.addHandler(this.setupStaticMiddleware((_this_conf_output = this.conf.output) === null || _this_conf_output === void 0 ? void 0 : _this_conf_output.assetPrefix));
41
+ this.addHandler(faviconFallbackHandler);
42
+ this.addHandler(this.routeHandler.bind(this));
43
+ this.compose();
44
+ }
45
+ getRenderHandler() {
46
+ var _this_conf_server, _conf_security;
47
+ const { distDir, staticGenerate, conf, metaName } = this;
37
48
  const ssrConfig = (_this_conf_server = this.conf.server) === null || _this_conf_server === void 0 ? void 0 : _this_conf_server.ssr;
38
49
  const forceCSR = typeof ssrConfig === "object" ? ssrConfig.forceCSR : false;
39
- this.routeRenderHandler = createRenderHandler({
50
+ return createRenderHandler({
40
51
  distDir,
41
52
  staticGenerate,
42
53
  forceCSR,
43
54
  nonce: (_conf_security = conf.security) === null || _conf_security === void 0 ? void 0 : _conf_security.nonce,
44
55
  metaName
45
56
  });
46
- await this.setupBeforeProdMiddleware();
47
- this.addHandler(this.setupStaticMiddleware((_this_conf_output = this.conf.output) === null || _this_conf_output === void 0 ? void 0 : _this_conf_output.assetPrefix));
48
- this.addHandler(faviconFallbackHandler);
49
- this.addHandler(this.routeHandler.bind(this));
50
- this.compose();
51
57
  }
52
58
  // server ready
53
59
  onRepack(_) {
@@ -59,7 +65,9 @@ export class ModernServer {
59
65
  async render(req, res, url) {
60
66
  req.logger = req.logger || this.logger;
61
67
  req.metrics = req.metrics || this.metrics;
62
- const context = createContext(req, res);
68
+ const context = createContext(req, res, {
69
+ metaName: this.metaName
70
+ });
63
71
  const matched = this.router.match(url || context.path);
64
72
  if (!matched) {
65
73
  return null;
@@ -153,9 +161,10 @@ export class ModernServer {
153
161
  return handler;
154
162
  }
155
163
  async prepareAPIHandler(extension) {
164
+ var _bff, _bff1;
156
165
  const { workDir, runner, conf } = this;
157
166
  const { bff } = conf;
158
- const prefix = (bff === null || bff === void 0 ? void 0 : bff.prefix) || "/api";
167
+ const prefix = ((_bff = bff) === null || _bff === void 0 ? void 0 : _bff.prefix) || "/api";
159
168
  const webOnly = await isWebOnly();
160
169
  if (webOnly && process.env.NODE_ENV === "development") {
161
170
  return (req, res) => {
@@ -167,7 +176,7 @@ export class ModernServer {
167
176
  pwd: workDir,
168
177
  config: extension,
169
178
  prefix: Array.isArray(prefix) ? prefix[0] : prefix,
170
- httpMethodDecider: bff === null || bff === void 0 ? void 0 : bff.httpMethodDecider,
179
+ httpMethodDecider: (_bff1 = bff) === null || _bff1 === void 0 ? void 0 : _bff1.httpMethodDecider,
171
180
  render: this.render.bind(this)
172
181
  }, {
173
182
  onLast: () => null
@@ -259,23 +268,35 @@ export class ModernServer {
259
268
  /* —————————————————————— private function —————————————————————— */
260
269
  // handler route.json, include api / csr / ssr
261
270
  async routeHandler(context) {
262
- const { res } = context;
271
+ const { res, req, reporter } = context;
263
272
  const matched = this.router.match(context.path);
264
273
  if (!matched) {
265
274
  this.render404(context);
266
275
  return;
267
276
  }
277
+ await reporter.init({
278
+ match: matched
279
+ });
280
+ const end = time();
281
+ res.on("finish", () => {
282
+ const cost = end();
283
+ reporter.reportTiming("server_handle_request", cost);
284
+ });
268
285
  let route = matched.generate(context.url);
269
286
  if (route.isApi) {
270
287
  await this.handleAPI(context);
271
288
  return;
272
289
  }
290
+ await bodyParser(req);
273
291
  if (route.entryName) {
274
292
  const afterMatchContext = createAfterMatchContext(context, route.entryName);
275
293
  if (this.runMode === RUN_MODE.FULL) {
294
+ const end2 = time();
276
295
  await this.runner.afterMatch(afterMatchContext, {
277
296
  onLast: noop
278
297
  });
298
+ const cost = end2();
299
+ reporter.reportTiming("server_hook_after_render", cost);
279
300
  }
280
301
  if (this.isSend(res)) {
281
302
  return;
@@ -297,7 +318,10 @@ export class ModernServer {
297
318
  if (this.frameWebHandler) {
298
319
  res.locals = res.locals || {};
299
320
  const middlewareContext = createMiddlewareContext(context);
321
+ const end2 = time();
300
322
  await this.frameWebHandler(middlewareContext);
323
+ const cost = end2();
324
+ reporter.reportTiming("server_middleware", cost);
301
325
  res.locals = {
302
326
  ...res.locals,
303
327
  ...middlewareContext.response.locals
@@ -319,9 +343,12 @@ export class ModernServer {
319
343
  if (route.entryName) {
320
344
  const afterRenderContext = createAfterRenderContext(context, response.toString());
321
345
  if (this.runMode === RUN_MODE.FULL) {
346
+ const end2 = time();
322
347
  await this.runner.afterRender(afterRenderContext, {
323
348
  onLast: noop
324
349
  });
350
+ const cost = end2();
351
+ reporter.reportTiming("server_hook_after_render", cost);
325
352
  }
326
353
  if (this.isSend(res)) {
327
354
  return;
@@ -434,6 +461,7 @@ export class ModernServer {
434
461
  context.res.end(createErrorDocument(status, text));
435
462
  }
436
463
  constructor({ pwd, config, routes, staticGenerate, logger, metrics, runMode, proxyTarget, appContext }) {
464
+ var _appContext;
437
465
  _define_property(this, "pwd", void 0);
438
466
  _define_property(this, "distDir", void 0);
439
467
  _define_property(this, "workDir", void 0);
@@ -448,13 +476,13 @@ export class ModernServer {
448
476
  _define_property(this, "reader", reader);
449
477
  _define_property(this, "proxyTarget", void 0);
450
478
  _define_property(this, "routeRenderHandler", void 0);
479
+ _define_property(this, "staticGenerate", void 0);
480
+ _define_property(this, "metaName", void 0);
451
481
  _define_property(this, "loaderHandler", null);
452
482
  _define_property(this, "frameWebHandler", null);
453
483
  _define_property(this, "frameAPIHandler", null);
454
484
  _define_property(this, "proxyHandler", null);
455
485
  _define_property(this, "_handler", void 0);
456
- _define_property(this, "staticGenerate", void 0);
457
- _define_property(this, "metaName", void 0);
458
486
  require("ignore-styles");
459
487
  this.pwd = pwd;
460
488
  this.distDir = path.resolve(pwd, config.output.path || "dist");
@@ -468,6 +496,6 @@ export class ModernServer {
468
496
  this.proxyTarget = proxyTarget;
469
497
  this.staticGenerate = staticGenerate || false;
470
498
  this.runMode = runMode || RUN_MODE.FULL;
471
- this.metaName = appContext === null || appContext === void 0 ? void 0 : appContext.metaName;
499
+ this.metaName = (_appContext = appContext) === null || _appContext === void 0 ? void 0 : _appContext.metaName;
472
500
  }
473
501
  }
@@ -119,3 +119,33 @@ export const isRedirect = (code) => {
119
119
  308
120
120
  ].includes(code);
121
121
  };
122
+ function parseBodyTypes(headers, body) {
123
+ switch (headers["content-type"]) {
124
+ case "application/json":
125
+ return JSON.parse(body);
126
+ default:
127
+ return body;
128
+ }
129
+ }
130
+ const getRequestBody = (req) => new Promise((resolve, reject) => {
131
+ var _req;
132
+ if (((_req = req) === null || _req === void 0 ? void 0 : _req.method) && req.method.toLowerCase() !== "get") {
133
+ let body = "";
134
+ req.on("data", (chunk) => {
135
+ body += chunk.toString();
136
+ });
137
+ req.on("end", () => {
138
+ resolve(parseBodyTypes(req.headers, body));
139
+ });
140
+ req.on("error", (err) => {
141
+ reject(err);
142
+ });
143
+ } else {
144
+ resolve(void 0);
145
+ }
146
+ });
147
+ export const bodyParser = async (req) => {
148
+ if (!req.body) {
149
+ req.body = await getRequestBody(req);
150
+ }
151
+ };
@@ -4,6 +4,7 @@ import { createAfterMatchContext, createAfterRenderContext, createMiddlewareCont
4
4
  import { Logger } from "./libs/logger";
5
5
  import { RouteMatchManager } from "./libs/route";
6
6
  import { metrics as defaultMetrics } from "./libs/metrics";
7
+ import { defaultReporter } from "./libs/reporter";
7
8
  export class ReturnResponse {
8
9
  /**
9
10
  * Iterate a Object
@@ -69,7 +70,7 @@ export const createHandler = (manifest) => {
69
70
  const { pages, routes } = manifest;
70
71
  routeMgr.reset(routes);
71
72
  return async (options) => {
72
- var _page_serverHooks, _page_serverHooks_afterMatch;
73
+ var _page_serverHooks_afterMatch, _page_serverHooks, _page;
73
74
  const { request, loadableStats, routeManifest } = options;
74
75
  const url = new URL(request.url);
75
76
  const pageMatch = routeMgr.match(url.pathname);
@@ -82,15 +83,16 @@ export const createHandler = (manifest) => {
82
83
  level: "warn"
83
84
  });
84
85
  const metrics = defaultMetrics;
85
- const hookContext = createWorkerHookContext(request.url, logger, metrics);
86
+ const reporter = defaultReporter;
87
+ const hookContext = createWorkerHookContext(request.url, logger, metrics, reporter);
86
88
  const afterMatchHookContext = createAfterMatchContext(hookContext, entryName);
87
- page === null || page === void 0 ? void 0 : (_page_serverHooks = page.serverHooks) === null || _page_serverHooks === void 0 ? void 0 : (_page_serverHooks_afterMatch = _page_serverHooks.afterMatch) === null || _page_serverHooks_afterMatch === void 0 ? void 0 : _page_serverHooks_afterMatch.call(_page_serverHooks, afterMatchHookContext, () => void 0);
89
+ (_page = page) === null || _page === void 0 ? void 0 : (_page_serverHooks = _page.serverHooks) === null || _page_serverHooks === void 0 ? void 0 : (_page_serverHooks_afterMatch = _page_serverHooks.afterMatch) === null || _page_serverHooks_afterMatch === void 0 ? void 0 : _page_serverHooks_afterMatch.call(_page_serverHooks, afterMatchHookContext, () => void 0);
88
90
  if (checkIsSent(hookContext)) {
89
91
  return new ReturnResponse(hookContext.res.body || "Unkown body", hookContext.res.status, hookContext.res.headers);
90
92
  }
91
93
  if (page.serverRender) {
92
94
  try {
93
- var _page_serverHooks1, _page_serverHooks2, _page_serverHooks_afterRender;
95
+ var _page_serverHooks1, _page_serverHooks_afterRender, _page_serverHooks2;
94
96
  const middlewarsHookContext = createMiddlewareContext(hookContext);
95
97
  applyMiddlewares(middlewarsHookContext, (_page_serverHooks1 = page.serverHooks) === null || _page_serverHooks1 === void 0 ? void 0 : _page_serverHooks1.middleware);
96
98
  if (checkIsSent(hookContext)) {
@@ -118,9 +120,15 @@ export const createHandler = (manifest) => {
118
120
  template: page.template,
119
121
  entryName: page.entryName,
120
122
  logger,
123
+ reporter: defaultReporter,
121
124
  metrics,
122
125
  // FIXME: pass correctly req & res
123
126
  req: request,
127
+ serverTiming: {
128
+ addServeTiming() {
129
+ return this;
130
+ }
131
+ },
124
132
  res: responseLike
125
133
  };
126
134
  const body = await page.serverRender(serverRenderContext);
@@ -165,7 +173,7 @@ function createResponse(template) {
165
173
  return RESPONSE_NOTFOUND;
166
174
  }
167
175
  }
168
- function createWorkerHookContext(url, logger, metrics) {
176
+ function createWorkerHookContext(url, logger, metrics, reporter) {
169
177
  const [res, req] = [
170
178
  {
171
179
  headers: new Headers(),
@@ -179,7 +187,8 @@ function createWorkerHookContext(url, logger, metrics) {
179
187
  res,
180
188
  req,
181
189
  logger,
182
- metrics
190
+ metrics,
191
+ reporter
183
192
  };
184
193
  }
185
194
  function applyMiddlewares(ctx, middleware) {
@@ -6,5 +6,6 @@ export { ModernServer } from './server/modernServer';
6
6
  export { createProxyHandler } from './libs/proxy';
7
7
  export * from './type';
8
8
  export * from './constants';
9
+ export { createRenderHandler } from './libs/render';
9
10
  declare const _default: (options: ModernServerOptions) => Promise<Server>;
10
11
  export default _default;
@@ -2,11 +2,12 @@
2
2
  /// <reference types="node" />
3
3
  /// <reference types="node" />
4
4
  /// <reference types="node/http" />
5
- /// <reference types=".dts-temp/kKZBfG7unyISzN2HX-IzS/src/type" />
5
+ /// <reference types=".dts-temp/rFczrZA4GO714tUiIeLuz/src/type" />
6
6
  import { IncomingMessage, ServerResponse } from 'http';
7
7
  import qs from 'querystring';
8
- import type { ModernServerContext as ModernServerContextInterface } from '@modern-js/types';
8
+ import type { ModernServerContext as ModernServerContextInterface, Reporter as ModernServerReporter, ServerTiming as ModernServerTiming } from '@modern-js/types';
9
9
  export type ContextOptions = {
10
+ metaName?: string;
10
11
  etag?: boolean;
11
12
  };
12
13
  type ResponseBody = string | Buffer;
@@ -23,6 +24,8 @@ export declare class ModernServerContext implements ModernServerContextInterface
23
24
  * url params
24
25
  */
25
26
  params: Record<string, string>;
27
+ reporter: ModernServerReporter;
28
+ serverTiming: ModernServerTiming;
26
29
  get logger(): import("@modern-js/types").Logger;
27
30
  get metrics(): import("@modern-js/types").Metrics;
28
31
  serverData: Record<string, any>;
@@ -1,4 +1,4 @@
1
- import { AfterMatchContext, AfterRenderContext, HookContext, Logger, Metrics, MiddlewareContext } from '@modern-js/types/server';
1
+ import { AfterMatchContext, AfterRenderContext, HookContext, Logger, Metrics, MiddlewareContext, Reporter } from '@modern-js/types/server';
2
2
  export interface WorkerResponse {
3
3
  headers: Headers;
4
4
  status: number;
@@ -10,6 +10,7 @@ export interface WorkerServerContext {
10
10
  res: WorkerResponse;
11
11
  req: Request;
12
12
  logger: Logger;
13
+ reporter: Reporter;
13
14
  metrics: Metrics;
14
15
  }
15
16
  export declare const base: (context: WorkerServerContext) => HookContext;
@@ -1,24 +1,19 @@
1
1
  import type { ModernServerContext } from '@modern-js/types';
2
2
  import { RenderResult, ServerHookRunner } from '../../type';
3
3
  import { ModernRoute } from '../route';
4
- export declare const createRenderHandler: ({
5
- distDir,
6
- staticGenerate,
7
- forceCSR,
8
- nonce,
9
- metaName
10
- }: {
11
- distDir: string;
12
- staticGenerate: boolean;
13
- forceCSR?: boolean | undefined;
14
- nonce?: string | undefined;
15
- metaName?: string | undefined;
16
- }) => ({
17
- ctx,
18
- route,
19
- runner
20
- }: {
4
+ import * as ssr from './ssr';
5
+ export type RenderHandler = (options: {
21
6
  ctx: ModernServerContext;
22
7
  route: ModernRoute;
23
8
  runner: ServerHookRunner;
24
- }) => Promise<RenderResult | null>;
9
+ }) => Promise<RenderResult | null>;
10
+ type CreateRenderHandler = (ctx: {
11
+ distDir: string;
12
+ staticGenerate: boolean;
13
+ ssrRender?: typeof ssr.render;
14
+ forceCSR?: boolean;
15
+ nonce?: string;
16
+ metaName?: string;
17
+ }) => RenderHandler;
18
+ export declare const createRenderHandler: CreateRenderHandler;
19
+ export {};
@@ -0,0 +1,2 @@
1
+ import { Reporter } from '@modern-js/types/server';
2
+ export declare const defaultReporter: Reporter;
@@ -0,0 +1,12 @@
1
+ import { ServerTiming as IServerTiming } from '@modern-js/types';
2
+ interface Res {
3
+ getHeader: (name: string) => number | string | string[] | undefined;
4
+ setHeader: (name: string, value: string) => void;
5
+ }
6
+ export declare class ServerTiming implements IServerTiming {
7
+ meta: string;
8
+ res: Res;
9
+ constructor(res: Res, meta: string);
10
+ addServeTiming(name: string, dur: number, desc?: string): this;
11
+ }
12
+ export {};
@@ -2,10 +2,11 @@
2
2
  /// <reference types="node" />
3
3
  import { IncomingMessage, ServerResponse, Server } from 'http';
4
4
  import { Adapter, WebAdapter, APIServerStartInput, ServerOptions } from '@modern-js/server-core';
5
- import type { ModernServerContext, ServerRoute } from '@modern-js/types';
5
+ import { type ModernServerContext, type ServerRoute } from '@modern-js/types';
6
6
  import type { ContextOptions } from '../libs/context';
7
7
  import { ModernServerOptions, NextFunction, ServerHookRunner, Metrics, Logger, ModernServerInterface, BuildOptions, ModernServerHandler } from '../type';
8
8
  import { RouteMatchManager, ModernRouteInterface, ModernRoute } from '../libs/route';
9
+ import { RenderHandler } from '../libs/render';
9
10
  import { mergeExtension } from '../utils';
10
11
  import * as reader from '../libs/render/reader';
11
12
  type ModernServerAsyncHandler = (context: ModernServerContext, next: NextFunction) => Promise<void>;
@@ -23,14 +24,14 @@ export declare class ModernServer implements ModernServerInterface {
23
24
  protected readonly runMode: string;
24
25
  protected reader: typeof reader;
25
26
  protected readonly proxyTarget: ModernServerOptions['proxyTarget'];
26
- private routeRenderHandler;
27
+ protected routeRenderHandler: RenderHandler;
28
+ protected readonly staticGenerate: boolean;
29
+ protected readonly metaName?: string;
27
30
  private loaderHandler;
28
31
  private frameWebHandler;
29
32
  private frameAPIHandler;
30
33
  private proxyHandler;
31
34
  private _handler;
32
- private readonly staticGenerate;
33
- private readonly metaName?;
34
35
  constructor({
35
36
  pwd,
36
37
  config,
@@ -43,6 +44,7 @@ export declare class ModernServer implements ModernServerInterface {
43
44
  appContext
44
45
  }: ModernServerOptions);
45
46
  onInit(runner: ServerHookRunner, app: Server): Promise<void>;
47
+ getRenderHandler(): RenderHandler;
46
48
  onRepack(_: BuildOptions): void;
47
49
  getRequestHandler(): (req: IncomingMessage, res: ServerResponse, next?: () => void) => void | ServerResponse;
48
50
  render(req: IncomingMessage, res: ServerResponse, url?: string): Promise<string | import("stream").Readable | null>;
@@ -11,6 +11,7 @@ declare module 'http' {
11
11
  interface IncomingMessage {
12
12
  logger: Logger;
13
13
  metrics: Metrics;
14
+ body?: any;
14
15
  }
15
16
  }
16
17
  export type ModernServerOptions = {
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node/http" />
3
- /// <reference types=".dts-temp/kKZBfG7unyISzN2HX-IzS/src/type" />
3
+ /// <reference types=".dts-temp/rFczrZA4GO714tUiIeLuz/src/type" />
4
4
  import { IncomingMessage } from 'http';
5
5
  import type { OutputNormalizedConfig, HtmlNormalizedConfig } from '@modern-js/server-core';
6
6
  export declare const debug: any;
@@ -21,4 +21,5 @@ export declare const createMiddlewareCollecter: () => {
21
21
  export declare const getStaticReg: (output?: OutputNormalizedConfig, html?: HtmlNormalizedConfig, prefix?: string) => RegExp;
22
22
  export declare const prepareFavicons: (favicon: string | undefined, faviconByEntries?: Record<string, string | undefined>) => string[];
23
23
  export declare const headersWithoutCookie: (headers: IncomingMessage['headers']) => import("http").IncomingHttpHeaders;
24
- export declare const isRedirect: (code: number) => boolean;
24
+ export declare const isRedirect: (code: number) => boolean;
25
+ export declare const bodyParser: (req: IncomingMessage) => Promise<void>;