
Research
/Security News
9 Malicious NuGet Packages Deliver Time-Delayed Destructive Payloads
Socket researchers discovered nine malicious NuGet packages that use time-delayed payloads to crash applications and corrupt industrial control systems.
budo-express
Advanced tools
Get client-side code bundling and automagical live-reloading working in your Express or Koa app, in 5 minutes!
This library integrates a Budo development server into your Express or Koa application. It uses Browserify for bundling, and LiveReload for page reloading. It combines really well with nodemon, for auto-restarting your server process too!
Because this package doesn't rely on any generators or boilerplates, you can easily integrate it into your existing Express or Koa application.
This library uses Browserify, which is a bundler just like Webpack - however, Browserify is much simpler to understand and configure. It can do the same things as Webpack can, and you won't need Webpack when using Browserify. It's actually been around for longer than Webpack!
Licensed under either the WTFPL or CC0, at your choice. In practice, that means it's more or less public domain, and you can do whatever you want with it. Giving credit is not required, but still very much appreciated! I'd love to hear from you if this module was useful to you.
Creating and maintaining open-source modules is a lot of work. A donation is also not required, but much appreciated! You can donate here.
Because budo-express is meant to integrate into your own Express app, it's exposed as a library rather than a command-line utility.
You simply start by creating your own "binary", something like bin/server.js, and then call budo-express from there, handing it your Express app as an argument:
"use strict";
const budoExpress = require("budo-express");
const path = require("path");
budoExpress({
port: 3000,
app: require("../src/server/app"),
basePath: path.join(__dirname, ".."),
entryFiles: "src/client/index.jsx",
staticPath: "public",
bundlePath: "js/bundle.js",
livereloadPattern: "**/*.{css,html,js,svg}",
browserify: {
extensions: [".jsx"],
transform: [
["babelify", {
presets: ["@babel/preset-env", "@babel/preset-react"],
}]
]
}
});
(Don't worry about all those options for now - they're all explained below!)
And in your src/server/app.js -- note that you never call app.listen, and you export your app instead:
"use strict";
const express = require("express");
let app = express();
// ... your Express app stuff goes here ...
module.exports = app;
Now you simply run:
NODE_ENV=development node bin/server.js
... and that's it! You now have a fully-functioning development server, that:
src/client/index.jsx into public/js/bundle.js.css, .html, .js, or .svg files in the public/ folder change.There's only one thing missing; your server process won't auto-restart when your server code changes. That's easy to fix, when you have nodemon installed:
NODE_ENV=development nodemon bin/server.js
(Note how we've just changed node to nodemon, and that's it!)
The browserify option accepts any kind of valid Browserify configuration.
So for example, if we want to add support for CSS modules and nested CSS, we just install icssify and postcss-nested, and do this in our bin/server.js:
"use strict";
const budoExpress = require("budo-express");
const path = require("path");
budoExpress({
port: 3000,
app: require("../src/server/app"),
basePath: path.join(__dirname, ".."),
entryFiles: "src/client/index.jsx",
staticPath: "public",
bundlePath: "js/bundle.js",
livereloadPattern: "**/*.{css,html,js,svg}",
browserify: {
extensions: [".jsx"],
plugin: [
["icssify", {
before: [ require("postcss-nested")() ]
}]
],
transform: [
["babelify", {
presets: ["@babel/preset-env", "@babel/preset-react"],
}]
]
}
});
Note the added plugin list with icssify; that's the only difference.
Of course, we don't want to run a development server when we're really deploying our app. And when we're running it in production, we need a 'real' generated bundle, not just one that the development server generates on-the-fly.
There's only two steps needed to run your app in production. Step one is to generate the bundle:
BUDO_BUILD=1 node bin/server.js
Note how we're just running the same 'binary' again, but with a different environment variable. This tells budo-express that we want to generate a bundle instead. This doesn't require any extra configuration; it'll use the configuration we've specified in bin/server.js!
The second step is to actually run your application, but without the development server sitting in front of it:
node bin/server.js
That's it! We just leave off the environment variables, and it will default to production mode. Nothing will be auto-reloaded, budo-express will get out of the way, and all you're left with is your own Express application.
In the example above, there were quite a few options - especially path-related options. This is because we're actually dealing with two different kinds of paths
/some/path part in https://example.com/some/path.... and we need to deal with a number of different files; the input files, the output bundle, static files, and so on.
Here's a rundown of what all the path-related options mean:
basePath: This is the filesystem path for your "project root", ie. where your package.json is. It must be an absolute path. The easiest way to generate this is to use path.join with __dirname and the right amount of ../.. entries.
For example, in the example above, our bin/server.js is in bin, which is one folder deeper than the root of the project; so we need to combine it with a single .. to get the project root.
entryFiles: These are the files - relative to the basePath (project root) - that the bundler should start with; basically, the files that contain the code that should be executed right when the bundle loads. The bundler will then follow all the require(...) statements starting from those files, collecting everything together. Note that this can be either a single path, or an array of them.
staticPath: This is the filesystem path - again, relative to the basePath - where your static files (CSS stylesheets, images...) are stored.
bundlePath: This is the filesystem path - relative to both staticPath and the URL root of your static files (see the staticPrefix option below) - where your bundle should be saved. So if staticPath is "public/", and bundlePath is "js/bundle.js", the final path for your generated bundle will be "public/js/bundle.js" (relative to the project root).
livereloadPattern: This is the glob pattern - relative to staticPath - that defines which files should be live-reloaded when they changed. Anything in the static files folder that matches this pattern, will be reloaded; anything that does not, will not.
And then there's a bunch of required non-path options:
port: The port that your server should run on, both in development and production mode.
app: The actual Express or Koa application that the development server should be integrated into (or, in production mode, the application that should be run).
browserify: The Browserify configuration to use for bundling.
Finally, there's a handful of optional options:
staticPrefix: The URL path, relative to the root of your domain/hostname, where your static file folder is publicly exposed. If you're exposing it at the root (the default result of doing app.use(express.static(...)) without specifying a middleware prefix), leave this undefined.
host: The host to listen on in production mode. Defaults to all network interfaces ("::").
allowUnsafeHost: By default, in development mode, the development server will only listen on localhost, so that noone can access it from outside your computer; this is for security reasons. If you want to disable this and use the host specified in host instead, you can set this option to true -- however, only do this if you fully understand the risks!
sourceMaps: Whether to enable Browserify's sourcemaps in development mode. Defaults to true.
developmentMode: Whether to run in development mode (true), production mode (false), or auto-detect it based on the NODE_ENV environment variable like in the examples ("auto"). Defaults to auto-detection.
middleware: Custom Connect/Express-style middleware to run in development mode only, before a request reaches your application. Don't use this for normal application middleware! You should almost never need this option.
livereloadPort: The port that the LiveReload server should listen on. Changing this will almost certainly break any LiveReload browser extensions. Defaults to 35729.
stream: A Writable stream to log ndjson output from Budo to. This defaults to process.stdout (ie. your terminal).
Altogether, the various paths are composed like this:
| Path | Calculated as |
|---|---|
| Static files filesystem path | basePath + staticPath |
| Static files URL path | root of your domain + staticPrefix |
| Bundle filesystem path | basePath + staticPath + bundlePath |
| Bundle URL path | root of your domain + staticPrefix + bundlePath |
| Pattern for livereloaded file matching | basePath + staticPath + livereloadPattern |
| Entry files filesystem path | basePath + entryFiles |
Depending on whether BUDO_BUILD=1 is specified:
NODE_ENV=development or developmentMode: true), a development server integrated into it.Arguments:
expressApp option has been renamed to app.inject-lr for LiveReload script injection instead of a custom implementation, to make it more robust in edge cases.express-budo.budo-express is used with an external restarter such as Nodemon, there's no longer a race condition between the browser reloading and the server process having restarted (which would result in an error page). Currently uses a fixed timeout, which is not ideal; if you're still seeing this problem, please file an issue!Initial release.
FAQs
A small wrapper to integrate Budo with an Express application
The npm package budo-express receives a total of 0 weekly downloads. As such, budo-express popularity was classified as not popular.
We found that budo-express demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Socket researchers discovered nine malicious NuGet packages that use time-delayed payloads to crash applications and corrupt industrial control systems.

Security News
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.

Security News
Learn the essential steps every developer should take to stay secure on npm and reduce exposure to supply chain attacks.