Giter Club home page Giter Club logo

budo's Introduction

budō

build status stability NPM version Downloads js-standard-style

This is a browserify development server focused on incremental reloading, LiveReload integration (including CSS injection) and other high-level features for rapid prototyping.

To install it globally:

npm install budo -g

Running budo will start a server with a default index.html and incrementally bundle your source on filesave. The requests are delayed until the bundle has finished, so you won't be served stale or empty bundles if you refresh the page mid-update. Examples:

# serve file on port 9966 and open browser
budo index.js --open

# enable LiveReload on HTML/CSS/JS file changes
budo index.js --live

# default html will use src="static/bundle.js"
budo src/index.js:static/bundle.js

# pass some options to browserify
budo index.js --live -- -t babelify

# use HTTPS and enable CORS headers
budo index.js --ssl --cors

# LiveReload public directory without any bundling
# Add all extensions of file types you want to trigger reloads
budo --dir public/ --wg **/*.{html,css,js} --live

Then open http://localhost:9966/ to see the content in action.

By default, budo pretty-prints to terminal with garnish.

See docs for more details and integrations, such as React Hot Module Replacement, Pushstate Servers and HTTPS. PRs/suggestions/comments welcome.

features

At a glance:

  • serves a default index.html
  • fast incremental bundling, suspending the response until the new source is ready
  • watches HTML and CSS files for changes; CSS is injected without reloading the page
  • can emit ndjson logs to use another pretty-printer, like bistre.
  • provides clear error messaging during development in DOM and console
  • supports SSL and can generate a self-signed certificate
  • the rich API allows you to build more complex development tools on top of budo

Below is an example of how syntax errors look during development, using the babelify transform.

docs

usage

NPM

CLI

Details for budo command-line interface.

Usage:
  budo index.js [opts] -- [browserify opts]

Options:
  --help, -h       show help message
  --version        show version
  --port, -p       the port to run, default 9966
  --host, -H       the host, default internal IP (localhost)
  --dir, -d        a path, or array of paths for base static content
  --serve, -s      override the bundle path being served
  --live, -l       enable default LiveReload integration
  --live-port, -L  the LiveReload port, default 35729
  --open, -o       launch the browser once connected
  --pushstate, -P  always render the index page instead of a 404 page
  --base           set the base path for the generated HTML, default to '/'
  --onupdate       a shell command to trigger on bundle update
  --poll=N         use polling for file watch, with optional interval N
  --title          optional title for default index.html
  --css            optional stylesheet href for default index.html
  --ssl, -S        create an HTTPS server instead of HTTP
  --cert, -C       the cert for SSL (default cert.pem)
  --key, -K        the key for SSL (default key.pem)
  --cors           set header to use CORS (Access-Control-Allow-Origin: *)
  --ndjson         print ndjson instead of pretty-printed logs
  --verbose, -v    also include debug messages
  --force-default-index always serve a generated index.html instead of a static one
  --no-stream      do not print messages to stdout
  --no-debug       do not use inline source maps
  --no-portfind    will not attempt auto-portfinding
  --no-error-handler    disable default DOM error handling
  --watch-glob, --wg    glob(s) to watch for reloads, default '**/*.{html,css}'
  --static-options      subarg options to pass to serve-static module

By default, messages will be printed to process.stdout, and --debug will be sent to browserify (for source maps). You can turn these off with --no-stream and --no-debug, respectively.

Everything after -- is passed directly to browserify. Example:

budo index.js --live -- -t [ babelify --extensions .es6 ]

API

The API mirrors the CLI except it does not write to process.stdout by default.

var budo = require('budo')
var babelify = require('babelify')

budo('./src/index.js', {
  live: true,             // setup live reload
  port: 8000,             // use this port
  browserify: {
    transform: babelify   // ES6
  }
}).on('connect', function (ev) {
  console.log('Server running on %s', ev.uri)
  console.log('LiveReload running on port %s', ev.livePort)
}).on('update', function (buffer) {
  console.log('bundle - %d bytes', buffer.length)
})

See API usage for details.

See Also

budō combines several smaller and less opinionated modules.

Also, special thanks to beefy and wzrd which originally inspired budo.

License

MIT, see LICENSE.md for details.

budo's People

Contributors

anandthakker avatar aral avatar ashnur avatar benburrill avatar bendrucker avatar brunoimbrizi avatar chbernat avatar cvan avatar fibo avatar jmckinnell avatar mantoni avatar mattdesl avatar naoyashiga avatar rosszurowski avatar rreusser avatar rtsao avatar scothis avatar sethvincent avatar spacejack avatar steveorevo avatar thibauts avatar thorn0 avatar veggiemonk avatar wbinnssmith avatar wooorm avatar yoshuawuyts avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

