How to improve your API service on node.js. Part 1

A decent amount of material is now available on writing the API on node.js. Most of them are in the form of tutorials and demos in the documentation. This is enough to quickly figure out and write something of their own. But they rarely find details of why this is done that way. And some points are omitted altogether for simplicity and brevity.

This article is intended to fill in some gaps that might arise, and ultimately improve your service on node.js.

PS In no case do I consider myself an expert: there is room to grow. But at the same time there is something to share.

Project file structure


File structure is a basic, but very important thing. When creating it, it is worth considering the possibility of scaling the service, for this reason it is not worth placing files in the flat structure of one directory. Need a hierarchy, need modularity.

When naming directories, you must adhere to established standards. This will help colleagues and in a few months to quickly find out where and what is located.

File structure example

src/
    controllers/
         users/
             index.js
         index.js
    db/
         mongo/
             index.js
         index.js
    helpers/
    middlewares/
         auth.js
    models/
         users.js
    routes/
        users/
             index.js
        index.js
    index.js

.eslintrc
.gitignore
README.md
...
package.json

Notes:

  1. All executable files should be located in ./src.
    This will allow you to separate the source files from compiled typescript or babel, which will be located in ./dist or ./build.
    It will also make it easier to configure linters and other configurable tools, since the target files are located in a separate directory.

  2. Place all controller and route entities in separate directories. This will open a ./routes or ./controller and see only one index.js file that imports and exports subdirectory entities.
    This will allow you to quickly navigate the existing functionality, since it describes only the interface of controllers or routers without delving into their implementation.

About Javascript Compilation


Of course, you can not use babel or typescript to convert your javascript. As a rule, new ECMAScript standards quickly end up in node.js, and you, with the exception of browser-based javascript, can control their support.
But I am convinced that they are worth using. And that's why:

  1. The latest version of Node.js is not always available for production.
  2. Node.js (v. 13) still has problems with supporting ECMAScript modules, although they appeared and left the flag, they are still experimental. To sell early.

Consider adding babel to the project:

Install the dependencies:

npm install @babel/core @babel/node @babel/preset-env --save-dev

Add the .babelrc configuration file to the project root
{
    "presets": [
      "@babel/preset-env"
    ]
}

Script run example
"start": "nodemon --exec babel-node src/index.js",

Notes:

  1. When installing dependencies, do not forget to put the --save-dev (-D) switch only during the development phase. It is necessary at least for semantics.

About the need for linter


Let's start with the obvious fact: linters are needed. We write code, a lot of code. So much of that, they themselves are not able to control its uniformity. This item is incredibly enhanced in team development.

And uniformity is the key to code readability.

The question remains about the rigor of the linter. The choice of which should be based on the size of the team, their professional level, an important criterion is the project itself.

Adding a simple linter to the project

Let's install the dependencies:

npm install eslint --save-dev

Add the .eslintrc configuration file to the project root:

{
    "env": {
        "node": true,
        "es6": true,
    },
    "extends": "eslint:recommended"
}

As a rule, such a config is not enough. Here either expand the rules yourself or take a closer look at the more rigorous options prepared.

 ,  
...
    "extends": "eslint:recommended",
    "rules": {
        "quotes": ["error", "single"]
    }
}

Using a stricter linter

There are several popular configurations based on the same style guides.

  • Google

     npm install --save-dev eslint-config-google
    
  • Airbnb

     npm install --save-dev eslint-config-airbnb-base eslint-plugin-import
    
  • Idiomatic
     npm install --save-dev eslint-config-idiomatic
    

Accordingly, it will be necessary to correct .eslintrc

{
    "env": {
        "node": true,
        "es6": true,
    },
    "extends": "google" | "airbnb-base" | "idiomatic"
}

It is also necessary to add the launch of the linter to a separate script.

"lint": "eslint ./src --cache && echo \"eslint: no lint errors\"",
"lint:fix": "eslint ./src --fix && echo \"eslint: no lint errors\""

About application launch


Anyone who has access to the project repository should be able to run it. Whether he can do it and how much time it will take for him to do this is one of your project quality criteria.

It is important to document in advance how to start the service step-by-step in the README.md file, as well as prescribe commands for the main actions.

"start": "npm run dev",
"dev": "nodemon --exec babel-node ./src/index.js",
"build": "babel ./src --out-dir ./build",
"prod": "NODE_ENV=production node ./build/index.js",
"lint": "eslint ./src --cache && echo \"eslint: no lint errors\"",

To use the above commands, you may need to install the following packages:

npm install --save-dev @babel/cli nodemon babel-node

Note:

  1. If you even added the basic commands to package.json, still describe the startup process in README.md.

Conclusion


Initially, the article wanted to cover much more recommendations on writing an API on node.js, but I want to fit in 3-5 minutes. reading the article. Subject to good feedback, a follow-up will be released.

All Articles