Node.Js or Javascript in general is certainly not a very awesome programming language and definitely not the best choice for creating high performance server-side applications. But even then, it is quite popular in the industry, largely because of the community and having the same language on both frontend and the backend code. This has led to the development of the two of the most famous and on-demand tech stacks called as MERN (MongoDB, Express.Js, React.Js, Node.Js) and MEAN (same as MERN with Angular.js in place of React.Js) and many others like MEVN, MESN etc.
Let's shift our focus today to the server side only, dealing with creating APIs with Node.Js. In this tutorial, I use Express.Js as the server framework, MongoDB as the database and other things would be discussed as the tutorial goes on.
The motive behind this is to give some insights on how I prefer to do certain things when creating my APIs in nodejs. This architecture is very scalable and maintainable from a developer perspective. There may be methods better than this and used widely in the industry, and you are free to choose any of them.
We will be mainly using typescript to ensure type safety in our code. I have not limited this project to be able to be deployed to a single cloud environment and this contains pretty much all the configuration files required to do so.
Package.json is the first place you should look for when watching a new project. This contains useful configuration for the project like name, version, author, scripts, dependencies etc.
Here, I have tried to make this file as readable and expressive as possible. I have tried separating the scripts to most atomic possible. This includes different scripts depending on differenet node environments like development,production and testing. I have kept this minimal and dependencies section does not include anything so that the template can be used for pretty much any project.
Eslint helps to add enforce code quality and style of your code. This file contains useful configuration for these use cases.
Prettier is used to format your code and keep it consistent across different developers. There can be cases where certain developer in the team prefers double quotes for strings while others prefer single quote, here prettier comes to rescue. This ensures a consistent code formatting standard for the entire codebase and reformats to the defined configuration.
This file is useful when deploying to heroku (for testing purposes). Heroku (on free dynos) is not suitable for production deployments, as the dynos keep on going to sleep mode after a short interval of time of around 30 mins or so.
Ignore the required files
.gitignore to ignore files from git
.eslintignore to ignore files from eslint checks
.prettierignore to ignore files from prettier checks
.dockerignore to ignore files from docker builds
.slugignore to ignore files from heroku builds
Use .env to store all the actual dependencies and .env.sample to give a glimpse of what all environment variables are required in the project. For example
Tsconfig.json file is responsible for defining standards and configurations to be used while compiling your typescript file to javascript to be able to run. These are my preffered configuration for tsconfig.json. This is obviously not complete and there is a scope of improvement for a better developer experience
After adding this file, you need to make this file executable. In linux, you can do something like (from the root of the project)
sudo chmod +x ./.husky/pre-commit
requires root user permissions
After this step, on installing any npm package, there would be an additional message saying "Git Hooks Installed". This ensures, your git hooks are properly setup. These git hooks can be later used to enforce styles, run scripts (tests) before committing code to git.
This file contains all the configuration options for the website. Right now, it contains only some of the things, but this file is usually large and contains a lot of configurations
Rate limiting users is a very important feature of the server. This prevents users from the same IP from spamming the server with multiple requests. This can prevent DOS and malitious hackers from spamming the server with pre-scripted requests.
This contains scripts to be used for all routers in the codebase. Here, I have put a makeSafe function, which gets wrapped on the routes to automatically catch the errors, and so there is no need to use try/catch for any controllers, you can throw errors directly inside the controllers without thinking about ways to catch the error. This reduces the code size and make it more readable and maintainable.
Authentication is one of the primary requirements of any API server and typically found in almost all websites now-a-days. This module is responsible for all the authentication logic (in premise). This includes login, register, forgot/reset password, delete/recover account, etc.
This module can go anywhere from level 0 to level 100 and can involve a lot of complexities depending on the use case and business requirements.
So, basically, this was it. This is how, I prefer things to be done while creating a nodejs API server. Again, this may not be the best approach, but definitely a good approach.