Bootstrapping New Project

Assuming you already have node and npm installed (if not: I recommend using nvm), you can install nodebootstrap via NPM and use the nodebootstrap CLI tool to create a brand-new skeleton project.

You can replace hello in the installation command, with a sensible name for your project. Once the new project is built (typically takes less than a minute), you need to start it via a bash script. When the application finishes start you should see a simple “home document” response at: http://localhost:3000/

Installing nodebootstrap and building a new project:

$ npm install nodebootstrap -g
$ # If you are building a simple web application:
$ nodebootstrap build hello
$ # If you're building just an API 
$ # and/or want to customize destination location:
$ nodebootstrap build best-api -p ~/projects/bestapi --api

Once the project is built, you can start the application in dev-mode:

$ cd hello
$ npm run dev

or for “production-mode”:

$ cd hello
$ npm start

Dev mode provides hot reloading of code, which shouldn’t be required in production mode. In production, you should also make sure that npm start is ran by some process manager (e.g. Upstart) to ensure your Node app start on system startup and gets restarted in case the process crashes for whatever reason. Depending on your needs, how you facilitate this in production can vary greatly, so NodeBootstrap lets you make those decisions, getting out of your way.

You can also start the app as a Docker container, if you have Docker and Docker Composer properly set up, on your machine. Installing them on Linux should be trivial. On Windows and Mac, the easiest and the recommended way to get Docker tools installed is: via Docker Toolbox.

Project Structure

One of the benefits of using Node Bootstrap is the well-structured project skeleton it creates.

sample project structure

 

Various parts of the project structure:

bin
Startup scripts for dev and production environments. Feel free to create more.
config
configuration files for various environments, set by $NODE_ENV environmental variable. default is the baseline that is inherited by all others. Don’t create an explicit environment called default.
lib
this is where various modules your application logic consists of go under. Ideally, you should design all your modules as self-contained code that could be cleanly installed and uninstalled to add/remove distinct functionality, without touching other parts of the code. Node Bootstrap goes extra mile to promote self-contained modules. Self contained modules allow higher degree of reuse.
node_modules
this is where third-party modules installed via npm go under. Typically you install these using npm install modulename --save command.
public
dedicates space for static assets (images, js, css). The benefit of this folder is that you can point a web-server (e.g. Nginx or Apache) directly to this folder and not “bother” node on serving these files.
runit
Startup scripts for Docker-mode.
test
This is where you put your various types of automated tests. Node Bootstrap comes fully configured for Mocha unit and integration tests and even: Casper/Phantom drivers for Mocha to write powerful acceptance tests targeted at web applications. Istanbul coverage reports and batteries included.
views
Place to put your shared template files under. Node Bootstrap is, by default, pre-configured for Handlebars templates, but you can use any other Express4-friendly templating engine, even: alongside Handlebars, if you want. Typically templates should be encapsulated in their respective modules (which also have views folders, see the sample modules under “lib”), but in case you need to share some templates across various modules: this is where you’d do it.

 

Docker Support

Docker containers are an extremely convenient way of pre-packaging complex applications for easy installation on large number of hosting providers and systems.

Nodebootstrap comes with Docker batteries included. As soon as you create a new project you can launch it in a container, given that you have Docker tooling on your machine. If you installation steps looked like the following:

> nodebootstrap build firstapp

You can easily launch the app in dev mode (hot-reloading enable) with:

> cd firstapp
> npm run docker-dev

After which you can access your app at: http://<docker-host>:5000/

Where <docker-host> may either be 127.0.0.1 or whatever the IP of your Docker Machine happens to be (e.g. on Mac and Windows). If you need to find it, run: docker-machine ls and write-down the IP in the URL column.

Please note: even if you are using Docker Machine, you will be able to edit project files locally. And since hot-reloading is enabled in dev mode, changes will be immediately reflected.

Once you are ready to deploy your application in production, you can do it using a different npm script:

> npm run docker-start

The difference, in production mode is that: hot reloading is disabled. Also, the port which the service starts on is “random” (please ignore the service reporting port 3000) – Docker will assign first available port. This is highly recommended behavior in production environments, to ensure that various services won’t accidentally try to bind to the same port. In order to discover the current port, most people use a service discovery such as: Consul or etcd.

There are other useful scripts coded as npm scripts that you will need when using NodeBootstrap in Docker:

> npm run docker-test

will run automated tests inside the container.

Likewise, if you need to install an NPM package, you should not just issue “npm install” but should rather run a command such as:

> npm run docker-install-package lodash

This way module will be built inside the container, not on your host and that can make a huge difference for modules with native bindings (but may not matter as much for pure-JS modules).

By default, container uses Alpine Linux-based Node distribution, to minimize the container size. If you need full power of Ubuntu, edit Dockerfile in the project root and change the commented-out line accordingly.

To build a Docker image:

> docker build -t <reponame>/<projectname> .
# for instance:
> docker build -t irakli/nodebootstrap-hello .
# to see newly minted image:
> docker images

