diff --git a/.eslintrc b/.eslintrc index 18bfaa0..d6a6324 100755 --- a/.eslintrc +++ b/.eslintrc @@ -1,31 +1,6 @@ { - "ecmaFeatures": { - "arrowFunctions": true, - "binaryLiterals": true, - "blockBindings": true, - "classes": true, - "defaultParams": true, - "destructuring": true, - "forOf": true, - "generators": true, - "modules": false, - "objectLiteralComputedProperties": true, - "objectLiteralDuplicateProperties": true, - "objectLiteralShorthandMethods": true, - "objectLiteralShorthandProperties": true, - "octalLiterals": true, - "regexUFlag": true, - "regexYFlag": true, - "superInFunctions": true, - "templateStrings": true, - "unicodeCodePointEscapes": true, - "globalReturn": true, - "jsx": true - }, "env": { - "browser": true, - "node": true, - "es6": true + "node": true }, "rules": { "no-comma-dangle": 2, @@ -134,7 +109,7 @@ "comma-spacing": [ 1, { - "before": 0, + "before": false, "after": true } ], @@ -155,7 +130,7 @@ "key-spacing": [ 1, { - "beforeColon": 0, + "beforeColon": false, "afterColon": true } ], @@ -178,7 +153,14 @@ "no-trailing-spaces": 2, "no-underscore-dangle": 0, "no-wrap-func": 2, - "one-var": 1, + "one-var": [ + 1, + { + "var": "always", + "let": "never", + "const": "never" + } + ], "operator-assignment": [ 2, "always" @@ -205,7 +187,7 @@ "always" ], "space-before-blocks": 0, - "space-before-function-parentheses": [ + "space-before-function-paren": [ 1, "always" ], @@ -222,11 +204,12 @@ "space-unary-ops": [ 1, { - "words": 2, + "words": true, "nonwords": false } ], - "spaced-line-comment": [ + "spaced-comment": [ + 1, "always", { "exceptions": [ diff --git a/README.md b/README.md index 3406232..063c41a 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ If `true`, minifies source code and sets debug to true. If object, passed as opt If `true`, [watchify](https://github.com/substack/watchify) will be used to create a file watcher and speed up subsequent builds. #### opts.cache -If truthy, will use [browserify-incremental](https://github.com/jsdf/browserify-incremental) to cache the result of a build. This can give you dramatically faster build times if you're not using `opts.watch`. +If truthy, will use [rebundler](https://github.com/bjoerge/rebundler) to cache the result of a build. This can give you dramatically faster build times if you're not using `opts.watch`. If `opts.cache` is a string, it will be used as the file path to save the cache file to. diff --git a/index.js b/index.js index 6c54b53..a700e00 100644 --- a/index.js +++ b/index.js @@ -1,9 +1,10 @@ 'use strict' var browserify = require('browserify') - , browserifyInc = require('browserify-incremental') + , rebundler = require('rebundler') , path = require('path') , fs = require('fs') + , md5 = require('MD5') , events = require('events') , mkdirp = require('mkdirp') , watchify = require('watchify') @@ -30,6 +31,8 @@ ctor = module.exports = function atomifyJs (opts, cb) { , _outputcb , _buffercb , browserifyOptions + , persistKey + , cacheChecker , transforms , assets , outputs @@ -90,25 +93,33 @@ ctor = module.exports = function atomifyJs (opts, cb) { // remove the default 600ms delay because speed is tood // ignoreWatch to true to ignore node_modules if (opts.watch) _.extend({delay: 0, ignoreWatch: true}, browserifyOptions, watchify.args) - // mixin the required browserifyInc options if we need to cache - if (opts.cache) _.extend(browserifyOptions, browserifyInc.args) - - b = browserify(browserifyOptions) if (opts.cache) { - b = browserifyInc(b - , _.isString(opts.cache) ? {cacheFile: opts.cache} : {} - ) + persistKey = md5(opts.entry || opts.entries.toString() || opts.require.toString()) + + b = browserify(_.extend(browserifyOptions, { + fullPaths: true + })) + emitter.emit('browserify', b) + + cacheChecker = rebundler({persist: true, persistKey: persistKey, cacheDir: typeof opts.cache === 'string' ? opts.cache : null}, function rebundle (cache, packageCache) { + b._mdeps.cache = { + deps: cache + , pkgs: packageCache + , mtimes: b._mdeps.cache.mtimes + } + return b + }) + } + else { + b = browserify(browserifyOptions) + emitter.emit('browserify', b) } - - emitter.emit('browserify', b) if (opts.watch) { w = watchify(b) emitter.emit('watchify', w) - } - if (opts.watch) { w.on('update', function onUpdate (ids) { ids.forEach(function eachId (id) { emitter.emit('changed', id) @@ -225,7 +236,7 @@ ctor = module.exports = function atomifyJs (opts, cb) { }) // we need to wrap the callback to output an object with all the bundles - return b.bundle(function bundledWithCommon (err, common) { + return (opts.cache ? cacheChecker() : b).bundle(function bundledWithCommon (err, common) { var hasCallback = _.isFunction(cb) , out = {} @@ -249,7 +260,7 @@ ctor = module.exports = function atomifyJs (opts, cb) { }) } // if we don't need to use factor bundle, just browserify! - else return b.bundle(cb) + else return (opts.cache ? cacheChecker() : b).bundle(cb) } ctor.emitter = emitter diff --git a/package.json b/package.json index 24ccb4e..a82adfd 100644 --- a/package.json +++ b/package.json @@ -35,21 +35,22 @@ ], "license": "MIT", "dependencies": { - "babelify": "^6.0.2", + "MD5": "^1.2.2", + "babelify": "^6.1.2", "brfs": "^1.4.0", "browserify": "^7.1.0", - "browserify-incremental": "^1.5.0", "ejsify": "^1.0.0", "envify": "^3.4.0", - "factor-bundle": "^2.4.0", + "factor-bundle": "^2.4.1", "handlebars": "^2.0.0", "hbsfy": "^2.2.1", - "jade": "^1.9.2", - "jadeify": "^4.1.0", - "lodash": "^3.6.0", - "minifyify": "^6.3.2", - "mkdirp": "^0.5.0", + "jade": "^1.11.0", + "jadeify": "^4.3.0", + "lodash": "^3.10.0", + "minifyify": "^6.4.0", + "mkdirp": "^0.5.1", "partialify": "^3.1.2", + "rebundler": "^0.1.0", "resrcify": "^1.1.0", "stream-buffers": "^1.1.0", "watchify": "^2.6.0", @@ -57,10 +58,12 @@ }, "devDependencies": { "dmn": "^1.0.10", - "doctoc": "^0.12.0", - "ghooks": "^0.3.0", - "nodemon": "^1.2.1", - "tap-spec": "^1.0.0", - "tape": "^3.0.0" + "doctoc": "^0.14.1", + "eslint": "^0.24.0", + "ghooks": "^0.3.2", + "nodemon": "^1.3.7", + "rimraf": "^2.4.1", + "tap-spec": "^4.0.2", + "tape": "^4.0.0" } } diff --git a/test/cache.js b/test/cache.js index d9bc112..1474029 100644 --- a/test/cache.js +++ b/test/cache.js @@ -8,19 +8,20 @@ var test = require('tape') , outputPath = path.join(entryPath, 'output') , changerPath = path.join(outputPath, 'changer.js') , mkdirp = require('mkdirp') - , cachePath = path.join(outputPath, 'cache.json') - , setup = function setup(value){ + , cacheDir = path.join(outputPath, 'cache') + , rimraf = require('rimraf') + , setup = function setup (value) { var file = 'module.exports = ' + value || Date.now() mkdirp.sync(outputPath) + mkdirp.sync(cacheDir) fs.writeFileSync(changerPath, file) } -test('opts.cache', function(t){ - var parseTime = function parseTime(logMsg){ - return parseFloat(logMsg.replace(/.*?\(([0-9\.]{1,}) seconds\)/, '$1')) - } - +test('opts.cache', function (t) { + var startTime = Date.now() + , runTests + , b setup() t.plan(5) @@ -30,97 +31,113 @@ test('opts.cache', function(t){ , 'should throw if opts.watch is also set' ) - lib.emitter.once('browserify', function (b){ - b.once('log', function(msg){ - var initialTime = parseTime(msg) + lib.emitter.once('browserify', function (br) { + b = br + }) - t.ok( - msg - , 'compiles once' - ) + runTests = function () { + var firstBundleTime = Date.now() + , firstBundleDuration = firstBundleTime - startTime + + t.ok( + firstBundleDuration + , 'compiles once' + ) - b.bundle() - b.once('log', function(msg2){ - var secondTime = parseTime(msg2) + b.bundle(function () { + var secondBundleTime = Date.now() + , secondBundleDuration = secondBundleTime - firstBundleTime + // wait for 1000ms, b/c rebundler does + setTimeout(function () { // wait for the second callback because some fs are slow. (linux) t.ok( - fs.existsSync(cachePath) + fs.existsSync(cacheDir) , 'writes the cache file' ) // cleanup - fs.unlinkSync(cachePath) + rimraf.sync(cacheDir) + }, 1050) - t.ok( - msg2 - , 'compiles a second time' - ) + t.ok( + secondBundleDuration + , 'compiles a second time' + ) - t.ok( - secondTime <= initialTime - , 'the second of ' + secondTime + ' compiles faster than ' + initialTime - ) - }) + t.ok( + secondBundleDuration <= firstBundleDuration + , 'the second bundle time of ' + secondBundleDuration + ' compiles faster than the initial ' + firstBundleDuration + ) }) - }) + } - lib({cache: cachePath, entry: path.join(entryPath, 'index.js')}) + lib({cache: cacheDir, entry: path.join(entryPath, 'index.js')}, runTests) }) -test('opts.cache works with opts.common', function(t){ - var parseTime = function parseTime(logMsg){ - return parseFloat(logMsg.replace(/.*?\(([0-9\.]{1,}) seconds\)/, '$1')) - } +test('opts.cache works with opts.common', function (t) { + var startTime = Date.now() , bundleNames = ['common', 'dep-1', 'dep-2', 'index'] + , runTests , b setup() - t.plan(6 + bundleNames.length) + t.plan(5 + bundleNames.length) t.throws( lib.bind(null, {watch: true, cache: true}) , 'should throw if opts.watch is also set' ) - lib.emitter.once('browserify', function (browserifyInstance){ + lib.emitter.once('browserify', function (browserifyInstance) { b = browserifyInstance - b.once('log', function(msg){ - var initialTime = parseTime(msg) + }) + + runTests = function (err, bundles) { + var bundleKeys = Object.keys(bundles) + , firstBundleTime = Date.now() + , firstBundleDuration = firstBundleTime - startTime + t.error(err, 'should not error') + + bundleNames.forEach(function ensureEachBundleExists (bundleName) { t.ok( - msg - , 'compiles once' + bundleKeys.indexOf(bundleName) > -1 + , 'creates the ' + bundleName + ' bundle' ) + }) - b.once('log', function(msg2){ - var secondTime = parseTime(msg2) + t.ok( + firstBundleTime + , 'compiles once' + ) - // wait for the second callback because some fs are slow. (linux) - t.ok( - fs.existsSync(cachePath) - , 'writes the cache file' - ) + // trigger another bundle so that we can time the difference + b.bundle(function () { + var secondBundleTime = Date.now() + , secondBundleDuration = secondBundleTime - firstBundleTime + // wait for 1000ms, b/c rebundler does + setTimeout(function () { // cleanup - fs.unlinkSync(cachePath) + if (fs.existsSync(cacheDir)) rimraf.sync(cacheDir) + }, 1020) - t.ok( - msg2 - , 'compiles a second time' - ) + t.ok( + secondBundleDuration + , 'compiles a second time' + ) - t.ok( - secondTime <= initialTime - , 'the second of ' + secondTime + ' compiles faster than ' + initialTime - ) - }) + t.ok( + secondBundleDuration <= firstBundleDuration + , 'the second bundle time of ' + secondBundleDuration + ' compiles faster than the initial ' + firstBundleDuration + ) }) - }) + } lib({ - cache: cachePath + cache: cacheDir , entries: [ path.join(entryPath, 'index.js') , path.join(entryPath, '..', 'entry', 'dep-2.js') @@ -128,19 +145,6 @@ test('opts.cache works with opts.common', function(t){ ] , common: true , debug: true - } - , function(err, bundles){ - var bundleKeys = Object.keys(bundles) - t.error(err, 'should not error') - - bundleNames.forEach(function ensureEachBundleExists(bundleName){ - t.ok( - bundleKeys.indexOf(bundleName) > -1 - , 'creates the ' + bundleName + ' bundle' - ) - }) - - // trigger another bundle so that we can time the difference - b.bundle() - }) + } + , runTests) })