From 40ac8ce5418e9e24d66f5ef199be6f3429e08010 Mon Sep 17 00:00:00 2001 From: Yusuke Wada Date: Thu, 14 Nov 2024 05:02:26 +0900 Subject: [PATCH 1/2] refactor: make constructors as functions to reduce bundle size --- src/context.ts | 24 +++++++++++++----------- src/hono-base.ts | 9 +++++---- src/request.ts | 3 ++- src/utils/constructors.ts | 11 +++++++++++ 4 files changed, 31 insertions(+), 16 deletions(-) create mode 100644 src/utils/constructors.ts diff --git a/src/context.ts b/src/context.ts index 86124e008a..60ff3b053b 100644 --- a/src/context.ts +++ b/src/context.ts @@ -9,6 +9,7 @@ import type { RouterRoute, TypedResponse, } from './types' +import { newHeaders, newResponse } from './utils/constructors' import type { ResponseHeader } from './utils/headers' import { HtmlEscapedCallbackPhase, resolveCallback } from './utils/html' import type { RedirectStatusCode, StatusCode } from './utils/http-status' @@ -386,7 +387,7 @@ export class Context< */ get res(): Response { this.#isFresh = false - return (this.#res ||= new Response('404 Not Found', { status: 404 })) + return (this.#res ||= newResponse('404 Not Found', { status: 404 })) } /** @@ -415,7 +416,7 @@ export class Context< } catch (e) { if (e instanceof TypeError && e.message.includes('immutable')) { // `_res` is immutable (probably a response from a fetch API), so retry with a new response. - this.res = new Response(_res.body, { + this.res = newResponse(_res.body, { headers: _res.headers, status: _res.status, }) @@ -525,7 +526,7 @@ export class Context< if (options?.append) { if (!this.#headers) { this.#isFresh = false - this.#headers = new Headers(this.#preparedHeaders) + this.#headers = newHeaders(this.#preparedHeaders) this.#preparedHeaders = {} } this.#headers.append(name, value) @@ -630,13 +631,13 @@ export class Context< ): Response { // Optimized if (this.#isFresh && !headers && !arg && this.#status === 200) { - return new Response(data, { + return newResponse(data, { headers: this.#preparedHeaders, }) } if (arg && typeof arg !== 'number') { - const header = new Headers(arg.headers) + const header = newHeaders(arg.headers) if (this.#headers) { // If the header is set by c.header() and arg.headers, c.header() will be prioritized. this.#headers.forEach((v, k) => { @@ -648,7 +649,7 @@ export class Context< }) } const headers = setHeaders(header, this.#preparedHeaders) - return new Response(data, { + return newResponse(data, { headers, status: arg.status ?? this.#status, }) @@ -657,7 +658,7 @@ export class Context< const status = typeof arg === 'number' ? arg : this.#status this.#preparedHeaders ??= {} - this.#headers ??= new Headers() + this.#headers ??= newHeaders() setHeaders(this.#headers, this.#preparedHeaders) if (this.#res) { @@ -683,7 +684,7 @@ export class Context< } } - return new Response(data, { + return newResponse(data, { status, headers: this.#headers, }) @@ -744,11 +745,12 @@ export class Context< if (!this.#preparedHeaders) { if (this.#isFresh && !headers && !arg) { // @ts-expect-error `Response` due to missing some types-only keys - return new Response(text) + return newResponse(text) } this.#preparedHeaders = {} } this.#preparedHeaders['content-type'] = TEXT_PLAIN + // @ts-expect-error `Response` due to missing some types-only keys return typeof arg === 'number' ? this.#newResponse(text, arg, headers) @@ -824,7 +826,7 @@ export class Context< location: string | URL, status?: T ): Response & TypedResponse => { - this.#headers ??= new Headers() + this.#headers ??= newHeaders() this.#headers.set('Location', String(location)) return this.newResponse(null, status ?? 302) as any } @@ -842,7 +844,7 @@ export class Context< * ``` */ notFound = (): Response | Promise => { - this.#notFoundHandler ??= () => new Response() + this.#notFoundHandler ??= () => newResponse() return this.#notFoundHandler(this) } } diff --git a/src/hono-base.ts b/src/hono-base.ts index df782b97aa..8b4a636250 100644 --- a/src/hono-base.ts +++ b/src/hono-base.ts @@ -26,6 +26,7 @@ import type { RouterRoute, Schema, } from './types' +import { newResponse, newRequest } from './utils/constructors' import { getPath, getPathNoStrict, mergePath } from './utils/url' /** @@ -355,7 +356,7 @@ class Hono { const url = new URL(request.url) url.pathname = url.pathname.slice(pathPrefixLength) || '/' - return new Request(url, request) + return newRequest(url, request) } })() @@ -396,7 +397,7 @@ class Hono - new Response(null, await this.#dispatch(request, executionCtx, env, 'GET')))() + newResponse(null, await this.#dispatch(request, executionCtx, env, 'GET')))() } const path = this.getPath(request, { env }) @@ -487,11 +488,11 @@ class Hono => { if (input instanceof Request) { - return this.fetch(requestInit ? new Request(input, requestInit) : input, Env, executionCtx) + return this.fetch(requestInit ? newRequest(input, requestInit) : input, Env, executionCtx) } input = input.toString() return this.fetch( - new Request( + newRequest( /^https?:\/\//.test(input) ? input : `http://localhost${mergePath('/', input)}`, requestInit ), diff --git a/src/request.ts b/src/request.ts index 68c710c359..961c032324 100644 --- a/src/request.ts +++ b/src/request.ts @@ -11,6 +11,7 @@ import type { } from './types' import { parseBody } from './utils/body' import type { BodyData, ParseBodyOptions } from './utils/body' +import { newResponse } from './utils/constructors' import type { CustomHeader, RequestHeader } from './utils/headers' import type { Simplify, UnionToIntersection } from './utils/types' import { decodeURIComponent_, getQueryParam, getQueryParams, tryDecode } from './utils/url' @@ -222,7 +223,7 @@ export class HonoRequest

{ if (anyCachedKey === 'json') { body = JSON.stringify(body) } - return new Response(body)[key]() + return newResponse(body)[key]() }) } diff --git a/src/utils/constructors.ts b/src/utils/constructors.ts new file mode 100644 index 0000000000..e025efc932 --- /dev/null +++ b/src/utils/constructors.ts @@ -0,0 +1,11 @@ +export const newRequest = (input: RequestInfo | URL, init?: RequestInit): Request => { + return new Request(input, init) +} + +export const newResponse = (body?: BodyInit | null, init?: ResponseInit): Response => { + return new Response(body, init) +} + +export const newHeaders = (init?: HeadersInit): Headers => { + return new Headers(init) +} From 51d20400440fde0ac5f74a5b320afcb857496710 Mon Sep 17 00:00:00 2001 From: Yusuke Wada Date: Tue, 19 Nov 2024 13:42:59 +0900 Subject: [PATCH 2/2] empty commit