diff --git a/index.js b/index.js index f6e486d..b95b39a 100644 --- a/index.js +++ b/index.js @@ -12,7 +12,6 @@ var path = require('path'); * Helper methods. */ -var compile = babel.transform; var canCompile = babel.util.canCompile; /** @@ -49,37 +48,75 @@ function plugin(o) { var ignore = extract(o, 'ignore'); if (ignore) debug('not compiling files matching', ignore); - return function babel(file, entry) { + return function* babel(file, entry) { // compile only what babel recognizes if (!canCompile(file.path, extensions)) return debug('ignoring file: %s', file.path); // ignore remotes if configured to if (onlyLocals && file.remote()) return debug('ignoring remote: %s', file.id); - var root = file.duo.root(); - - var options = extend(true, { - filename: file.path, - filenameRelative: file.id, - sourceMap: file.duo.sourceMap() ? 'inline' : false, - sourceRoot: '/', - only: prepend(only, root), - ignore: prepend(ignore, root) - }, o); - - try { - debug('attempting to compile: %s', file.id, options); - var es5 = compile(file.src, options); - if (file.src === es5.code) debug('did not compile: %s', file.id); - file.type = 'js'; - file.src = es5.code; - } catch (err) { - debug('failed to compile: %s', file.id); - throw new Error(err.message); - } + var duo = file.duo; + var es5 = yield run(duo, file, o, only, ignore); + file.src = es5.code; + file.type = 'js'; }; } +/** + * Run the compilation, but utilizes the cache if available. + * + * @param {Duo} duo Duo instance + * @param {File} file File to be compiled + * @param {Object} options User-defined config + * @param {Array} only User-defined whilelist + * @param {Array} ignore User-defined blacklist + * @returns {Object} Results of babel compile + */ + +function* run(duo, file, options, only, ignore) { + var cache = yield duo.getCache(); + if (!cache) { + debug('cache not enabled for %s', file.id); + return compile(duo, file, options, only, ignore); + } + + var key = [ duo.hash(file.src), duo.hash(options) ]; + var cached = yield cache.plugin('babel', key); + if (cached) { + debug('retrieved %s from cache', file.id); + return cached; + } + + var results = compile(duo, file, options, only, ignore); + yield cache.plugin('babel', key, results); + debug('saved %s to cache', file.id); + return results; +} + +/** + * Compiles the file given options from user. + */ + +function compile(duo, file, options, only, ignore) { + var root = duo.root(); + var sourceMap = duo.sourceMap(); + + var o = extend(true, { + ast: false, + filename: file.path, + filenameRelative: file.id, + sourceMap: sourceMap ? 'inline' : false, + sourceRoot: '/', + only: prepend(only, root), + ignore: prepend(ignore, root) + }, options); + + debug('attempting to compile: %s', file.id, o); + var es5 = babel.transform(file.src, o); + if (file.src === es5.code) debug('did not compile: %s', file.id); + return es5; +} + /** * Prepend a value to each item in the given array. * diff --git a/package.json b/package.json index e76588b..8718b02 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ }, "devDependencies": { "convert-source-map": "^1.0.0", - "duo": "^0.11.2", - "mocha": "^2.2.4" + "duo": "^0.13.0", + "mocha": "^2.2.4", + "rimraf": "^2.4.1" } } diff --git a/test/index.js b/test/index.js index d967171..fd2aa0b 100644 --- a/test/index.js +++ b/test/index.js @@ -4,16 +4,21 @@ */ var assert = require('assert'); +var babel = require('..'); var convert = require('convert-source-map'); var Duo = require('duo'); var path = require('path'); -var babel = require('..'); +var rm = require('rimraf').sync; var vm = require('vm'); /** * Tests */ +after(function () { + rm(path.join(__dirname, 'components/duo-cache')); +}); + describe('duo-babel', function() { it('should compile .js', function(done) { build('simple.js').run(function(err, src) { @@ -121,6 +126,29 @@ describe('duo-babel', function() { done(); }); }); + + describe('with cache enabled', function () { + it('should still work', function(done) { + build('simple.js').cache(true).run(done); + }); + + it('should be significantly faster', function(done) { + var timer1 = timer(); + build('simple.js').run(function (err, src) { + if (err) return done(err); + var noCache = timer1(); + + var timer2 = timer(); + build('simple.js').cache(true).run(function (err, src) { + if (err) return done(err); + + var withCache = timer2(); + assert(withCache < noCache / 2); + done(); + }); + }); + }); + }); }); /** @@ -149,3 +177,18 @@ function evaluate(src, ctx) { ctx = ctx || { console: console }; return vm.runInNewContext(src, ctx)(1); } + +/** + * Create a timer. The function returned should be called + * later and it will return the number of ms since it was + * created. + * + * @returns {Function} + */ + +function timer() { + var now = (new Date()).getTime(); + return function () { + return (new Date()).getTime() - now; + }; +} diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 0000000..6cb4788 --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1 @@ +--harmony-generators