├── .npmignore ├── .travis.yml ├── example ├── command-line │ └── lib │ │ └── foo.js ├── test-module │ ├── test2 │ │ ├── index.js │ │ ├── submodule │ │ │ ├── index.js │ │ │ └── package.json │ │ └── package.json │ ├── index.js │ └── package.json ├── build.js ├── build-files.js ├── build-cachefile.js └── build-manual-cache.js ├── .eslintignore ├── .gitignore ├── CONTRIBUTING.md ├── package.json ├── .eslintrc.js ├── index.js ├── bin └── cmd.js ├── test ├── command-line.js └── build.js └── README.md /.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | support 3 | test 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "4.2" -------------------------------------------------------------------------------- /example/command-line/lib/foo.js: -------------------------------------------------------------------------------- 1 | module.exports = 'FOO'; -------------------------------------------------------------------------------- /example/test-module/test2/index.js: -------------------------------------------------------------------------------- 1 | require('./submodule'); 2 | -------------------------------------------------------------------------------- /example/test-module/test2/submodule/index.js: -------------------------------------------------------------------------------- 1 | console.log('submodule'); 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | example/output/ 2 | example/test-module/ 3 | example/command-line/ -------------------------------------------------------------------------------- /example/test-module/index.js: -------------------------------------------------------------------------------- 1 | require('./package.json'); 2 | require('./test2'); 3 | -------------------------------------------------------------------------------- /example/test-module/test2/submodule/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "submodule", 3 | "version": "0.0.1", 4 | "style" : "style/*.css" 5 | } 6 | -------------------------------------------------------------------------------- /example/test-module/test2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test-module", 3 | "version": "0.0.1", 4 | "style" : "style/*.less", 5 | "transforms" : ["less-css-stream"], 6 | "dependencies": { 7 | "less-css-stream": "^0.1.2" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/test-module/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test-module", 3 | "version": "0.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "James Friend (http://jsdf.co/)", 10 | "license": "ISC", 11 | "dependencies": { 12 | "react": "^0.14.7" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /example/build.js: -------------------------------------------------------------------------------- 1 | var br = require('../'); 2 | var fs = require('fs'); 3 | 4 | var counter = 10; 5 | var testTimeout = 1000; 6 | 7 | var b = br(); 8 | // b.on('log', function(msg){ console.log(msg) }) 9 | b.add(__dirname + '/test-module'); 10 | 11 | run(); // start test 12 | 13 | function run() { 14 | b.bundle() 15 | .on('end', next) 16 | .pipe(fs.createWriteStream(__dirname + '/output/bundle.js')); 17 | } 18 | 19 | function next() { 20 | if (counter-- > 0) { 21 | setTimeout(run, testTimeout); 22 | console.log('built once'); 23 | } else console.log('done'); 24 | } 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore docs files 2 | _gh_pages 3 | _site 4 | .ruby-version 5 | 6 | # Numerous always-ignore extensions 7 | *.diff 8 | *.err 9 | *.orig 10 | *.log 11 | *.rej 12 | *.swo 13 | *.swp 14 | *.zip 15 | *.vi 16 | *~ 17 | 18 | # OS or Editor folders 19 | .DS_Store 20 | ._* 21 | Thumbs.db 22 | .cache 23 | .project 24 | .settings 25 | .tmproj 26 | *.esproj 27 | nbproject 28 | *.sublime-project 29 | *.sublime-workspace 30 | .idea 31 | 32 | # Komodo 33 | *.komodoproject 34 | .komodotools 35 | 36 | # Folders to ignore 37 | node_modules 38 | bower_components 39 | 40 | example/output 41 | browserify-cache.json -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributor Guidelines 2 | 3 | This project has automated tests which can be run with `npm test`. This will be 4 | run in Travis CI when you make a Pull Request so please try to ensure that they 5 | are passing when submitting one. If your PR adds new features please also add 6 | tests. If your PR fixes a bug, it might be helpful to add a test which would fail 7 | if the bug was re-introduced. 8 | 9 | The source code of this project is also checked for coding errors and code style 10 | consistency using ESLint. You can run it with `npm run lint` to see any errors, 11 | and you can automatically fix some coding style errors using `npm run lint-fix`. 12 | -------------------------------------------------------------------------------- /example/build-files.js: -------------------------------------------------------------------------------- 1 | console.time('total'); 2 | console.time('startup'); 3 | var browserifyIncremental = require('../'); 4 | var fs = require('fs'); 5 | 6 | console.timeEnd('startup'); 7 | var cache = true; 8 | 9 | console.time('cache fill'); 10 | var opts; 11 | if (cache) { 12 | opts = {cacheFile: __dirname + '/output/cache.json'}; 13 | } else { 14 | opts = {}; 15 | } 16 | var b = browserifyIncremental([__dirname + '/test-module'], opts); 17 | console.timeEnd('cache fill'); 18 | b.on('log', function(msg) { console.log(msg); }); 19 | b.on('update', function(updated) { console.log('changed files\n' + updated.join('\n')); }); 20 | 21 | process.on('exit', function() { console.timeEnd('total'); }); 22 | 23 | run(); // start test 24 | 25 | function run() { 26 | console.time('bundle'); 27 | b.bundle() 28 | .on('end', function() { console.timeEnd('bundle'); }) 29 | .pipe(fs.createWriteStream(__dirname + '/output/bundle.js')); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /example/build-cachefile.js: -------------------------------------------------------------------------------- 1 | console.time('total'); 2 | console.time('startup'); 3 | var browserifyIncremental = require('../'); 4 | var fs = require('fs'); 5 | 6 | console.timeEnd('startup'); 7 | var cache = true; 8 | 9 | console.time('cache fill'); 10 | var opts; 11 | if (cache) { 12 | opts = {cacheFile: __dirname + '/output/cache.json'}; 13 | } else { 14 | opts = {}; 15 | } 16 | var b = browserifyIncremental(opts); 17 | console.timeEnd('cache fill'); 18 | b.on('log', function(msg) { console.log(msg); }); 19 | b.on('update', function(updated) { console.log('changed files\n' + updated.join('\n')); }); 20 | b.add(__dirname + '/test-module'); 21 | 22 | process.on('exit', function() { console.timeEnd('total'); }); 23 | 24 | run(); // start test 25 | 26 | function run() { 27 | console.time('bundle'); 28 | b.bundle() 29 | .on('end', function() { console.timeEnd('bundle'); }) 30 | .pipe(fs.createWriteStream(__dirname + '/output/bundle.js')); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "browserify-incremental", 3 | "version": "3.1.1", 4 | "description": "Fast incremental rebuilds for browserify", 5 | "main": "index.js", 6 | "bin": { 7 | "browserifyinc": "./bin/cmd.js" 8 | }, 9 | "scripts": { 10 | "test": "npm run lint && tap test", 11 | "lint": "eslint .", 12 | "lint-fix": "eslint . --fix" 13 | }, 14 | "author": "James Friend (http://jsdf.co/)", 15 | "license": "MIT", 16 | "homepage": "https://github.com/jsdf/browserify-incremental", 17 | "bugs": "https://github.com/jsdf/browserify-incremental/issues", 18 | "repository": { 19 | "type": "git", 20 | "url": "git://github.com/jsdf/browserify-incremental.git" 21 | }, 22 | "dependencies": { 23 | "JSONStream": "^0.10.0", 24 | "browserify-cache-api": "^3.0.0", 25 | "through2": "^2.0.0", 26 | "xtend": "^4.0.0" 27 | }, 28 | "peerDependencies": { 29 | "browserify": "*" 30 | }, 31 | "devDependencies": { 32 | "browserify": "^13.0.0", 33 | "eslint": "2.4.0", 34 | "tap": "^5.7.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: "eslint:recommended", 3 | parserOptions: { 4 | ecmaVersion: 6, 5 | sourceType: "module", 6 | }, 7 | env: { 8 | node: true, 9 | }, 10 | rules: { 11 | "no-console": 0, 12 | // style 13 | "semi": 2, 14 | "no-extra-semi": 2, 15 | "no-multi-spaces": 2, 16 | "array-bracket-spacing": 2, 17 | "block-spacing": 2, 18 | "comma-spacing": 2, 19 | "comma-dangle": [2, "always-multiline"], 20 | "computed-property-spacing": 2, 21 | "eol-last": 2, 22 | "indent": [2, 2], 23 | "keyword-spacing": 2, 24 | "linebreak-style": 2, 25 | "no-spaced-func": 2, 26 | "no-trailing-spaces": 2, 27 | "object-curly-spacing": 2, 28 | "quotes": [2, "single", "avoid-escape"], 29 | "semi": 2, 30 | "semi-spacing": 2, 31 | "space-before-blocks": 2, 32 | "space-before-function-paren": [2, "never"], 33 | "space-in-parens": 2, 34 | "space-infix-ops": 2, 35 | "space-unary-ops": 2, 36 | "arrow-spacing": 2, 37 | "generator-star-spacing": 2, 38 | "template-curly-spacing": 2, 39 | "yield-star-spacing": 2, 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /example/build-manual-cache.js: -------------------------------------------------------------------------------- 1 | console.time('total'); 2 | console.time('startup'); 3 | var browserifyIncremental = require('../'); 4 | var fs = require('fs'); 5 | 6 | console.timeEnd('startup'); 7 | var cache = true; 8 | 9 | console.time('cache fill'); 10 | var opts; 11 | if (cache) { 12 | var incrementalCache = JSON.parse(fs.readFileSync(__dirname + '/output/cache.json', {encoding: 'utf8'})); 13 | opts = {cache:incrementalCache.cache, mtimes: incrementalCache.mtimes}; 14 | } else { 15 | opts = {}; 16 | } 17 | console.timeEnd('cache fill'); 18 | var b = browserifyIncremental(opts); 19 | b.on('log', function(msg) { console.log(msg); }); 20 | b.on('cache', function(incrementalCache) { fs.writeFile(__dirname + '/output/cache.json', JSON.stringify(incrementalCache)); }); 21 | b.on('update', function(updated) { console.log('changed files', updated); }); 22 | b.add(__dirname + '/test-module'); 23 | 24 | process.on('exit', function() { console.timeEnd('total'); }); 25 | 26 | run(); // start test 27 | 28 | function run() { 29 | console.time('bundle'); 30 | b.bundle() 31 | .on('end', function() { console.timeEnd('bundle'); }) 32 | .pipe(fs.createWriteStream(__dirname + '/output/bundle.js')); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var xtend = require('xtend'); 2 | var through = require('through2'); 3 | var browserify = require('browserify'); 4 | var browserifyCache = require('browserify-cache-api'); 5 | 6 | module.exports = browserifyIncremental; 7 | browserifyIncremental.browserify = browserify; 8 | browserifyIncremental.args = browserifyCache.args; 9 | 10 | function browserifyIncremental(files, opts) { 11 | var b; // browserify instance 12 | 13 | // browserify plugin boilerplate, normalises variable arguments 14 | if (files && typeof files.bundle === 'function') { 15 | // browserify instance as first arg 16 | b = files; 17 | opts = opts || b._options; 18 | } else { 19 | if (!opts) { 20 | // opts as first arg (or no args) 21 | opts = files || {}; 22 | files = undefined; 23 | b = browserify(xtend(browserifyCache.args, opts)); 24 | } else { 25 | // files as first arg, opts as second arg 26 | b = browserify(files, xtend(browserifyCache.args, opts)); 27 | } 28 | } 29 | 30 | browserifyCache(b, opts); 31 | 32 | if (!b.pipeline) b.emit('error', new Error('missing pipeline: incompatible browserify version (< 5.x)')); 33 | b.on('reset', function() { attachMetrics(b); }); 34 | attachMetrics(b); 35 | 36 | return b; 37 | } 38 | 39 | function attachMetrics(b) { 40 | var time = null; 41 | var bytes = 0; 42 | b.pipeline.get('record').on('end', function() { 43 | time = Date.now(); 44 | }); 45 | 46 | b.pipeline.get('wrap').push(through(write, end)); 47 | function write(buf, enc, next) { 48 | bytes += buf.length; 49 | this.push(buf); 50 | next(); 51 | } 52 | function end() { 53 | var delta = Date.now() - time; 54 | b.emit('time', delta); 55 | b.emit('bytes', bytes); 56 | b.emit('log', bytes + ' bytes written (' 57 | + (delta / 1000).toFixed(2) + ' seconds)' 58 | ); 59 | this.push(null); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /bin/cmd.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var browserifyIncremental = require('../'); 4 | var fs = require('fs'); 5 | var fromArgs = require('browserify/bin/args'); 6 | var JSONStream = require('JSONStream'); 7 | var through = require('through2'); 8 | 9 | function run() { 10 | process.stdout.on('error', process.exit); 11 | 12 | var b, outfile, verbose, cachefile; 13 | 14 | var b_ = fromArgs(process.argv.slice(2), browserifyIncremental.args); 15 | cachefile = b_.argv.cachefile || './browserify-cache.json'; 16 | outfile = b_.argv.o || b_.argv.outfile; 17 | verbose = (b_.argv.v || b_.argv.verbose); 18 | b = browserifyIncremental(b_, {cacheFile: cachefile}); 19 | 20 | b.on('update', function(changes) { 21 | if (verbose && changes.length) console.error('changed files:\n' + changes.join('\n')); 22 | }); 23 | 24 | if (b.argv.version) { 25 | return console.log(require('../package.json').version); 26 | } 27 | 28 | b.on('error', errorExit); 29 | 30 | if (b.argv.pack) { 31 | process.stdin.pipe(b.pack()).pipe(process.stdout); 32 | process.stdin.resume(); 33 | return; 34 | } 35 | 36 | if (b.argv.deps) { 37 | var stringify = JSONStream.stringify(); 38 | stringify.pipe(process.stdout); 39 | b.pipeline.get('deps').push(through.obj( 40 | function(row, enc, next) { stringify.write(row); next(); }, 41 | function() { stringify.end(); } 42 | )); 43 | return b.bundle(); 44 | } 45 | 46 | if (b.argv.list) { 47 | b.pipeline.get('deps').push(through.obj(function(row, enc, next) { 48 | console.log(row.file || row.id); 49 | next(); 50 | })); 51 | return b.bundle(); 52 | } 53 | 54 | var bytes, time; 55 | b.on('bytes', function(b) { bytes = b; }); 56 | b.on('time', function(t) { time = t; }); 57 | 58 | var bundle = b.bundle(); 59 | bundle.on('error', errorExit); 60 | 61 | bundle.on('end', function() { 62 | if (verbose) { 63 | console.error(bytes + ' bytes written to ' + (outfile || 'stdout') 64 | + ' (' + (time / 1000).toFixed(2) + ' seconds)' 65 | ); 66 | } 67 | }); 68 | 69 | if (outfile) { 70 | bundle.pipe(fs.createWriteStream(outfile)); 71 | } 72 | else { 73 | bundle.pipe(process.stdout); 74 | } 75 | } 76 | 77 | function errorExit(err) { 78 | if (err.stack) { 79 | console.error(err.stack); 80 | } 81 | else { 82 | console.error(String(err)); 83 | } 84 | process.exit(1); 85 | } 86 | 87 | run(); 88 | -------------------------------------------------------------------------------- /test/command-line.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | var exec = require('child_process').exec; 3 | var spawn = require('child_process').spawn; 4 | var path = require('path'); 5 | var fs = require('fs'); 6 | var xtend = require('xtend'); 7 | 8 | var basedir = path.resolve(__dirname, '../'); 9 | var exampledir = path.join(basedir, 'example', 'command-line'); 10 | var outputdir = path.join(basedir, 'example', 'output', 'command-line', 'build'); 11 | var dynamicModule = path.join(outputdir, 'dynamic.js'); 12 | var requiresDynamicModule = path.join(outputdir, 'requires-dynamic.js'); 13 | 14 | // also allows building with a custom NODE_PATH eg. 15 | // NODE_PATH=$PWD/lib/ browserifyinc --require foo in.js > out.js 16 | 17 | test('make sure it builds via command line', function(t) { 18 | var iterations = 3; 19 | 20 | t.plan(1 + iterations * 2); 21 | 22 | if (!(outputdir.charAt(0) == '/' && outputdir.length > 1)) { 23 | throw new Error('unsafe outputdir for rm -rf'); 24 | } 25 | exec('rm -rfv ' + outputdir, function() { 26 | exec('mkdir -p ' + outputdir, function(err) { 27 | t.notOk(err, 'dir created'); 28 | fs.writeFileSync(requiresDynamicModule, 'require("./dynamic")'); 29 | build(1, iterations); 30 | }); 31 | }); 32 | 33 | function build(n, nmax) { 34 | // setup 35 | fs.writeFileSync(dynamicModule, 'console.log("build ' + n + '")'); 36 | 37 | var processExited = false; 38 | var outputFileClosed = false; 39 | 40 | var buildProc = makeBuildProc(); 41 | 42 | function maybeDone() { 43 | if (!(processExited && outputFileClosed)) return; 44 | 45 | if (n == nmax) { 46 | t.end(); 47 | } else { 48 | setTimeout(function() { 49 | build(n + 1, nmax); 50 | }, 2000); // mtime resolution can be 1-2s depending on OS 51 | } 52 | } 53 | 54 | buildProc 55 | .on('exit', function(code) { 56 | processExited = true; 57 | t.ok(code == 0, 'built ' + n + ' times'); 58 | maybeDone(); 59 | }); 60 | 61 | buildProc.stdout 62 | .pipe(fs.createWriteStream(path.join(outputdir, 'build' + n + '.js'))) 63 | .on('close', function() { 64 | outputFileClosed = true; 65 | t.ok(true, 'got output ' + n); 66 | maybeDone(); 67 | }); 68 | } 69 | }); 70 | 71 | function makeBuildProc() { 72 | var browserifyIncBin = require.resolve('../bin/cmd.js'); 73 | 74 | var proc = spawn(browserifyIncBin, [ 75 | '--cachefile', path.join(outputdir, 'cache.json'), 76 | '--require', 'foo', 77 | dynamicModule, 78 | ], { 79 | env: xtend(process.env, { 80 | // allows require('foo') from lib/ dir 81 | NODE_PATH: path.join(exampledir, 'lib'), 82 | }), 83 | }); 84 | 85 | proc.stderr.pipe(process.stderr); 86 | 87 | return proc; 88 | } 89 | -------------------------------------------------------------------------------- /test/build.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | var exec = require('child_process').exec; 3 | var path = require('path'); 4 | var through = require('through2'); 5 | var fs = require('fs'); 6 | 7 | var basedir = path.resolve(__dirname, '../'); 8 | var outputdir = path.join(basedir, 'example', 'output', 'test', 'build'); 9 | var dynamicModule = path.join(outputdir, 'dynamic.js'); 10 | var requiresDynamicModule = path.join(outputdir, 'requires-dynamic.js'); 11 | 12 | test('make sure it builds and builds again', function(t) { 13 | var iterations = 3; 14 | 15 | t.plan(11); // 1 assertion at setup + (3 builds * 3 assertions) + 1 post assertion 16 | 17 | if (!(outputdir.charAt(0) == '/' && outputdir.length > 1)) { 18 | throw new Error('unsafe outputdir for rm -rf'); 19 | } 20 | exec('rm -rfv ' + outputdir, function() { 21 | exec('mkdir -p ' + outputdir, function(err) { 22 | t.notOk(err, 'dir created'); 23 | fs.writeFileSync(requiresDynamicModule, 'require("./dynamic")'); 24 | build(1, iterations); 25 | }); 26 | }); 27 | 28 | function build(n, nmax) { 29 | fs.writeFileSync(dynamicModule, 'console.log("' + n + '")'); 30 | 31 | var b = make(); 32 | 33 | var numChanged = 0; 34 | var cacheSize = Object.keys(b._options.cache).length; 35 | 36 | b.on('changedDeps', function(invalidated) { 37 | if (invalidated) numChanged = invalidated.length; 38 | }); 39 | 40 | var outputFile = path.join(outputdir, 'build' + n + '.js'); 41 | b.bundle() 42 | .pipe(through()) 43 | .on('finish', function() { 44 | t.ok(true, 'built ' + n + ' times'); 45 | 46 | t.ok( 47 | n == 1 ? numChanged == 0 : numChanged > 0, 48 | numChanged + ' items invalidated before build ' + n 49 | ); 50 | 51 | // TODO: fix cache load race condition 52 | t.ok( 53 | n == 1 ? cacheSize == 0 : cacheSize > 0, 54 | 'cache size ' + cacheSize + ' at start of build ' + n 55 | ); 56 | }) 57 | .pipe(fs.createWriteStream(outputFile)) 58 | .on('close', function() { 59 | if (n == nmax) { 60 | var output = fs.readFileSync(outputFile, {encoding: 'utf8'}); 61 | t.notMatch(output, 'module.exports=module.exports={', "doesn't append json prelude twice"); 62 | t.end(); 63 | } else { 64 | setTimeout(function() { 65 | build(n + 1, nmax); 66 | }, 2000); // mtime resolution can be 1-2s depending on OS 67 | } 68 | }); 69 | } 70 | }); 71 | 72 | function make() { 73 | var browserifyIncremental = require('../'); 74 | 75 | var opts = {cacheFile: path.join(outputdir, 'cache.json')}; 76 | 77 | var b = browserifyIncremental(opts); 78 | b.add(path.join(basedir, 'example/test-module')); 79 | b.add(requiresDynamicModule); 80 | 81 | return b; 82 | } 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # browserify-incremental 2 | 3 | Incremental rebuild for browserify 4 | 5 | Update any source file and re-bundle, and only changed files will be parsed, 6 | so it will build super fast (even with big dependencies like React!). 7 | 8 | 9 | ## How is this different from [watchify](https://github.com/substack/watchify)? 10 | 11 | browserify-incremental can detect changes which occured in between runs, which 12 | means it can be used as part of build systems which are invoked on demand, 13 | without requiring a long lived process. Whereas watchify is slow for the first 14 | run upon each startup, browserify-incremental is fast every time after the very 15 | first. 16 | 17 | 18 | # example 19 | 20 | Use `browserifyinc` with all the same arguments as `browserify`, with the added 21 | `--cachefile` argument specifying where to put the cache file: 22 | 23 | ``` 24 | $ browserifyinc -r react -o output/bundle.js -v 25 | 556200 bytes written to output/bundle.js (1.38 seconds) 26 | $ browserifyinc -r react -o output/bundle.js -v 27 | 556200 bytes written to output/bundle.js (0.13 seconds) 28 | ``` 29 | 30 | Now if you change some files and rebuild, only the changed files will be parsed 31 | and the rest will reuse the previous build's cached output. 32 | 33 | You can use `-v`/`--verbose` to get more verbose output to show which files have 34 | changed and how long the bundling took: 35 | 36 | ``` 37 | $ browserifyinc test-module/ -v -o output/bundle.js 38 | changed files: 39 | /Users/jfriend/code/browserify-incremental/example/test-module/index.js 40 | 1000423 bytes written to output/bundle.js (0.18 seconds) 41 | ``` 42 | 43 | If you don't specify `--cachefile`, a `browserify-cache.json` file will be 44 | created in the current working directory. 45 | 46 | # usage 47 | 48 | # CLI 49 | 50 | ``` 51 | browserifyinc --cachefile tmp/browserify-cache.json main.js > output.js 52 | ``` 53 | 54 | All the bundle options are the same as the browserify command except for `-v` 55 | and `--cachefile`. 56 | 57 | # API 58 | 59 | ``` js 60 | var browserifyInc = require('browserify-incremental') 61 | ``` 62 | 63 | ## var b = browserifyInc(opts) 64 | 65 | Create a browserify bundle `b` from `opts`. 66 | 67 | `b` is exactly like a browserify bundle except that it caches file contents and 68 | calling `b.bundle()` extra times past the first time will be much faster 69 | due to that caching. 70 | 71 | By default, when used via API, browserify-incremental will only use in-memory 72 | caching, however you can pass a `cacheFile` option which will use an on disk 73 | cache instead (useful for build scripts which run once and exit). 74 | 75 | You can also pass in a browserify instance of your own, and that will be used 76 | instead of creating a new one, however when you create your browserify instance 77 | you must include the following options: 78 | 79 | ```js 80 | {cache: {}, packageCache: {}, fullPaths: true} 81 | ``` 82 | 83 | For convenience, these options are available as `browserifyInc.args`, so you can 84 | use them like: 85 | 86 | ```js 87 | var browserify = require('browserify') 88 | var browserifyInc = require('browserify-incremental') 89 | 90 | var b = browserify(Object.assign({}, browserifyInc.args, { 91 | // your custom opts 92 | })) 93 | browserifyInc(b, {cacheFile: './browserify-cache.json'}) 94 | 95 | b.bundle().pipe(process.stdout) 96 | ``` 97 | 98 | The `cacheFile` opt can be passed to either the browserify or browserify-incremental 99 | constructor. 100 | 101 | # events 102 | 103 | ## b.on('bytes', function (bytes) {}) 104 | 105 | When a bundle is generated, this event fires with the number of bytes written. 106 | 107 | ## b.on('time', function (time) {}) 108 | 109 | When a bundle is generated, this event fires with the time it took to create the 110 | bundle in milliseconds. 111 | 112 | ## b.on('log', function (msg) {}) 113 | 114 | This event fires to with messages of the form: 115 | 116 | ``` 117 | X bytes written (Y seconds) 118 | ``` 119 | 120 | with the number of bytes in the bundle X and the time in seconds Y. 121 | 122 | # install 123 | 124 | With [npm](https://npmjs.org) do: 125 | 126 | ``` 127 | $ npm install -g browserify-incremental browserify 128 | ``` 129 | 130 | to get the browserifyinc command and: 131 | 132 | ``` 133 | $ npm install --save browserify-incremental browserify 134 | ``` 135 | 136 | to get just the library. 137 | 138 | ## Contributing 139 | 140 | Please see the [Contributor Guidelines](CONTRIBUTING.md). 141 | 142 | # license 143 | 144 | MIT 145 | --------------------------------------------------------------------------------