To (re-)run an image once it’s built:

> docker run -ti -p 5000:3000 irakli/nodebootstrap-hello

where 5000 is the port which will be exposed to the outside world (well, Docker host) and 3000 is the port which the service is running on, inside the container.

If you need to daemonize the Docker process and (optionally) save the process ID in a shell variable:

> PROC_ID=$(docker run -ti -p 5000:3000 -d irakli/nodebootstrap-hello)

To see running processes:

> docker ps

To kill a daemonized process:

> docker kill $PROC_ID

Encapsulated Modules

In addition to solving common boilerplate, central design principle of NodeBootstrap is to compose applications with re-usable, fully encapsulated, targeted set of modules.

TJ Holowaychuk explains this approach in a video screencast: http://vimeo.com/56166857

In a more “spaghetti” Node project you may see HTTP route handlers in the main script or application area, tangled together. What TJ argues for and NodeBootstrap implements is: letting each module declare their own handlers, so if you are installing a “user management” or “blog” module, all you need to do is NPM install that module and indicate from the main app where in the URL path the routes get attached.

Feel free to check-out more details about module design per NodeBootstrap in the source code of the sample module.

For a more advanced example, see: https://github.com/inadarei/nodebootstrap/tree/master/lib/hello

Compare this, in your main server.js file:

app.use('/users', require('./lib/user')); // attach to sub-route

to this:

app.get('/user', user.get);
app.post('/user', user.new);
app.delete('/user', user.remove);
...
app.get('/users/locations', user.getLocations);
app.post('/users/photos', user.getAvatars);

First is how NodeBootstrap handles things, the latter: what you may, alas, see in many projects that don’t use elegant componentization similar to NodeBootstrap style.

Contextualizing Runtime Environment

A number of environmental variables can affect the runtime behavior and startup mode of a Node Bootstrap project. A lot of those variables get their default values via bin/dev_start.sh and bin/start.sh shell scripts, but they won’t override the values if a value already exists, so you are in full control.

List of environmental variables:

NODE_LAUNCH_SCRIPT
defaults to “server.js”
NODE_ENV
defaults to “production”
NODE_CLUSTERED
defaults to 1 (on)
NODE_HOT_RELOAD
defaults to 0 (off)
NODE_SERVE_STATIC
defaults to 0 (off) - in production you should serve static content with NginX, not: Node.
NODE_CONFIG_DIR
defaults to “config” folder in the current folder
NODE_LOG_DIR
defaults to “logs” folder in the current folder

Startup Scripts

NodeBootstrap comes with three shell scripts (located in the bin folder):

dev_start.sh
will start your server.js node app in single-CPU mode with hot-realoading of code enabled. Convenient for active development.
start.sh
will start your server.js without hot-reloading, but with as many child processes as you have CPU cores. Recommended for production.
stop.sh
is a counterpart of start.sh to easily stop running background processes.

By default, dev_start.sh also lets Express.js handle static files so you don’t have to have a web server. The production version: start.sh assumes that you want your web-server (Nginx?) to take on this job.

Put something like this (as root) in your /etc/limits.conf or /etc/security/limits.conf:

* hard nofile 10000

Then log out, log back in and run:

> ulimit -n 10000

Hot Reloading vs. Daemon-izing Script.

In production environments it is a good idea to daemon-ize your Node process using so that it restarts if the process gets killed or crashes for some reason Nodemon. In non-Docker version Nodemon package is used for this purpose. In Docker version of NodeBootstrap installation runit manages the same.

While actively developing a project, it is very convenient to have “hot-reloading” of code available i.e. to have Node processes automatically restart themselves when you save a source file. If you set NODE_HOT_RELOAD to 1, start.sh will run in hot-reloading mode watching your: main script, as well as libs and config folders.

 

File Limits

Hot reloading uses native file watching features of unix-compatible systems. This is extremely handy and efficient, but unfortunately most systems have very low limits on watched and open files. If you use hot reloading a lot, you should expect to see: “Error: watch EMFILE” or similar.

To solve the problem you need to raise your filesystem limits. This may be a two-step process. On Linux, there’re hard limits (something root user can change in /etc/limits.conf or /ets/security/limits.conf) that govern the limits individual users can alter from command-line.

You should probably put ulimit -n 10000 in your .profile file, because it does not persist between restarts.

For OS-X and Solaris-specific instructions see a Stackoverflow Answer

Put something like this (as root) in your /etc/limits.conf or /etc/security/limits.conf:

* hard nofile 10000

Then log out, log back in and run:

> ulimit -n 10000

On certain Linux distributions you may also need to raise iNotify limit:

> sysctl fs.inotify.max_user_instances=16384 \
> && echo sysctl fs.inotify.max_user_instances=16384 \
> | sudo tee /etc/rc.local

And last, but not least, it’s a good idea to also run:

> sudo sysctl -w kern.maxfiles=40960 kern.maxfilesperproc=20480