buddy(1)
buddy(1) is a build tool for js/css projects. It helps you manage third-party dependencies, compiles source code from higher order js/css languages (coffeescript/stylus/less), automatically wraps js files in module definitions, statically resolves module dependencies, and concatenates (and optionally compresses) all souces into a single file for more efficient delivery to the browser.
Current version: 0.5.4
[the 0.5.x branch is not backwards compatible with earlier versions. See Change Log below for more details]
Installation
Use the -g global flag to make the buddy(1) command available system-wide:
$ npm -g install buddy
Or, optionally, add buddy as a dependency in your project's package.json file:
{
"name": "myproject",
"description": "This is my web project",
"version": "0.0.1",
"dependencies": {
"buddy": "0.5.0"
},
"scripts": {
"install": "buddy install",
"build": "buddy build",
"deploy": "buddy deploy"
}
}
...then install:
$ cd path/to/project
$ npm install
Usage
$ cd path/to/project
$ buddy install
$ buddy build
$ buddy -c build
$ buddy -l build
$ buddy watch
$ buddy deploy
$ buddy --help
$ npm run-script install
$ ./node_modules/buddy/bin/buddy install
Configuration
The only requirement for adding buddy support to a project is the presence of a buddy.js file in your project root:
exports.build = {
js: {
sources: ['a/coffeescript/source/directory', 'a/js/source/directory'],
targets: [
{
input: 'a/coffeescript/or/js/file',
output: 'a/js/file/or/directory',
targets: [
{
input: 'a/coffeescript/or/js/file',
output: 'a/js/file/or/directory'
}
]
},
{
input: 'a/coffeescript/or/js/directory',
output: 'a/js/directory',
modular: false
}
]
},
css: {
sources: ['a/stylus/directory', 'a/less/directory', 'a/css/directory'],
targets: [
{
input: 'a/stylus/less/or/css/file',
output: 'a/css/file/or/directory'
},
{
input: 'a/stylus/less/or/css/directory',
output: 'a/css/directory'
}
]
}
}
exports.dependencies = {
'a/vendor/directory': {
sources: [
'popeindustries/browser-require',
'library@version'
],
output: 'a/js/file'
},
'a/source/directory': {
sources: [
'username/repo',
'username/repo#a/file/or/directory|another/file/or/directory',
'a/file/or/directory'
]
}
}
exports.settings = {
plugins: {
js: {
compilers: ['a/file', 'another/file'],
compressor: 'a/file',
linter: 'a/file',
module: 'amd'
},
css: {
compilers: ['a/file', 'another/file'],
compressor: 'a/file',
linter: 'a/file'
}
}
}
Concepts
BUILD
Project Root: The directory from which all paths resolve to. Determined by location of the buddy.js configuration file.
Sources: An array of directories from which all referenced files are retrieved from. Note: A js module's id is derived from it's relative path to it's source directory.
Targets: Objects that specify the input and output files or directories for each build. Targets are built in sequence, allowing builds to be chained together. Note: A js target can also have nested child targets, ensuring that dependencies are not duplicated across related builds.
Target parameters:
-
input: file or directory to build. If js (or equivalent) file, all dependencies referenced will be concatenated together for output.
If directory, all compileable files will be compiled, wrapped in module definitions (js), and output to individual js/css files.
-
output: file or directory to output to.
-
targets: a nested target that prevents the duplication of source code with it's parent target.
-
modular: a flag to prevent js files from being wrapped with a module definition.
MODULES
Each js file is wrapped in a module declaration based on the file's location. Dependencies (and concatenation order) are determined by the use of require()
statements:
var lib = require('./my/lib');
var SomeClass = require('../someclass');
var util = require('utils/util');
lib.doSomething();
var something = new SomeClass();
util.log('hey');
Specifying a module's public behaviour is achieved by decorating an exports
object:
var myModuleVar = 'my module';
exports.myModuleMethod = function() {
return myModuleVar;
};
...or overwriting the exports
object completely:
function MyModule() {
this.myVar = 'my instance var';
};
MyModule.prototype.myMethod = function() {
return this.myVar;
};
module.exports = MyModule;
Each module is provided with a module
, exports
, and require
reference.
When require()
-ing a module, keep in mind that the module id is resolved based on the following rules:
- packages begin at the root folder specified in buddy.js > js > sources:
'Users/alex/project/src/package/main.js' > 'package/main'
- uppercase filenames are converted to lowercase module ids:
'my/package/Class.js' > 'my/package/class'
See node.js modules for more info on modules.
NOTE: require
boilerplate needs to be included on the page to enable module loading. It's recommended to install
a library like popeindustries/browser-require.
DEPENDENCIES
Dependency resources are installed from local locations or remotely from Github.
Sources: An array of local or remote resource locations.
-
destination: each group of sources will be installed to the project relative location specified.
-
identifier: github username/repo
identifiers are preferred, but it is also possible to use identifiers from the bower package manager: 'jquery', 'backbone', 'underscore'
-
versioning: github sources can specify a version by appending @
and a npm-style symantic version: '*', '1.2.3', '1.x', '~1.2.0', '>=1.2.3'
-
resources: specific resources can be specified by appending #
and a list of |
separated relative file or directory locations: 'username/repo#a/file/or/directory|another/file/or/directory'
Output: A file destination to concatenate and compress the source contents. The order of sources determines the content order.
Examples
Copy project boilerplate from a local directory:
exports.dependencies = {
'.': {
sources: ['../../boilerplate/project']
}
}
Grab js dependencies to be installed and packaged for inclusion in html:
exports.dependencies = {
'libs/vendor': {
sources: [
'popeindustries/browser-require',
'jquery@1.8.2'
],
output: 'www/assets/js/libs.js'
}
}
Grab sources to be referenced in your builds:
exports.dependencies = {
'libs/src/css': {
sources: [
'visionmedia/nib#lib/nib'
]
}
}
Compile a library, then reference some library files in your project:
exports.build = {
js: {
sources: ['libs/src/coffee', 'libs/js', 'src'],
targets: [
{
input: 'libs/src/coffee',
output: 'libs/js'
},
{
input: 'src/main.js',
output: 'js/main.js'
}
]
}
}
Compile a site with an additional widget using shared sources:
exports.build = {
js: {
sources: ['src/coffee'],
targets: [
{
input: 'src/coffee/main.coffee',
output: 'js',
targets: [
{
input: 'src/coffee/widget.coffee',
output: 'js'
}
]
}
]
}
}
Changelog
0.5.4 - November 23, 2012
- regression fix for clean command
- improved .buddy-filelog force clean
- improved notifications for install and clean commands
0.5.3 - November 23, 2012
- refactored install command behaviour; no longer uses git operations, changed syntax for specifying version ('@') and resources ('#'), added ability to list several resources [breaking change]
- .buddy-filelog now stores relative paths for compatibility on different systems
- file deletions limited to resources under the project root
0.5.2 - Novemver 20, 2012
- added watch command; handle add, remove, and change of source files
0.5.1 - Novemver 14, 2012
- added clean command to remove all generated files
- added hidden .buddy-filelog file for tracking files changes between sessions
- fix for false-negative module wrapping test
0.5.0 - November 13, 2012
- compile command renamed to build [breaking change]
- changed module naming for compatibility with recent versions of Node.js (camel case no longer converted to underscores) [breaking change]
- changed configuration file type to 'js' from 'json'; added dependencies and settings [breaking change]
- changed configuration target parameters to input/output from in/out [breaking change]
- changed configuration target parameter to modular from nodejs [breaking change]
- concatenated js modules no longer self-booting; need to
require('main');
manually [breaking change] - require boilerplate no longer included in generated source; install git://github.com/popeindustries/browser-require.git or equivalent [breaking change]
- removed watch command (temporarily) [breaking change]
- added install command and project dependency management
- added plugin support for compilers, compressors, linters, and modules; added support for custom plugins
- added code linting
- all errors now throw
- complete code base refactor
License
Copyright (c) 2011 Pope-Industries <alex@pope-industries.com>
Permission is hereby granted to do whatever you want with this software, but I won't be held responsible if something bad happens.