Skip to content
This repository was archived by the owner on Feb 23, 2021. It is now read-only.

GovTechSG/node-example-express-app

 
 

Repository files navigation

Node.js Example Project

Running the App

Install all dependencies using npm.

npm install

Ensure that you have MongoDB running and listening to port 27017. For ease of development, use the following docker-compose command.

docker-compose up mongo

Run the app by running the following command.

node bin/www.js

For development, it's useful to restart the application whenever you make changes. Using nodemon helps in this regard.

npm install --global nodemon

nodemon bin/www.js

Use the following docker-compose command to up the entire application stack.

docker-compose up

Project Structure

The following table describes a standard directory structure for a web application. Refer to this blog post.

Path Description
bin Important binaries and scripts
config Configuration files for the project
daos Data access objects that couple the application to the ODM/ORM library
models Domain Model definitions, usually written using the ODM/ORM library
routes The defined REST API routes and their business logic
services Services used by the Express application
util Static utilities to store commonly used code

Application Setup

To start off from scratch, you can install the Express generator.

npm install --global express-generator

express new-app

Libraries

The following Express middleware are used:

Library Purpose npm install
morgan
Docs
Logs requests received by Express npm install --save morgan
multer
Docs
Processes multipart requests npm install --save multer
connect-rid
Docs
Adds a unique request ID to each header. Good for debugging. npm install --save connect-rid
serve-static
Docs
Enables Express to serve static files npm install --save serve-static
serve-favicon
Docs
Enables Express to serve a favicon file npm install --save serve-favicon

The following libraries are used:

Library Purpose npm install
Lodash
Docs
Utility functions for working with objects and arrays. npm install --save lodash
Moment.js
Docs
Utility functions for working with date and time. npm install --save moment
bluebird
Docs
My library of choice for working with Promises npm install --save bluebird
SuperAgent
Docs
Library for making HTTP requests npm install --save superagent
Mongoose
Docs
Object Document Mapper Library for working with MongoDB npm install --save mongoose
Sequelize
Docs
Object relational Mapper Libary for working with SQL databases like PostgreSQL or MySQL npm install --save sequelize
Passport
Docs
Authentication Library to secure your endpoints npm install --save passport
Winston
Docs
Logging Library npm install --save winston

It's good practice to have a .gitignore that excludes node_modules, any IDE generated files, configuration and RSA private keys.

Config

When writing an application that connects to a database, or interacts with a secured API, all of this information is usually stored in a configuration file. I usually write a config loader and import it into my services.

config/index.js

config/config.js

Services

Mongoose ODM

When importing the config, I make sure to check environment variables for configuration overrides, as per the 12-Factor App spec. This is especially useful when packaging your web application in Docker containers as it enables you to modify configuration at runtime for different environments.

services/mongooseService.js

Logging

I always setup a logging service to give me flexibility to send my logs to external log collection endpoints. As I frequently use Docker containers, and as per 12-Factor Application standards, I usually send all logs to STDOUT``` and ```STDERR by default.

services/loggingService.js

Main App

I customize the Express app.js to include all my middleware. I also wire up the routes import, where all my controller logic will be placed for each REST API endpoint I define. app.js

Models

I earlier setup a models import into my services/mongooseService.js. You can define rich models in Mongoose with validation, instance and static functions. For ease of creation of the schemas, I import and re-export them in an object that I can loop over to instantiate the Mongoose schemas.

models/index.js

models/KeyValue.js

Routes

Most of the business logic of the application goes into my routes. Each route trigger a function in the dao or services layers and returns a JSON response.

routes/index.js

The following is an example route that exposes a REST API for working with a domain object.

routes/store.js

Express Starting Script

I also heavily modify the Express starting script, so that I can support TLS and import all my services. I also implement a listener to exit the application when the SIGTERM process signal is received, as per 12-Factor Application standards.

bin/www.js

Docker and Docker Compose

Docker

I also usually write a Dockerfile to package the application. Following this helpful guide from Node.JS

Dockerfile

A .dockerignore``` file is useful to prevent the humongous ```node_modules directory from being sent to the Docker host every time you build the Docker image.

.dockerignore

Docker Compose

It's also useful to create a docker-compose.yml to make it easier to build and run your application services.

docker-compose.yml

With the above docker-compose.yml in place, I can run the application together with a supporting MongoDB instance with the following command:

docker-compose up

About

Example Node.js Express App

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 98.1%
  • Dockerfile 1.9%