From 656ed058b2bbd3f5ca5ae5aa48bea9b0d2122568 Mon Sep 17 00:00:00 2001 From: SukkaW Date: Sun, 13 Aug 2023 01:55:05 +0800 Subject: [PATCH] realpath performance improvements + error handling --- src/workspace/node-module.ts | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/workspace/node-module.ts b/src/workspace/node-module.ts index 436e71f..8029f90 100644 --- a/src/workspace/node-module.ts +++ b/src/workspace/node-module.ts @@ -7,6 +7,13 @@ import Workspace from './workspace'; import semverMaxSatisfying from 'semver/ranges/max-satisfying'; import semver from 'semver'; +// fs.realpathSync is 70x slower than fs.realpathSync.native: +// https://github.com/nodejs/node/issues/2680 +// However, `fs.realpathSync.native` resolves differently in +// Windows network drive, causing file read errors +const fsRealpathSync = + process.platform === 'win32' ? fs.realpathSync : fs.realpathSync.native; + export type RemoteData = { time: Record; versions: Array; @@ -21,6 +28,7 @@ export default class NodeModule { _remoteData: RemoteData | null; _packageJson: PackageJson | null; _stats: Stats | null; + _realpath: string | null; _yarnRequiredBy: Set | null; _symlink: string | null; @@ -40,6 +48,7 @@ export default class NodeModule { this.parent = parent; this.workspace = workspace; this._stats = null; + this._realpath = null; this._remoteData = null; this._packageJson = null; this._yarnRequiredBy = null; @@ -75,7 +84,21 @@ export default class NodeModule { } get realpath() { - return fs.realpathSync(path.join(this.nodeModulesPath, this.name)); + if (!this._realpath) { + try { + this._realpath = fsRealpathSync(this.path); + } catch (e: any) { + // When using npm "overwrites" with "@favware/skip-dependency", there could be modules + // that have symlinks to non-existing paths, causing an ENOENT error. Falling back to + // the path when this happen. + if ('code' in e && e.code === 'ENOENT') { + this._realpath = this.path; + } + throw e; + } + } + + return this._realpath; } get stats() {