From 0c3689c68f27ba19d779053665eac03e975e9a24 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 | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/index.js b/src/index.js index 1ec504e..5bd4452 100644 --- a/src/index.js +++ b/src/index.js @@ -8,6 +8,37 @@ 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(), + err => { + if (err.code == 'ENOENT') return false; + throw err; + } + ).catch(err => { + 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 +62,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 +135,8 @@ export default function nodeResolve ( options = {} ) { } return pkg; }, + readFile: cachedReadFile, + isFile: cachedIsFile, extensions: options.extensions }, customResolveOptions ), ( err, resolved ) => {