diff --git a/src/services/cache/cacheFile.ts b/src/services/cache/cacheFile.ts index 046449546..909e7dbb5 100644 --- a/src/services/cache/cacheFile.ts +++ b/src/services/cache/cacheFile.ts @@ -151,10 +151,10 @@ class CacheFile { return true; } - addFileDep({filename, content}: {filename: string; content: string}) { - const contentHash = CacheService.getHash(content); + addFileDep({filename, content}: {filename: string; content: string | Uint8Array}) { + if (this.data.fileDeps[filename]) return; - this.data.fileDeps[filename] = contentHash; + this.data.fileDeps[filename] = CacheService.getHash(content); } addFileExists({filename, state}: {filename: string; state: boolean}) { diff --git a/src/utils/pluginEnvApi.ts b/src/utils/pluginEnvApi.ts index a5d271d42..692e32dab 100644 --- a/src/utils/pluginEnvApi.ts +++ b/src/utils/pluginEnvApi.ts @@ -26,11 +26,15 @@ class PluginEnvApi { return new PluginEnvApi(props); } - readonly root: string; - readonly distRoot: string; - cacheFile: CacheFile | undefined; + public readonly root: string; + public readonly distRoot: string; + public readonly cacheFile: CacheFile | undefined; - private asyncActionQueue: AsyncAction[] = []; + private readonly fileExistsCache = new Map(); + private readonly readFileCache = new Map(); + private readonly mkdirCache = new Set(); + + private readonly asyncActionQueue: AsyncAction[] = []; constructor({root, distRoot, cacheFile}: PluginEnvApiProps) { this.root = root; @@ -45,7 +49,7 @@ class PluginEnvApi { const fullFrom = path.join(this.root, from); const fullTo = path.join(this.distRoot, to); - fs.mkdirSync(path.dirname(fullTo), {recursive: true}); + this.cacheMkdir(path.dirname(fullTo)); fs.copyFileSync(fullFrom, fullTo); if (this.cacheFile) { this.cacheFile.addCopyFile({from, to}); @@ -59,11 +63,11 @@ class PluginEnvApi { this.asyncActionQueue.push({type: AsyncActionType.Copy, from, to}); } - readFile(rawTarget: string, encoding: T) { + readFile(rawTarget: string, encoding: T | null = null) { const target = safeRelativePath(rawTarget); const fullTarget = path.join(this.root, target); - const result = fs.readFileSync(fullTarget, encoding); + const result = this.cacheReadFileSync(fullTarget, encoding); if (this.cacheFile) { this.cacheFile.addFileDep({filename: target, content: result}); } @@ -74,7 +78,7 @@ class PluginEnvApi { const target = safeRelativePath(rawTarget); const fullTarget = path.join(this.root, target); - const result = fs.existsSync(fullTarget); + const result = this.cacheExistsSync(fullTarget); if (this.cacheFile) { this.cacheFile.addFileExists({filename: target, state: result}); } @@ -85,7 +89,7 @@ class PluginEnvApi { const to = safeRelativePath(rawTo); const fullTo = path.join(this.distRoot, to); - fs.mkdirSync(path.dirname(fullTo), {recursive: true}); + this.cacheMkdir(path.dirname(fullTo)); fs.writeFileSync(fullTo, data); if (this.cacheFile) { this.cacheFile.addWriteFile(to, data); @@ -118,7 +122,7 @@ class PluginEnvApi { const fullFrom = path.join(this.root, from); const fullTo = path.join(this.distRoot, to); - fs.mkdirSync(path.dirname(fullTo), {recursive: true}); + this.cacheMkdir(path.dirname(fullTo)); fs.copyFileSync(fullFrom, fullTo); if (this.cacheFile) { this.cacheFile.addCopyFile({from, to}); @@ -129,7 +133,7 @@ class PluginEnvApi { const {to, data} = action; const fullTo = path.join(this.distRoot, to); - fs.mkdirSync(path.dirname(fullTo), {recursive: true}); + this.cacheMkdir(path.dirname(fullTo)); fs.writeFileSync(fullTo, data); if (this.cacheFile) { this.cacheFile.addWriteFile(to, data); @@ -150,7 +154,7 @@ class PluginEnvApi { const fullFrom = path.join(this.root, from); const fullTo = path.join(this.distRoot, to); - await fs.promises.mkdir(path.dirname(fullTo), {recursive: true}); + await this.cacheMkdirAsync(path.dirname(fullTo)); await fs.promises.copyFile(fullFrom, fullTo); if (this.cacheFile) { this.cacheFile.addCopyFile({from, to}); @@ -161,7 +165,7 @@ class PluginEnvApi { const {to, data} = action; const fullTo = path.join(this.distRoot, to); - await fs.promises.mkdir(path.dirname(fullTo), {recursive: true}); + await this.cacheMkdirAsync(path.dirname(fullTo)); await fs.promises.writeFile(fullTo, data); if (this.cacheFile) { this.cacheFile.addWriteFile(to, data); @@ -171,6 +175,43 @@ class PluginEnvApi { } })); } + + private cacheMkdir(path: string) { + const {mkdirCache} = this; + if (!mkdirCache.has(path)) { + fs.mkdirSync(path, {recursive: true}); + mkdirCache.add(path); + } + } + + private async cacheMkdirAsync(path: string) { + const {mkdirCache} = this; + if (!mkdirCache.has(path)) { + await fs.promises.mkdir(path, {recursive: true}); + mkdirCache.add(path); + } + } + + private cacheReadFileSync(filename: string, encoding: BufferEncoding | null = null) { + const {readFileCache} = this; + const key = `${filename}_${encoding}`; + let result = readFileCache.get(key); + if (result === undefined) { + result = fs.readFileSync(filename, encoding); + readFileCache.set(key, result); + } + return result; + } + + private cacheExistsSync(filename: string) { + const {fileExistsCache} = this; + let result = fileExistsCache.get(filename); + if (result === undefined) { + result = fs.existsSync(filename); + fileExistsCache.set(filename, result); + } + return result; + } } export default PluginEnvApi;