Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP refactor: make constructors as functions to reduce bundle size #3666

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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 }))
}

/**
Expand Down Expand Up @@ -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,
})
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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) => {
Expand All @@ -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,
})
Expand All @@ -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) {
Expand All @@ -683,7 +684,7 @@ export class Context<
}
}

return new Response(data, {
return newResponse(data, {
status,
headers: this.#headers,
})
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -824,7 +826,7 @@ export class Context<
location: string | URL,
status?: T
): Response & TypedResponse<undefined, T, 'redirect'> => {
this.#headers ??= new Headers()
this.#headers ??= newHeaders()
this.#headers.set('Location', String(location))
return this.newResponse(null, status ?? 302) as any
}
Expand All @@ -842,7 +844,7 @@ export class Context<
* ```
*/
notFound = (): Response | Promise<Response> => {
this.#notFoundHandler ??= () => new Response()
this.#notFoundHandler ??= () => newResponse()
return this.#notFoundHandler(this)
}
}
9 changes: 5 additions & 4 deletions src/hono-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type {
RouterRoute,
Schema,
} from './types'
import { newResponse, newRequest } from './utils/constructors'
import { getPath, getPathNoStrict, mergePath } from './utils/url'

/**
Expand Down Expand Up @@ -356,7 +357,7 @@ class Hono<E extends Env = Env, S extends Schema = {}, BasePath extends string =
return (request) => {
const url = new URL(request.url)
url.pathname = url.pathname.slice(pathPrefixLength) || '/'
return new Request(url, request)
return newRequest(url, request)
}
})()

Expand Down Expand Up @@ -397,7 +398,7 @@ class Hono<E extends Env = Env, S extends Schema = {}, BasePath extends string =
// Handle HEAD method
if (method === 'HEAD') {
return (async () =>
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 })
Expand Down Expand Up @@ -488,11 +489,11 @@ class Hono<E extends Env = Env, S extends Schema = {}, BasePath extends string =
executionCtx?: ExecutionContext
): Response | Promise<Response> => {
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
),
Expand Down
3 changes: 2 additions & 1 deletion src/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -222,7 +223,7 @@ export class HonoRequest<P extends string = '/', I extends Input['out'] = {}> {
if (anyCachedKey === 'json') {
body = JSON.stringify(body)
}
return new Response(body)[key]()
return newResponse(body)[key]()
})
}

Expand Down
11 changes: 11 additions & 0 deletions src/utils/constructors.ts
Original file line number Diff line number Diff line change
@@ -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)
}
Loading