diff --git a/packages/server/prod-server/src/libs/context/context.ts b/packages/server/prod-server/src/libs/context/context.ts index c4521a196e7e..53d96217e595 100644 --- a/packages/server/prod-server/src/libs/context/context.ts +++ b/packages/server/prod-server/src/libs/context/context.ts @@ -1,6 +1,6 @@ import { IncomingMessage, ServerResponse } from 'http'; import { URL } from 'url'; -import qs from 'querystring'; +import qs, { ParsedUrlQuery } from 'querystring'; import { Buffer } from 'buffer'; import type { ModernServerContext as ModernServerContextInterface, @@ -55,6 +55,10 @@ export class ModernServerContext implements ModernServerContextInterface { private options: ContextOptions = {}; + #urls: Map; + + #queries: Map; + constructor( req: IncomingMessage, res: ServerResponse, @@ -64,6 +68,8 @@ export class ModernServerContext implements ModernServerContextInterface { this.res = res; this.options = options || {}; this.bind(); + this.#urls = new Map(); + this.#queries = new Map(); this.serverTiming = new ServerTiming( this.res, cutNameByHyphen(options?.metaName || 'modern-js'), @@ -72,8 +78,13 @@ export class ModernServerContext implements ModernServerContextInterface { private get parsedURL() { try { - // only for parse url, use mock - return new URL(this.req.url!, MOCK_URL_BASE); + let url = this.#urls.get(this.req.url!); + if (!url) { + // only for parse url, use mock + url = new URL(this.req.url!, MOCK_URL_BASE); + this.#urls.set(this.req.url!, url); + } + return url; } catch (e) { this.logger.error( 'Parse URL error', @@ -180,10 +191,12 @@ export class ModernServerContext implements ModernServerContextInterface { if (!host) { host = this.getReqHeader('Host'); } + + host = (host as string).split(/\s*,\s*/, 1)[0] || 'undefined'; // the host = '',if we can't cat Host or X-Forwarded-Host header // but the this.href would assign a invalid value:`http[s]://${pathname}` // so we need assign host a no-empty value. - return (host as string).split(/\s*,\s*/, 1)[0] || 'undefined'; + return host; } public get protocol() { @@ -229,7 +242,12 @@ export class ModernServerContext implements ModernServerContextInterface { public get query() { const str = this.querystring; - return qs.parse(str); + let query = this.#queries.get(str); + if (!query) { + query = qs.parse(str); + this.#queries.set(str, query); + } + return query; } /* response property */ diff --git a/packages/server/prod-server/src/server/modernServer.ts b/packages/server/prod-server/src/server/modernServer.ts index 179b4869ff55..f6967f45f0eb 100644 --- a/packages/server/prod-server/src/server/modernServer.ts +++ b/packages/server/prod-server/src/server/modernServer.ts @@ -535,23 +535,21 @@ export class ModernServer implements ModernServerInterface { return; } - if (route.entryName) { + if (route.entryName && this.runMode === RUN_MODE.FULL) { const afterMatchContext = createAfterMatchContext( context, route.entryName, ); - // only full mode run server hook - if (this.runMode === RUN_MODE.FULL) { - const end = time(); - await this.runner.afterMatch(afterMatchContext, { onLast: noop }); - const cost = end(); - cost && - reporter.reportTiming( - ServerReportTimings.SERVER_HOOK_AFTER_MATCH, - cost, - ); - } + const end = time(); + + await this.runner.afterMatch(afterMatchContext, { onLast: noop }); + const cost = end(); + cost && + reporter.reportTiming( + ServerReportTimings.SERVER_HOOK_AFTER_MATCH, + cost, + ); if (this.isSend(res)) { return; @@ -607,7 +605,7 @@ export class ModernServer implements ModernServerInterface { return; } - if (route.entryName) { + if (route.entryName && this.runMode === RUN_MODE.FULL) { const afterRenderContext = createAfterRenderContext( context, response.toString(), @@ -615,17 +613,15 @@ export class ModernServer implements ModernServerInterface { // only full mode run server hook // FIXME: how to run server hook in streaming - if (this.runMode === RUN_MODE.FULL) { - const end = time(); - await this.runner.afterRender(afterRenderContext, { onLast: noop }); - const cost = end(); - // we shouldn't reporter unable run after-render. - cost && - reporter.reportTiming( - ServerReportTimings.SERVER_HOOK_AFTER_RENDER, - cost, - ); - } + const end = time(); + await this.runner.afterRender(afterRenderContext, { onLast: noop }); + const cost = end(); + // we shouldn't reporter unable run after-render. + cost && + reporter.reportTiming( + ServerReportTimings.SERVER_HOOK_AFTER_RENDER, + cost, + ); if (this.isSend(res)) { return;