Levelling up an Express API, Part 1

  developmentexpressjs

Over the past 18 months I’ve built and deployed a couple of APIs using Node, Express & TypeScript, typically serving data to a web site, sometimes with endpoints to validate and write data to a database.

I wanted to share some techniques past “getting started” (if you’re at that stage, a couple of great guides are at https://developer.okta.com/blog/2018/11/15/node-express-typescript and https://itnext.io/building-restful-web-apis-with-node-js-express-mongodb-and-typescript-part-1-2-195bdaf129cf). I’ll cover my learnings one by one, explaining how they incrementally improve code, help towards production quality, and take advantage of tens of hours of knowledge and research in ready-to-go dependencies.

My base API contains 3 files, currently serving a single endpoint pedals that returns a JSON collection of guitar effect pedals:

  • package.json - dev and production dependencies (initially, Express, TypeScript, and types only)
  • src/server.ts - Express server written in TypeScript, will be compiled to javascript to run by command in package.json
  • tsconfig.json - Typescript config file, borrowed from https://developer.okta.com/blog/2018/11/15/node-express-typescript

The Express server can be run from a terminal by calling npm run serve (after installing necessary dependencies using npm install), and then also calling curl -s http://localhost:34512/pedals in another terminal to demonstrate getting JSON from the running server.

Level 0: Version control

Before I start anything, I use version control. Git is easy to use, even as a solo developer. I’d suggest setting up a good .gitignore file too (I won’t be spending time explaining Git in this blog post, though).

Level 1: TypeScript

TypeScript includes javascript, adding explicit typing which helps avoid simple errors and leads to more correct code. TypeScript and javascript can be mixed in the same project too.

I went ahead and wrote my code in TypeScript already. I added a tsconfig.json file and a command in package.json to call the TypeScript compiler and serve the resulting javascript.

Level 2: Linting

I’d say linting is the next best “level up” after TypeScript. Regardless if you’re permissive or strict with your code style, linting can help. A linter like ESLint can be enhanced by adding Prettier to handle “cosmetic” preferences like indents, tabs vs. spaces, line length etc.

To add basic linting to the base API, first stop the server if it’s started, then install ESLint and friends: npm install --save-dev eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser

Next, create an .eslintignore file:

Then add a lint command and eslintConfig section to your package.json. The new package.json file looks like:

Going further - I’ve tried a couple of useful ESLint plugins that add checks and rules, such as:

  • eslint-plugin-import - “This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, and prevent issues with misspelling of file paths and import names. All the goodness that the ES2015+ static module syntax intends to provide, marked up in your editor.”
  • eslint-plugin-json - “Eslint plugin for JSON files”
  • eslint-plugin-node - “Additional ESLint’s rules for Node.js”
  • eslint-plugin-promise - “Enforce best practices for JavaScript promises.”
  • eslint-plugin-security - “ESLint rules for Node Security. This project will help identify potential security hotspots, but finds a lot of false positives which need triage by a human.”
  • eslint-plugin-sonarjs - “SonarJS rules for ESLint to detect bugs and suspicious patterns in your code.”
  • eslint-plugin-standard - “ESlint Rules for the Standard Linter”

Unfortunately, configuring the plugins is outside what I can cover in this post, though.

Level 3: Testing

Lastly (for part 1), good tests will provide confidence when updating or adding dependencies or features to your code. Overall, I try and test for the “happy path” in an Express API as well as errors like:

  • non-existent endpoints
  • too may requests
  • missing request headers
  • missing response headers
  • parameters too short
  • parameters too long etc.

I can suggest a couple of great resources for adding tests to Express, at https://blog.jscrambler.com/testing-apis-mocha-2/, https://hackernoon.com/testing-node-js-in-2018-10a04dd77391, and https://medium.com/@jodylecompte/express-routes-a-tdd-approach-1e12a0799352.

That’s all for part 1 - in part 2, I’ll cover a few easy, practical techniques to further production-ready an Express API.