From d175aea2107605147f9f573ddfde1f5a8bbf0baa Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Mon, 10 Jul 2023 19:51:42 +0200 Subject: [PATCH] perf: Refactor recursiveReadDirSync (#52517) - Use `opendirSync` instead of `readdirSync` - Use `.slice` instead of `.replace` as the rootDir Before (1.54ms): ![CleanShot 2023-07-10 at 18 33 23@2x](https://github.com/vercel/next.js/assets/3676859/829e0a49-35da-4754-bc3f-6fe243e815f4) With the change (0.88ms): ![CleanShot 2023-07-10 at 18 47 43@2x](https://github.com/vercel/next.js/assets/3676859/cabe1fdd-5861-49ba-8c8d-b505c16fbf7a) This scales when public/ folder grows. --- .../src/server/lib/recursive-readdir-sync.ts | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/next/src/server/lib/recursive-readdir-sync.ts b/packages/next/src/server/lib/recursive-readdir-sync.ts index aadcf75dd18cf..07549a88bbc36 100644 --- a/packages/next/src/server/lib/recursive-readdir-sync.ts +++ b/packages/next/src/server/lib/recursive-readdir-sync.ts @@ -1,5 +1,5 @@ import fs from 'fs' -import { join } from 'path' +import { sep } from 'path' /** * Recursively read directory @@ -10,20 +10,22 @@ export function recursiveReadDirSync( dir: string, /** This doesn't have to be provided, it's used for the recursion */ arr: string[] = [], - /** Used to replace the initial path, only the relative path is left, it's faster than path.relative. */ - rootDir = dir + /** Used to remove the initial path suffix and leave only the relative, faster than path.relative. */ + rootDirLength = dir.length ): string[] { - const result = fs.readdirSync(dir, { withFileTypes: true }) - - result.forEach((part) => { - const absolutePath = join(dir, part.name) + // Use opendirSync for better memory usage + const result = fs.opendirSync(dir) + let part: fs.Dirent | null + while ((part = result.readSync())) { + const absolutePath = dir + sep + part.name if (part.isDirectory()) { - recursiveReadDirSync(absolutePath, arr, rootDir) - return + recursiveReadDirSync(absolutePath, arr, rootDirLength) + } else { + arr.push(absolutePath.slice(rootDirLength)) } - arr.push(absolutePath.replace(rootDir, '')) - }) + } + result.closeSync() return arr }