What is broccoli?
Broccoli is a JavaScript build tool that allows you to define a build pipeline using a series of plugins. It is particularly well-suited for front-end development, enabling tasks such as file transformation, concatenation, and minification.
What are broccoli's main functionalities?
File Transformation
This code demonstrates how to use Broccoli to transform files. It uses the Funnel plugin to include only JavaScript files from the 'app' and 'vendor' directories and then merges these trees into a single output tree.
const Broccoli = require('broccoli');
const Funnel = require('broccoli-funnel');
const MergeTrees = require('broccoli-merge-trees');
let appTree = new Funnel('app', {
include: ['**/*.js']
});
let vendorTree = new Funnel('vendor', {
include: ['**/*.js']
});
let finalTree = new MergeTrees([appTree, vendorTree]);
module.exports = finalTree;
File Concatenation
This code demonstrates how to concatenate JavaScript files using the broccoli-concat plugin. It takes all JavaScript files in the 'app' directory and concatenates them into a single file, 'app.js', in the 'assets' directory.
const Broccoli = require('broccoli');
const Concat = require('broccoli-concat');
let appJs = new Concat('app', {
outputFile: '/assets/app.js',
inputFiles: ['**/*.js'],
sourceMapConfig: { enabled: true }
});
module.exports = appJs;
File Minification
This code demonstrates how to minify JavaScript files using the broccoli-uglify-sourcemap plugin. It takes all JavaScript files in the 'app' directory and minifies them, with source maps enabled.
const Broccoli = require('broccoli');
const UglifyJS = require('broccoli-uglify-sourcemap');
let appJs = new UglifyJS('app', {
mangle: true,
compress: true,
sourceMapConfig: { enabled: true }
});
module.exports = appJs;
Other packages similar to broccoli
gulp
Gulp is a toolkit for automating painful or time-consuming tasks in your development workflow. It uses a code-over-configuration approach, making it flexible and easy to use. Compared to Broccoli, Gulp has a larger ecosystem and more plugins available.
webpack
Webpack is a module bundler that takes modules with dependencies and generates static assets representing those modules. It is highly configurable and supports a wide range of plugins and loaders. Webpack is more powerful and complex compared to Broccoli, making it suitable for larger projects.
grunt
Grunt is a JavaScript task runner that automates repetitive tasks like minification, compilation, unit testing, and linting. It uses a configuration-over-code approach, which can be less flexible but easier to understand for beginners. Grunt has been largely superseded by Gulp and Webpack in recent years.
Broccoli
Note April 7, 2014: There was a recent data loss issue on OS X in
Broccoli and several plugins. Check to see if you're
affected.
A fast, reliable asset pipeline, supporting constant-time rebuilds and compact
build definitions. Comparable to the Rails asset pipeline in scope, though it
runs on Node and is backend-agnostic. For background and architecture, see the
introductory blog post.
For the command line interface, see
broccoli-cli.
This is 0.x beta software.
Installation
npm install --save-dev broccoli
npm install --global broccoli-cli
Getting Started
Check out
broccoli-sample-app.
Brocfile.js
A Brocfile.js
file in the project root contains the build specification. It
should export a tree which may simply be the directory path (as a string). To
build more advanced output trees you may want to use some of the plugins listed
below.
The following would export the app/
subdirectory as a tree:
module.exports = 'app'
Alternatively, the following would export the app/
subdirectory as appkit/
:
var pickFiles = require('broccoli-static-compiler')
module.exports = pickFiles('app', {
srcDir: '/',
destDir: 'appkit'
})
Plugins
More plugins may be found under the broccoli-plugin
keyword on npm.
Running Broccoli, Directly or Through Other Tools
Helpers
Shared code for writing plugins.
Plugin API Specification
Broccoli defines a single plugin API: a tree. A tree object represents a tree
(directory hierarchy) of files that can be regenerated on each build.
By convention, plugins will export a function that takes one or more input
trees, and returns an output tree object.
A tree object must supply two methods that will be called by Broccoli:
tree.read(readTree)
The .read
method must return a path or a promise for a path, containing the
tree contents.
It receives a readTree
function argument from Broccoli. If .read
needs to
read other trees, it must not call otherTree.read
directly. Instead, it must
call readTree(otherTree)
, which returns a promise for the path containing
otherTree
's contents. It must not call readTree
again until the promise
has resolved; that is, it cannot call readTree
on multiple trees in
parallel.
Broccoli will call the .read
method repeatedly to rebuild the tree, but at
most once per rebuild; that is, if a tree is used multiple times in a build
definition, Broccoli will reuse the path returned instead of calling .read
again.
The .read
method is responsible for creating a new temporary directory to
store the tree contents in. Subsequent invocations of .read
should remove
temporary directories created in previous invocations.
tree.cleanup()
For every tree whose .read
method was called one or more times, the
.cleanup
method will be called exactly once. No further .read
calls will
follow .cleanup
. The .cleanup
method should remove all temporary
directories created by .read
.
Security
- Do not run
broccoli serve
on a production server. While this is
theoretically safe, it exposes a needlessly large amount of attack surface
just for serving static assets. Instead, use broccoli build
to precompile
your assets, and serve the static files from a web server of your choice.
Get Help
- IRC:
#broccolijs
on Freenode - Twitter: mention @jo_liss with your question
- GitHub: Open an issue on a specific plugin repository, or on this
repository for general questions.
License
Broccoli was originally written by Jo Liss and is
licensed under the MIT license.