From 48cfafe412579eacc040c8188cb492765e5d6184 Mon Sep 17 00:00:00 2001 From: Okiki Ojo Date: Mon, 26 Jan 2026 04:30:51 -0500 Subject: [PATCH] perf: improve memory usage on deno deploy Signed-off-by: Okiki Ojo --- core/build.ts | 35 +++++++++++++++++++---------------- core/configs/platform.ts | 4 ++-- core/context.ts | 10 ++++++---- core/init.ts | 5 ++++- core/utils/filesystem.ts | 32 ++++++++++++++++++++++---------- utils/fetch-and-cache.ts | 2 +- 6 files changed, 54 insertions(+), 34 deletions(-) diff --git a/core/build.ts b/core/build.ts index b2fc515..8e41d71 100644 --- a/core/build.ts +++ b/core/build.ts @@ -162,17 +162,22 @@ export async function build(opts: BuildConfig = {}, filesystem: Promise(); try { - const { define = {}, ...esbuild_opts } = LocalConfig.esbuild ?? {}; + const esbuild_opts = LocalConfig.esbuild ?? {}; let outputs: ESBUILD.OutputFile[] = []; let contents: ESBUILD.OutputFile[] = []; - if (build_result.warnings?.length > 0) { + if (_ctx.warnings?.length > 0) { // Log errors with added color info. to the virtual console - const ansiMsgs = await createNotice(build_result.warnings, "warning", false) ?? []; + const ansiMsgs = await createNotice(_ctx.warnings, "warning", false) ?? []; dispatchEvent(LOGGER_WARN, ansiMsgs.join("\n")); const message = `${ansiMsgs.length} warning(s) `; @@ -181,8 +186,8 @@ export async function formatBuildResult(_ctx: BuildResultContext) { // Create an array of assets and actual output files, this will later be used to calculate total file size outputs = await Promise.all( - Array.from(StateContext.target.assets ?? []) - .concat(build_result?.outputFiles as ESBUILD.OutputFile[]) + Array.from(assets ?? []) + .concat(_ctx?.outputFiles as ESBUILD.OutputFile[]) ); contents = await Promise.all( @@ -214,12 +219,8 @@ export async function formatBuildResult(_ctx: BuildResultContext) { ); // Ensure a fresh filesystem on every run - // FileSystem.clear(); + await fs?.clear?.(); // console.log({ contentsLen: contents.length }) - - const packageManifests = - fromContext('packageManifests', StateContext) - ?? new Map(); const packageSizeArr: [string, string][] = []; let totalInstallSize = 0; @@ -233,7 +234,7 @@ export async function formatBuildResult(_ctx: BuildResultContext) { } return { - state: StateContext.target, + // state: StateContext.target, config: LocalConfig, /** @@ -246,12 +247,14 @@ export async function formatBuildResult(_ctx: BuildResultContext) { */ outputs, - files: (await StateContext.target.filesystem?.files()) || null, - packageSizeArr, totalInstallSize: bytes.format(totalInstallSize), - ...build_result, + errors: _ctx.errors, + mangleCache: _ctx.mangleCache, + metafile: _ctx.metafile, + outputFiles: _ctx.outputFiles, + warnings: _ctx.warnings, }; } catch (e) { const err = e as Error; diff --git a/core/configs/platform.ts b/core/configs/platform.ts index bfbe9dd..2cb69a7 100644 --- a/core/configs/platform.ts +++ b/core/configs/platform.ts @@ -1,7 +1,7 @@ /** * `@bundle/core`'s supported platforms */ -export type Platform = "node" | "deno" | "browser" | "edge" | "cloudflare" | "wasm" | "deno-wasm" | "builtin"; +export type Platform = "node" | "deno" | "browser" | "edge" | "cloudflare" | "wasm" | "deno-wasm"; /** * Automatically chooses the esbuild version to run based off platform heuristics, @@ -11,4 +11,4 @@ export type Platform = "node" | "deno" | "browser" | "edge" | "cloudflare" | "wa * - Otherwise the environment is the browser * */ -export const PLATFORM_AUTO: Platform = ("Deno" in globalThis) ? "deno" : ("process" in globalThis) ? "node" : "browser"; \ No newline at end of file +export const PLATFORM_AUTO: Platform = ("Deno" in globalThis) ? "deno-wasm" : ("process" in globalThis) ? "node" : "browser"; \ No newline at end of file diff --git a/core/context.ts b/core/context.ts index 3448816..e7b9650 100644 --- a/core/context.ts +++ b/core/context.ts @@ -124,10 +124,12 @@ export async function rebuild(ctx: BuildContext): Promise { try { try { // Clear the assets, failedExtensionChecks, and failedManifestUrls - StateContext.target.assets.length = 0; - StateContext.target.failedExtensionChecks.clear(); - StateContext.target.failedManifestUrls.clear(); - // StateContext.target.packageManifests.clear(); + ctx.state.target.assets.length = 0; + ctx.state.target.failedExtensionChecks.clear(); + ctx.state.target.failedManifestUrls.clear(); + ctx.state.target.sideEffectsMatchersCache.clear(); + ctx.state.target.filesystem?.clear?.(); + // ctx.state.target.packageManifests.clear(); build_result = await ctx.rebuild(); } catch (e) { diff --git a/core/init.ts b/core/init.ts index bc275a9..1423d11 100644 --- a/core/init.ts +++ b/core/init.ts @@ -19,7 +19,6 @@ export async function init(opts: Partial | null = {}, opts ??= {}; try { if (!fromContext("initialized")) { - toContext("initialized", true); dispatchEvent(INIT_START); const version = await getEsbuildVersion(_version); @@ -46,6 +45,7 @@ export async function init(opts: Partial | null = {}, } dispatchEvent(INIT_COMPLETE); + toContext("initialized", true); } return fromContext("esbuild"); @@ -53,5 +53,8 @@ export async function init(opts: Partial | null = {}, const error = e as Error | unknown; dispatchEvent(INIT_ERROR, error as Error); console.error(error); + + toContext("initialized", false); + toContext("esbuild", null); } } \ No newline at end of file diff --git a/core/utils/filesystem.ts b/core/utils/filesystem.ts index 5fced3a..80c7216 100644 --- a/core/utils/filesystem.ts +++ b/core/utils/filesystem.ts @@ -45,6 +45,14 @@ export interface IFileSystem { * @returns promise indicating delete was successful */ delete: (path: string) => Promise, + + + /** + * Clears all files and directories at specific paths in the virtual file system storage + * + * @returns promise indicating clear was successful + */ + clear?: () => Promise, } export function isValid(file: unknown) { @@ -179,32 +187,36 @@ export async function deleteFile>(fs: F, path: strin /** Virtual Filesystem Storage */ export function createDefaultFileSystem(FileSystem = new Map()) { const fs: IFileSystem = { - files: async () => await FileSystem as unknown as Map, - get: async (path: string) => await FileSystem.get(resolve(path)), - async set(path: string, content?: Content | null) { + files: () => Promise.resolve(FileSystem as unknown as Map), + get: (path: string) => Promise.resolve(FileSystem.get(resolve(path))), + set(path: string, content?: Content | null) { const resolvedPath = resolve(path); const dir = dirname(resolvedPath); const parentDirs = dir.split(posix.SEPARATOR).filter(x => x.length > 0); const len = parentDirs.length; - await FileSystem.set("/", null); + FileSystem.set("/", null); // Generate all the subdirectories in b/w let accPath = parentDirs[0] !== posix.SEPARATOR ? "/" : ""; for (let i = 0; i < len; i++) { accPath += parentDirs[i]; - if (!await FileSystem.has(accPath)) - await FileSystem.set(accPath, null); + if (!FileSystem.has(accPath)) + FileSystem.set(accPath, null); accPath += "/"; } FileSystem.set(resolvedPath, content); + return Promise.resolve(); + }, + has(path: string) { + return Promise.resolve(FileSystem.has(path)); }, - async has(path: string) { - return await FileSystem.has(path); + delete(path: string) { + return Promise.resolve(FileSystem.delete(resolve(path))) }, - async delete(path: string) { - return await FileSystem.delete(resolve(path)) + clear() { + return Promise.resolve(FileSystem.clear()); } }; diff --git a/utils/fetch-and-cache.ts b/utils/fetch-and-cache.ts index c79c812..c238e95 100644 --- a/utils/fetch-and-cache.ts +++ b/utils/fetch-and-cache.ts @@ -292,7 +292,7 @@ export async function fetchWithCache( // Stale-while-revalidate: return cached, refresh in background if (cacheMode === 'normal') { - backgroundRefresh(url, finalUrl, init, retries, cacheApi); + await backgroundRefresh(url, finalUrl, init, retries, cacheApi); } return { -- 2.54.0