The API mirrors the CLI except you must provide a stream
for logging, and it provides a couple extra options.
Sets up a new instance of budo
, where entry
is a path or or array of paths.
entry
can be optional -- if no entry paths are given, budo simply acts as a static HTTP server with optional LiveReload.
The return value is an event emitter.
Examples:
var budo = require('budo')
var babelify = require('babelify')
budo('./src/index.js', {
live: true, // live reload
stream: process.stdout, // log to stdout
port: 8000, // use this as the base port
browserify: {
transform: babelify // use ES6
}
}).on('connect', function(ev) {
//...
})
All settings are optional.
port
(Number)- the base port to use for the development server (default
9966
)
- the base port to use for the development server (default
livePort
(Number)- the base port to use for the LiveReload server (default
35729
)
- the base port to use for the LiveReload server (default
portfind
(Boolean)- whether to use portfinding to find the next available ports (default
true
)
- whether to use portfinding to find the next available ports (default
host
(String)- the host to listen on (default
'localhost'
)
- the host to listen on (default
live
(Boolean|String|Object)- whether to set up a default LiveReload integration (see LiveReload)
- if a string is specified, only filenames matching that glob will trigger LiveReload events
- object will be passed along to the
live()
function
cors
(Boolean)- Set the header to use CORS (
Access-Control-Allow-Origin: *
)
- Set the header to use CORS (
ssl
(Boolean)- Creates an HTTPS server instead of HTTP
cert
(String)- The SSL public certificate file path (default
'cert.pem'
)
- The SSL public certificate file path (default
key
(String)- The SSL private key file path (default
'key.pem'
)
- The SSL private key file path (default
watchGlob
(Array|String)- a glob string or array of glob strings to use as the default when
opts.live
is specified, or whenlive()
is called without arguments - defaults to
'**/*.{html,css}'
- a glob string or array of glob strings to use as the default when
open
(Boolean)- whether to launch the browser (default
false
)
- whether to launch the browser (default
dir
(String|Array)- a folder or list of folders to use as the base path for static assets (default
process.cwd()
) - a default
index.html
will be searched in the firstdir
folder
- a folder or list of folders to use as the base path for static assets (default
stream
(writable stream)- a writable stream like
process.stdout
for ndjson logging (defaultundefined
)
- a writable stream like
debug
(Boolean)- whether to enable source maps from browserify (default
true
)
- whether to enable source maps from browserify (default
serve
(String)- if specified, the
<script src>
will use this path; defaults to first entry filename
- if specified, the
title
(String)- an optional
<title>
to use for the defaultindex.html
- an optional
css
(String)- an optional
<link href>
stylesheet URL to use for the defaultindex.html
- an optional
browserify
(Object)- an object of options passed to browserify
browserifyArgs
(Array)- an array of command-line arguments passed to browserify
- if specified, this will be used to construct the new instance
middleware
(Array|Function)- an optional function or array of
fn(req, res, next)
functions for the server which is run before other routes; usingconnect
style middleware
- an optional function or array of
errorHandler
(Boolean|Function)- whether to include a DOM-based reporter build/syntax errors (default
true
) - can be a
reporter(err)
function which takes an Error and returns the new bundle contents
- whether to include a DOM-based reporter build/syntax errors (default
forceDefaultIndex
(Boolean)- whether to always generate index.html instead of serving a static file, if one is present (default:
false
)
- whether to always generate index.html instead of serving a static file, if one is present (default:
pushstate
(Boolean)- enable push state support, which defaults 404 routes to the index (default
false
) - Recommended you also add something like
<base href="/">
to your HTML<head>
- enable push state support, which defaults 404 routes to the index (default
base
(Boolean|String)- add
<base href="/">
to the generated default HTML page if set to true, or uses the specified path if it's a string
- add
verbose
(Boolean)- also print
'debug'
level messages to garnish; such as the pending state of the bundle and how many files changed in the last update.
- also print
defaultIndex
(Function)- a function
fn(params, req)
that returns a Readable stream, takes the followingparams
:
{ entry: opts.serve, title: opts.title, css: opts.css }
- defaults to simple-html-index
- a function
staticOptions
(Object)- an object passed to serve-static options
- this object is merged with the default options:
{ cacheControl: false }
Runs budo as a command-line tool, from the specified array of arguments and an optional opts
object for overrides. The options are the same as above.
This method returns the budo
instance, or null
if the args
command includes --version
or --help
.
For example, running the following script from the command line would behave like budo, but with some added features by default:
var args = process.argv.slice(2)
var babelify = require('babelify')
var budo = require('budo').cli(args, {
// additional overrides for our custom tool
pushstate: true,
browserify: {
transform: babelify
}
})
Note: In the CLI, anything after --
gets passed to opts.browserifyArgs
. Whenever opts.browserifyArgs
is specified, browserify will be created with browserify/bin/args instead of its usual constructor.
Closes the budo instance and its associated server/watcher/etc.
If live reload is enabled (i.e. through opts.live
or live()
), this will send a LiveReload event to the given path and then trigger the "reload"
event.
If path
is undefined, this is treated as a hard page reload.
If live
was not specified, you can manually enable the LiveReload server with the specified opt
options:
plugin
if true, the HTML will not have the LiveReload script injected into it, default falsepath
the script URL for the LiveReload client, defaults to'/budo/livereload.js'
include
a path or array of paths to files that should be added to the LiveReload client, defaults to an empty arraycache
whether to cache the LiveReload client file (faster) or re-bundle it on each request (easier to develop LiveReload clients), defaulttrue
debug
whether to add source maps to the bundled LiveReload client, defaultfalse
expose
whether to exposerequire('budo-livereload')
on the global context, default false
See LiveReload for details.
If live
was not specified, you can manually enabe chokidar's file watching with the specified globs
(array or string) and options.
globs
defaults to watching **/*.{html,css}
.
See LiveReload for details.
Called when the server is closed.
Called on a fatal error, like not being able to create the server.
Called once the budo server connects. The callback is passed an event
object that looks like this:
{
uri: 'http://localhost:9966/', // served URI
serve: 'bundle/entry%20file.js' // the URL path for our entry file
dir: 'app', // the working directory being served
host: 'localhost', // defaults to localhost
port: 9966, // the port we're running on
entries: [ 'entry file.js' ], // an array of entry file paths
server: HTTPServer // the HTTP/HTTPS server
}
Note: The dir
field might be a string or array, depending on user input.
Called when the source changes and begins the new incremental reload.
Called after the 'pending'
event, once the bundle has finished reloading. It is passed the following:
fn(contents, changedDependencies)
Where contents
is a Buffer with the new bundle source, and changedDependencies
is an array of dependencies that were changed since last bundle. On the initial update, this array will be empty.
Called after LiveReload has triggered a new event. The listener should have the signature fn(file)
, where file
is the path being reloaded.
This is only called when opts.live
is specified, or after b.reload(file)
is manually called.
Called after a file watch event with the signature: fn(event, file)
, where event
could be "add", "change", "unlink", etc and file
is the file path being changed.
If opts.live
was not specified, and b.watch()
was never set up, this event will not get called.
If you use budo.cli()
you can create a simple budo CLI wrapper with some pre-defined options and configurations, such as this dev.js
script:
require('budo').cli(process.argv.slice(2), {
port: 8080,
open: true,
live: true
})
Now you can run dev.js
with regular budo CLI flags:
node dev.js src/index.js:bundle.js -- -t babelify
A static HTTP server with no browserify capabilities, LiveReload integration, and a custom glob to watch for.
budo({
live: true,
watchGlob: '{src,examples}/**/*.{html,css,js}'
})
Using middleware
to create a small non-static server. This can be an array of functions, or just a single function.
var url = require('url')
var app = budo('./app.js', {
middleware: function (req, res, next) {
if (url.parse(req.url).pathname === '/api') {
res.statusCode = 200
res.end('hello world')
} else {
// fall through to other routes
next()
}
}
})
Let's say your dev server should map localhost:9966/about
and localhost:9966/about/
to an HTML file called localhost:9966/about.html
. You can specify options to the underlying static middleware and remove trailing slashes like so:
// dev.js
var slashes = require('connect-slashes')
require('budo').cli(process.argv.slice(2), {
middleware: slashes(false),
staticOptions: {
index: false,
extensions: [ 'html', 'htm' ]
}
})
Now you can run the above dev.js
file just like you would budo:
node dev.js src/index.js:bundle.js --live -- -t babelify
If you need more control over the bundler, such as adding external()
, you can use a browserify plugin.
For example, to ignore large files when browserifying the unicode package, write a dev.js
script like this:
require('budo').cli(process.argv.slice(2), {
browserify: {
plugin: bundler => bundler.ignore('unicode/category/So')
}
})
Now, you can call this dev.js
script from node just like you would with budo CLI:
node dev.js src/index.js:bundle.js --live -- -t babelify
Here is a more complex example, where require('os-arch')
returns the OS architecture of whatever machine is running budo.
const os = require('os');
const path = require('path');
const fromString = require('from2-string');
require('budo').cli(process.argv.slice(2), {
browserify: {
plugin: bundler => {
// A "dynamic" module from Node.js
// Keep in mind the result of the stream is cached by browserify!
const moduleName = 'os-arch';
// Give it a fake file name in node_modules
const moduleFile = path.resolve(process.cwd(), 'node_modules', moduleName, `${moduleName}.js`);
const message = os.arch();
const stream = fromString(`module.exports = ${JSON.stringify(message)}`);
bundler.exclude(moduleName);
bundler.require(stream, { file: moduleFile, expose: moduleName });
}
}
});
Budo doesn't need a Grunt or Gulp specific plugin to work. Instead, if you wish to use Grunt or Gulp, it is safer to require budo
directly, and wrap it within your task runner:
var gulp = require('gulp')
var budo = require('budo')
//start our local development server
gulp.task('dev', function(cb) {
budo('index.js', {
stream: process.stdout
}).on('connect', function(ev) {
// do something on connect ...
})
.on('exit', cb)
})
Now running gulp dev
will spin up a server on 9966, spawn watchify, and incrementally rebundle during development. It will stub out an index.html
and serve the browserified contents of index.js
and write pretty-printed logs to stdout
.