From 6ccdb4f99f8f284a74352de204a9a2a7bac65603 Mon Sep 17 00:00:00 2001 From: Keith Cirkel Date: Sun, 7 Jan 2018 15:16:26 +0000 Subject: [PATCH] perf: cache file stats/reads --- src/index.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/index.js b/src/index.js index 1ec504e..03d0e8e 100644 --- a/src/index.js +++ b/src/index.js @@ -8,6 +8,33 @@ const ES6_BROWSER_EMPTY = resolve( __dirname, '../src/empty.js' ); const CONSOLE_WARN = ( ...args ) => console.warn( ...args ); // eslint-disable-line no-console const exts = [ '.js', '.json', '.node' ]; +let readFileCache = {}; +const readFileAsync = file => new Promise((fulfil, reject) => fs.readFile(file, (err, contents) => err ? reject(err) : fulfil(contents))); +const statAsync = file => new Promise((fulfil, reject) => fs.stat(file, (err, contents) => err ? reject(err) : fulfil(contents))); +function cachedReadFile (file, cb) { + if (file in readFileCache === false) { + readFileCache[file] = readFileAsync(file).catch(err => { + delete readFileCache[file]; + throw err; + }); + } + readFileCache[file].then(contents => cb(null, contents), cb); +} + +let isFileCache = {}; +function cachedIsFile (file, cb) { + if (file in isFileCache === false) { + isFileCache[file] = statAsync(file) + .then(stat => stat.isFile()) + .catch(err => { + if (err.code == 'ENOENT') return false; + delete isFileCache[file]; + throw err; + }); + } + isFileCache[file].then(contents => cb(null, contents), cb); +} + export default function nodeResolve ( options = {} ) { const useModule = options.module !== false; const useMain = options.main !== false; @@ -31,6 +58,11 @@ export default function nodeResolve ( options = {} ) { return { name: 'node-resolve', + write () { + isFileCache = {} + readFileCache = {} + }, + resolveId ( importee, importer ) { if ( /\0/.test( importee ) ) return null; // ignore IDs with null character, these belong to other plugins @@ -99,6 +131,8 @@ export default function nodeResolve ( options = {} ) { } return pkg; }, + readFile: cachedReadFile, + isFile: cachedIsFile, extensions: options.extensions }, customResolveOptions ), ( err, resolved ) => {