Imagine you are writing a NodeJS webserver using expressjs. What should you do to create a secure, robust, easy to debug and deploy server? Here are my steps.
Always create a
package.json file, even if you do not intend to make the module public.
This file will list all dependencies (rather than listing them manually in the
can have script commands to test and run. Inside your folder run
npm init and answer a couple
of questions. If the server code is private and you want to avoid accidentally publishing it
to the public registry, set the
use configuration helper
At a very least, read the port from the environment first, otherwise use default
var app = express();
Hosting environments will pass the port to listen to via the environment variable, while in the local environment is ok to hardcode it.
automatically restart server during development
I use nodemon to start the server while developing it locally.
While developing locally I use
npm run watch. Anytime there is a file change or a crash, the server
restarts automatically. This speeds up the development.
save exact dependency versions
I prefer avoiding fuzzy dependency versions, like '1.1.*', or '^2.0.1', instead prefer to save
the exact version of the installed module's in the
package.json. To always do this, create and
set the following configuration in a new project's
Here is my
.npmrc file in my user folder
email=<my NPM email> save-exact=true fetch-retries=5 always-auth=true
advanced: clean up package.json
npm install --save-dev grunty grunt-nice-package
Add the command to the
npm run nice-package and fix all the errors / warnings. You
package.json surely looks nice now!
use a linter
To catch simple errors (like misspelled variables) in the static code without writing unit tests, install a linter, I recommend eslint - it is versatile, powerful and can be easily extended with custom rules.
npm install --save-dev eslint
Then create a file
.eslintrc - and set the following starting JSON
You can read how to configure eslint
and see the entire list of rules at [http://eslint.org/docs/rules/](http://eslint.org/docs/rules/.
eslint create a new command the
package.json scripts object - this allows to use shortcut name
If fixing every error is too difficult initially, at least make them warnings write in the source code, for example, to make unused variables a warning, rather than an error, use the comment
/* eslint no-unused-vars: 1 */
advanced: lint on each commit
To always lint before committing the code to avoid breaking the master, set up a pre-commit command.
npm install --save-dev pre-git
Then add all commands (only lint for now) to the
"pre-commit": "npm run lint"
You can always skip the
pre-commit hook by committing with
configure continuous integration service
Use Codeship (fast, works with Github and BitBucket, 100 private builds each month) or CircleCI (very fast, works with Github, single build host for free, even for unlimited private builds) to build your project on each commit.
Add badges to the project's README file to show the current build status, see badges
deploy to a hosting from CI
Instead of manually pushing the code to the hosting service, configure the CI server to push automatically.
All CI services worth their salt have nice and simple to configure integration with the major providers
(AWS, Heroku, etc). Just enter the branch / your hosting API key / application name. Each commit will be tested
and if the tests pass, deployed to the host. This is fine, at least for the
embed git commit id
It is very useful for debugging to embed the last commit id in the server. The server can print the commit id at startup, add it as a meta tag to the rendered HTML views and send with each exception to the crash reporting service. You can read how to pass the commit id from the CI to the hosting environment. Then you can embed the commit as a meta tag in each rendered view or pass to the crash reporting service Raygun.
setup crash reporting service
I advise to configure separate environments for the development vs production, and blacklist the local development to avoid the noise of multiple local errors.
To verify that the crash reporting service is working and catches the errors as expected,
you can include the crasher middleware. It throws an artificial
synchronous and asynchronous exceptions whenever someone requests
/api/crash route. This is extremely
useful for quick confirmation that the errors thrown inside the middleware are reported, as are
asynchronous global errors.
output pretty HTML
I strongly believe that the server should always generate pretty HTML output, any space savings between the minified and the original HTML text are negligible. Full indented HTML source is invaluable when looking through the page trying to understand the structure. To enable pretty HTML rendering in ExpressJS 4 just add the following after setting the render engine.
var app = express();
setup simple unit tests
It is important to start unit testing very quickly. I show how to test the ExpressJS server in this blog post.
secure the server against common attacks
Read this excellent series of blog posts and apply as many solutions to secure your server against injection / cross site and other types of attacks. The simplest solution that covers most of the recommended steps is to include the helmet middleware.
var express = require('express');
Protect against stray API requests
This is for websites that use forms to submit data.
If someone steals the session cookie from a valid session, they can then execute API requests directly to your server. A good intro to these "cross site forgery" attacks can be found at Understanding CSRF
To protect yourself, you want to send something else besides the cookie with each API request to guarantee that it is coming from your own web page, called CSRF tokens.
We can use expressjs/csurf module to automatically create a token that we can verify when someone makes a POST request.
The form in the
send view has the csrf token value in a hidden input
<form action="/process" method="POST">
End to end testing
I like unit testing Express but like end 2 end testing the server even more. Cypress.io is an excellent and powerful tool that works quickly right away. To start the server and then run the tests I use a utility to run NPM script commands in parallel.
npm install --save-dev npm-run-all
The script commands (see actual example in this repo).
More information about making an ExpressJS application robust and easy to maintain