budo's Issues

Static file caching

Ran into some odd caching issues today where assets were not the latest as I would expect. May need to tweak ecstatic's cache time.

Watching non JS filetypes

There seems to be a bug or then it's intended behaviour but in my current project I have shaders being compiled via glslify budo does not watch these files. So if I change my index.frag or index.vert file budo does not recompile the bundle.js.

With nodemon you can set extensions to watch for:
-e, --ext ................ extensions to look for, ie. js,jade,hbs.

Onchange commands from CLI

Is there a way from the command line to call a command when the file watchers detect a change?

I want to be able to run linters when budo detects a .js file is changed - but I don't want to add another file watcher to the mix. For example:

budo -- --onchange npm run lint

Live reload and browserify-css

I'm trying to use budo with the browserify-css transform. I use the simple example taken from browserify-css.

/* app.css */
@import url("css/one.css");
@import url("css/two.css");
body {
    background-color: #fff;
}
// index.js
var css = require('./app.css');
console.log(css);

I run with the following command

budo index.js --live -- -t browserify-css

If I make a change to app.css then a reload is triggered. If I make a change to, for example, css/one.css then the log will show

{"time":"2015-09-07T21:01:01.257Z","hostname":"secret","pid":8408,"level":"debug","name":"budo","type":"change","url":"css/one.css"}

but there will be no page reload.

Is it possible to trigger a page reload for changes to css imports? If so then do I need to pass some other options to budo/browserify?

Is there any way to pre-process files and send the output as stdin for live to refresh?

I am trying to think on a way that would allow budo requests to *.less,*.sass files to activate the pre-processor, run the output through auto-prefixer and render the outcome as text, directly injected into a page without the need to generate a physical file, basically the same as it does by default with javascript files.

Would that be somehow possible to achieve with budo?
The way it works is genius, but I only missing CSS pre-processors to really improve my workflow.

Ideally this would be achievable if the reload method accepted the file contents instead of its path only, like:

main.less

body {
    background: red;
    p {
        color: green;
    }
}

main.less compiled into .css and made available for rendering in-browser

app
  .watch('*.less', { interval: 300, usePolling: true })
  .live()
  .on('watch', function(type, file) {
    if (path.extname(file) === '.less') {
        less('./main.less').then(function (css) { 
            app.reload('main.less', css); //css => body { background: red; } p { color: green; }
        })
    }
  })

Thanks a lot

It works without the need of `example/index.html` almost

