diff --git a/src/core/utils/fs-tree.ts b/src/core/utils/fs-tree.ts index 9941115b8c..3cb9e2495c 100644 --- a/src/core/utils/fs-tree.ts +++ b/src/core/utils/fs-tree.ts @@ -31,7 +31,10 @@ export async function generateFSTree( const path = resolve(dir, file); const src = await fsp.readFile(path); const size = src.byteLength; - const gzip = options.compressedSizes ? await gzipSize(src) : 0; + const gzip = + options.compressedSizes && !file.includes("node_modules") + ? await gzipSize(src) + : 0; items.push({ file, path, size, gzip }); }, { concurrency: 10 } @@ -43,7 +46,6 @@ export async function generateFSTree( let totalGzip = 0; let totalNodeModulesSize = 0; - let totalNodeModulesGzip = 0; let treeText = ""; @@ -59,7 +61,6 @@ export async function generateFSTree( if (isNodeModules) { totalNodeModulesSize += item.size; - totalNodeModulesGzip += item.gzip; continue; } @@ -78,7 +79,7 @@ export async function generateFSTree( totalSize + totalNodeModulesSize )}`; if (options.compressedSizes) { - treeText += ` (${prettyBytes(totalGzip + totalNodeModulesGzip)} gzip)`; + treeText += ` (${prettyBytes(totalGzip)} gzip${totalNodeModulesSize ? ", excluding node_modules" : ""})`; } treeText += "\n"; diff --git a/test/unit/fs-tree.test.ts b/test/unit/fs-tree.test.ts new file mode 100644 index 0000000000..339ca30005 --- /dev/null +++ b/test/unit/fs-tree.test.ts @@ -0,0 +1,57 @@ +import { mkdir, mkdtemp, realpath, rm, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { stripVTControlCharacters } from "node:util"; +import { join } from "pathe"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { generateFSTree } from "../../src/core/utils/fs-tree"; + +// generateFSTree prints nothing under test +vi.mock("std-env", async (importOriginal) => ({ + ...(await importOriginal()), + isTest: false, +})); + +const { gzipSize } = vi.hoisted(() => ({ + gzipSize: vi.fn(async (input: Uint8Array) => input.byteLength / 2), +})); +vi.mock("gzip-size", () => ({ gzipSize })); + +describe("generateFSTree", () => { + let dir: string; + + beforeEach(async () => { + gzipSize.mockClear(); + dir = await realpath(await mkdtemp(join(tmpdir(), "nitro-fs-tree-"))); + await writeFile(join(dir, "index.mjs"), "a".repeat(1000)); + }); + + afterEach(async () => { + await rm(dir, { recursive: true, force: true }); + }); + + async function tree() { + return stripVTControlCharacters( + (await generateFSTree(dir, { compressedSizes: true })) || "" + ); + } + + it("reports gzip sizes of the listed files", async () => { + const text = await tree(); + + expect(text).toContain("index.mjs (1 kB) (500 B gzip)"); + expect(text).toContain("Σ Total size: 1 kB (500 B gzip)\n"); + }); + + it("does not gzip node_modules files", async () => { + await mkdir(join(dir, "node_modules/dep"), { recursive: true }); + await writeFile(join(dir, "node_modules/dep/index.js"), "b".repeat(3000)); + + const text = await tree(); + + expect(gzipSize).toHaveBeenCalledTimes(1); + expect(text).not.toContain("node_modules/dep"); + expect(text).toContain( + "Σ Total size: 4 kB (500 B gzip, excluding node_modules)\n" + ); + }); +});