diff --git a/bin/args.js b/bin/args.js index ccfdd3f..e966eec 100644 --- a/bin/args.js +++ b/bin/args.js @@ -11,6 +11,7 @@ module.exports = function (args) { if (ignoreWatch) { opts.ignoreWatch = ignoreWatch; } + opts.entryGlob = b.argv['entry-glob']; return watchify(b, xtend(opts, b.argv)); }; diff --git a/index.js b/index.js index 0753b9f..d9ffd14 100644 --- a/index.js +++ b/index.js @@ -89,6 +89,10 @@ function watchify (b, opts) { var fwatcherFiles = {}; var ignoredFiles = {}; + if (opts.entryGlob) { + fwatchers._entryWatcher = [watchEntries(opts.entryGlob)]; + } + b.on('transform', function (tr, mfile) { tr.on('file', function (dep) { watchFile(mfile, dep); @@ -150,6 +154,57 @@ function watchify (b, opts) { changingDeps = {}; } } + + function watchEntries(glob) { + var entriesAdded = {}; + var entriesRemoved = {}; + + var basedir = b._options.basedir || process.cwd(); + var watchOpts = xtend({ cwd: basedir }, wopts); + watchOpts.ignoreInitial = true; + var watcher = chokidar.watch(glob, watchOpts); + + watcher.on('error', b.emit.bind(b, 'error')); + watcher.on('add', function (file) { + file = path.join(basedir, file); + entriesAdded[file] = true; + if (entriesRemoved[file]) { + delete entriesRemoved[file]; + } + invalidate(file); + }); + watcher.on('unlink', function (file) { + file = path.join(basedir, file); + entriesRemoved[file] = true; + if (entriesAdded[file]) { + delete entriesAdded[file]; + } + invalidate(file); + }); + + b.on('reset', function () { + var added = entriesAdded; + var removed = entriesRemoved; + entriesAdded = {}; + entriesRemoved = {}; + var entryOrder = 0; + + b.pipeline.get('record').unshift(through.obj(function (row, enc, next) { + if (row.file && removed[row.file]) { + return next(); + } + if (row.entry) { + // for browser-pack + row.order = entryOrder++; + } + next(null, row); + })); + + b.add(Object.keys(added), { basedir: b._options.basedir }); + }) + + return watcher; + } b.close = function () { Object.keys(fwatchers).forEach(function (id) { diff --git a/test/entry_glob.js b/test/entry_glob.js new file mode 100644 index 0000000..20b818b --- /dev/null +++ b/test/entry_glob.js @@ -0,0 +1,65 @@ +var test = require('tape'); +var watchify = require('../'); +var browserify = require('browserify'); +var vm = require('vm'); + +var fs = require('fs'); +var path = require('path'); +var mkdirp = require('mkdirp'); + +var os = require('os'); +var tmpdir = path.join((os.tmpdir || os.tmpDir)(), 'watchify-' + Math.random()); + +var file = path.join(tmpdir, 'main.js'); + +mkdirp.sync(tmpdir); +fs.writeFileSync(file, 'console.log(333)'); + +var opts = { + cache: {}, + packageCache: {}, + basedir: tmpdir, +}; + +test('entry glob', function (t) { + t.plan(8); + var w = watchify(browserify(file, opts), { entryGlob: '*.js' }); + var toBeAdded = path.join(tmpdir, 'added.js'); + var removed = false; + w.on('update', function () { + w.bundle(function (err, src) { + t.ifError(err); + + if (removed) { + t.equal(run(src), '333\n', 'Should exclude removed entries'); + w.close(); + } else { + t.equal(run(src), '555\n333\n', 'Should include added entries'); + removed = true; + setTimeout(function () { + fs.unlink(toBeAdded, function (err) { + t.ifError(err, 'Remove ' + toBeAdded); + }); + }, 1000); + } + }); + }); + w.bundle(function (err, src) { + t.ifError(err); + t.equal(run(src), '333\n', 'initial'); + + setTimeout(function () { + fs.writeFile(toBeAdded, 'console.log(555)', function (err) { + t.ifError(err, 'Add ' + toBeAdded); + }); + }, 1000); + }); +}); + +function run (src) { + var output = ''; + function log (msg) { output += msg + '\n' } + vm.runInNewContext(src, { console: { log: log } }); + return output; +} +