multibuild
Let's say that you're developing an email platform. You use a rich text
editor in a lot of views—the email editor itself, the signature editor, the template
editor—and you'd like to reuse that component between them without bundling all of the
view-specific JavaScript together.
If you factor your codebase using ES6 modules, you can have per-view "entry" scripts that import that
component and other view-specific modules. A tool like Rollup can then produce
per-view bundles that only include the JavaScript used by each view. But how do you coordinate this
multi-target build process?
That's where multibuild comes in. It builds related ES6 module bundles using gulp and rollup, and
then rebuilds them as files change.
multibuild benefits:
- Modules are cached between build targets
- Only affected targets are rebuilt when a file changes
- Bundling is simpler and more consistent
Even if you don't have multiple views in your application, multibuild can still be used to
simultaneously build your application bundle and your test bundle.
Installation
$ npm install multibuild
or
$ npm install multibuild --save
Usage
var gulp = require('gulp');
var multiEntry = require('rollup-plugin-multi-entry');
var MultiBuild = require('multibuild');
var rename = require('gulp-rename');
var build = new MultiBuild({
gulp,
targets: [
'app',
'legacy-app',
'app-vendor',
'spec'
],
skipCache: [
'spec'
],
cacheGroups: {
vendored: [
'app-vendor'
]
},
skipResolveCache: ['jquery'],
errorHandler(e) {
if (process.env.NODE_ENV !== 'production') {
console.error(e);
} else {
throw(e);
}
},
entry: (target) => (target === 'spec') ? 'spec/**/*.js' : `src/js/main-${target}.js`,
rollupOptions: (target) => {
var options = {
plugins: [],
format: 'iife',
exports: 'none'
};
if (target === 'spec') {
options.plugins.push(multiEntry({exports: false}));
}
return options;
},
output: (target, input) => {
if (target === 'spec') {
return input
.pipe(rename('spec.js'))
.pipe(gulp.dest('./spec'));
} else {
return input
.pipe(rename(`build-${target}.js`))
.pipe(gulp.dest('./src'));
}
}
});
gulp.task('js', (cb) => build.runAll(cb));
gulp.task('watch', function() {
gulp.watch(['src/js/**/*.js'], (event) => build.changed(event.path));
});
gulp.task('default', ['js', 'watch']);
You can get the name of a task generated for a target with MultiBuild.task
. This can be useful for specifying MultiBuild-generated build tasks as dependencies of your other tasks without having to hard-code the task name.
var generatedTaskName = MultiBuild.task('targetName');
Contributing
We welcome pull requests! Please lint your code using the JSHint configuration in this project.