Actually, initially i was surprised why there is needed index.html when it use simple-html-index. But yea, almost. Javascript works, but it not sets the style. (lib/server.js#L172)

I think that it should also servers default css. I mean... basically I understand what it happens under the hood, without looking the code deeply. For example, if we have

 budo example/other.js:foo.js --live --dir example | garnish

It browserifies other.js to foo.js (or whatever you defined it),
mark it as "bundle"

info browserify: /foo.js 511ms (bundle)

and keep it in memory and start listening on index.html route (if we pass --dir, im not sure), then that route use simple-html-index which use that "bundle" and serves that default index, without writing the bundle and index.html to disk. But it also would be useful to have default styles endpoint. And yea, i see that we can change this behaving if we write our index.html file, but ye.

Talking about next branch.

name

might rename to something else

hmm.

in the vein of wzrd: mystc, knght, wrlck, dwrf, spllcrft, wtchcrft, wnd, crssbw...

other random stuff, trying to keep it short:
misty, spdstr, spnstr, spit, wzkid, wilee (as in Wile E.), watches, warpdrive, spins, serves, yumi, daikyu, kyudo, budo

how to bundle js with budo?

I use ' node_modules/.bin/budo main.js -- -o bundle7.js ' , but cannot output anything. Can anyone help me?

pushState support

Provide push state support similar to wzrd pushstate option i.e. always serve index.html for any file not found.

wzrd app.js --pushstate

Sourcemap header?

Should budo expose a header like this to indicate where a source map exists? Running 3.0.0 doesn't seem to have Google Chrome loading the sourcemap anymore.

X-SourceMap: /path/to/file.js.map

Watchify as direct dependency

In the first version of budo it made a bit of sense to not bundle watchify as a direct dependency, since I was using npm-execspawn to spawn a local/global version.

But now it would probably make more sense to depend directly on watchify and only use that local dependency. This would clean up some code / confusion / problems with global versions.

adds empty `style` tag in head (even if custom index is used)

just using this index, and it seems that when load it budo adds empty style tag. Cant realize from where and why.

<!doctype html>
<html>
<head>
  <title>foo</title>
  <meta charset="utf-8">
  <link rel="stylesheet" href="main.css">
</head>
<body>
  <script src="bundle.js"></script>
</body>
</html>

--live doesn't work with docker

fantastic library!

I am trying to make it work inside a docker container and it detects the file change but my browser does not refreshing itself. I assume it's something to do with tiny-lr and maybe some unix sockets issue between the container and my laptop. i'll investigate as soon as possible. here is the repo to reproduce my issue
https://github.com/oren/budo-template

(i might need to pass -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix to my run command)

Outfile option not being passed to Browserify.

Hi, so I know you have taken out the --outfile option from Budo in v3.0 (curious as to why?) but is there anyway to keep passing that option to Browserify? I have tried budo app/app.js:index.js -- -t babelify -o index.js but that does not seem to work. Thanks for any insight you can provide.

API (Gulp / Grunt)

Would be nice to expose a sort of programmatic API for things like gulp/grunt to just call budo() and reap some of its benefits .. will think about this.

entry mapping

In [email protected] you can rename the bundle like so:

budo src/index.js:static/bundle.js

This will browserify src/index.js but serve it as static/bundle.js.

But this doesn't work with multiple entries and zsh glob expansion. So a flag is needed:

budo tests/*.js other.js --serve static/bundle.js

I'm open to other names than --serve .. Maybe --rename or --dest.

inject LiveReload script into existing index.html?

A LiveReload script is included in the bare-bones index.html that is generated when no index.html exists in the directory. When there is an index.html file in the directory, that gets served instead. It would be convenient if the LiveReload script were injected into this existing index.html.

b.transform opts

When creating a custom bundler, you can pass opts to b.transform() like global: true.

This might be possible with 'global-transform' option but it is not well documented via browserify API.

Another option might be to allow a custom bundler object passed via budo API, in which case all other options are ignored.
hmm

see discssion #30

Enable LiveReload on non-bundle files

If I have a document that loads the bundle and some other dependent, non-browserified JS file:

<!doctype html>
<html>
  <head>
    <script src="static-file.js"></script>
    <script src="bundle.js"></script>
  </head>
  <body>
  </body>
</html>

I want LiveReload to pick up changes to static-file.js and reload the page. Can you think of a clever way to do this with budo?

Subarg syntax

Should support subarg syntax in CLI e.g. for transforms

feature: short hand for entry point

Should support the following cases:

budo . | garnish
budo .:bundle.js | garnish
budo :bundle.js | garnish

Which resolves to the entry point of ./package.json with optional entry mapping for entry URL. If no package exists, use ./index.js, if that fails, throw an error.

Note: currently in v5, not passing any entries will behave a bit differently. It will not spin up any browserify instances and will make budo act like a plain http server with LiveReload.

budo | garnish

--debug by default?

beefy uses -d by default to enable source maps... not sure if this is the way to go.

But I find myself adding it every time i'm using budo for dev

pending bundle

Handling "pending" state as discussed in watchify#180 to avoid getting served stale bundles or empty files. Usually this timeout is short, between 0 and 600 ms.

A proper fix might involve using watchify's programmatic API rather than spawning a child process.

Another solution for now might be to avoid serving the bundle file until it's length is not 0 (giving up after a few tries, in case the file is legitimately empty). Nope; only gets truncated after file writing begins (i.e. after 600 ms).

Other ideas?

5.0.0

Budo is growing into a more general-purpose tool than it was when it first started, so I'm looking to create a better UX. Some planned changes:

  • add --open option which launches the browser; no need for opnr anymore
  • use auto-portfinding in both CLI and API
  • use auto-portfinding for live reload server #34
  • include a --no-portfind or { portfind: false } option to disable it
  • include API aliases for dash-case names like browserify API does
  • force all browserify options to be after a full stop -- to fix #30
  • explore proxying / pushstate options #45 #41
  • errorify by default ?

Feature proposal; proxying

Hi @mattdesl, and thanks a bunch for budo! I really like it 😁

I would also like to use it for work, but have a challenge. Our "API" at work is this complicated distributed mess. It's not really feasible to run all the required pieces on a laptop. So I need to "connect" to an environment to get data. My proposal is; configurable proxy paths for budo.

There are several ways to go about it, but the basics would be to configure a local path to a proxy server;

budo app.js --proxy /api:http://localhost:8080/api

Translates to; any calls to http://budo-dev-server/api should be proxied to http://localhost:8080/api

This way the proxied-to server can be any arbitrary server, and we avoid baking any knowledge about how the proxy works into budo. I have lots of requirements for my proxy, it needs to perform auth, logging etc. But all this logic can go into my localhost:8080 server allowing me to connect to my complex backend from budo 😄

error handling

How to handle syntax errors in code while bundling.

Some issues worth investigating:

  • errors appear printed in console (due to this) - not bad but could be written to document.body
  • with --live the error is not printed to terminal console

feature: write all router paths to disk

It might be cool if budo's routes were able to be persisted to disk. This would allow users to prototype using a live-reloading environment, and once they're happy with the results store the output to disk and deploy it to GH-pages.

Currently the following modules are available to do this:

Usage looks like this:

const toServer = require('wayfarer-to-server')
const toFs = require('wayfarer-to-fs')
const wayfarer = require('wayfarer')

const router = toServer(wayfarer())
router.on('/', {
  get: (req, res) => fs.createReadStream(__dirname + '/index.html').pipe(res))
})

toFs(router, __dirname + '/dist', (err) => {
  if (err) throw err
})

What do you think of adding such functionality to budo?

issues when spacing in directory

I have a filesystem with a space in my path: /Volume/Case Sensitive/...

And when I try to use --outfile:

{ [Error: EISDIR, open '/Volumes/Case'] errno: -21, code: 'EISDIR', path: '/Volumes/Case' }

Regards,
gre

how do I turn off debug lines in console?

I'm seeing a ton of lines like this in my console

{"time":"2015-07-31T21:36:54.978Z","hostname":"localhost","pid":24816,"level":"info","name":"budo","url":"/sample4.png","type":"static"}

How do I turn these off? I saw the option --no-debug but I need the source-maps. I couldn't find any mention of setting the debug level in the docs folder.

Multiple ports for live reload

Hi !

What do you think about using getport for --live the same way you do it for the server port. It would be useful when having multiple budo instances running at the same time to have an auto live port pick from budo, for now it's either 35729 or --live-port but it won't work well if we select the same port multiple times (or if we don't select --live-port at all multiple times).

I'm currently working on a PR to add this feature (see this commit) but I have a hard time finding where the live reload <script> tag is inserted in the html, could you give me some pointers?

Thanks for your work on this cool lib, I'm using it a lot lately :)

Cheers

split out modules for watchify / server integration

Eventually it would be good to pull the "core" of budo out into its own module like watchify-server or something. This would make it more useful for non-static sites, specific bundler setups, and local servers like hihat.

open to suggestions

Features / TODOs

Spitballing some TODOs. See the alpha branch.

  • better error handling, maybe in the style of beefy (showing error in browser)
  • unit tests
  • testing tmp directory on Linux/Windows and other environments
  • making --path option more robust, maybe rename to --dir ?
  • decouple --live from budo-chrome so user has to specify explicitly if they want LiveReload in addition to script injection
  • handling entry mapping for tmp outfile option so user can specify something other than bundle.js
  • add option to include LiveReload in script or index.html ?
  • move budo-chrome out of "core" budo module

use watchify programmatically

pros:

  • handle pending bundles easily #19
  • programmatic API can accept objects for transforms/plugins/etc
  • no need to chokidar the bundle.js file
  • might simplify some code and avoid potential cross-platform woes with spawning child processes
  • pretty-printing timing
  • no need for temp dir

cons:

  • introduces some peer dependency woes
  • for e.g. maybe pending feature should be progressively enhanced so this doesn't outright break on watchify 2.x

i think this is the way to go. roadmap:

  • watchify resolve algorithm (Beefy's is currently not working for me)
  • handle pending so you are never served a stale/empty bundle
  • remove the debounce by default (seems unnecessary in my tests) but allow user to set --delay
  • change watcher to only look for HTML/CSS (no need for additional watchers) - breaking change
  • add on('update') to receive bundle events for LiveReactLoad and such
  • pretty-print time updates instead of using watchify's
  • if no --outfile is specified, just pipe the contents directly to the request
  • docs: encourage use without --outfile since there is no longer any temp file shenanigans
  • remove temp dir stuff
  • explore outpipe and determine whether it's the best way forward for exorcist / uglify / etc
  • update demos / examples / budo-chrome / tests

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.