Title: Node.js best Practices
1Node.js Best Practices and Security
2Table of Content
- Managing Project Structure
- Error Handling of the App
- Code Style Node.js Best Practices
- Node.js Security Best Practices
- Conclusion
- Reference
3Introduction
- Over the last couple of years, Node.js has been
one of the most popular platforms. - It is definitely easy to get started on those
Node.js projects, but understanding how to better
organise your code and how to deal with errors
can often become a nightmare once you get past
the simple Hello World app (as with most
languages and frameworks). - When designing applications for production, it is
a must to adopt the best practises in Node.js
programming, whether you are a novice or a
seasoned developer using Node.
4Managing Project Structure
- Divide your Solution by Components
- Layering Components
- Use npm in it for a New Project
- Wrap Common Utilities as npm Package
- Using Environment Aware, Secured and Hierarchical
Configuration File - Avoiding Garbage in-app
- Hook Things Up
5Divide your Solution by Components
- Maintaining a massive code base with lots of
dependencies is one of the toughest things for
larger applications. - This, though introducing new features, slows down
development. - We should split the entire codebase into smaller
components according to Node.js best practises,
so that each module gets its own folder, and
ensure that each module is kept simple and
compact. - We should create modular applications as a best
practice for node.js by splitting the entire
codebase into modular components.
6Layering Components
- Layering is important and each part is therefore
built to have 'layers.' - These layers have a dedicated object that can be
used on the network, logic, and data access code
as a Node.js best practice. - It can establish a clean separation of problems
by doing this and can separate processes from
mock and test codes significantly. - By passing the layer objects (Express req, res)
to the Service layer and the data layers, several
developers mix the layers.
7Use npm in it for a New Project
- Npm init will automatically generate a
package.json file for your project that shows all
the packages/node applications of npm install has
the information of your project.
8Wrap Common Utilities as npm Package
- Usually, a broader application/project has the
same code repeatedly used at different places
many times. - We may combine them into a single private package
at different locations within our application and
use that package. - Installing Npm removes duplication of code and
makes code more manageable.
9Using Environment Aware, Secured and Hierarchical
Configuration File
- We should preserve our app-level keys readable
from file and environment variables as security
best practises. - For easier usability, we can also keep secrets
outside the committed code and make a
configuration file hierarchy. - A complete and flawless configuration setup is
needed to meet all this. - In their projects, developers can also leverage
the power of npmrc file, which during npm init
can automate quite a few environment
configurations, such as setting up metadata
within the project package
10Avoiding Garbage in-app
- Node js has a 1.5 GB default limit, but a selfish
and lazy garbage collector is still used. - It waits until it uses the whole memory and
recovers on its own. - We can set the flags on the V8 if you want to
gain more power over the garbage collector. - If the app is running in an environment with less
than 1.5 GB of usable memory, this is
significant.
11Hook Things Up
- For automation, we can make perfect hooks using
Npm's lifecycle scripts. - We can use a pre-install script if we want to run
something before building our app. - You can build assets with a grunt, gulp and
browser or webpack of the production application
using a post-install script in the JSON package.
12Error Handling of the App
- Using Async-Await or Promises
- Handling Errors Centrally
- Validating Request Body
- Always Await Promises before Returning to Avoid a
Partial Stacktrace
13Using Async-Await or Promises
- Good programming practises claim that using
javascript' synchronous feature 'within promises
to handle async errors results in a callback hell
issue with multiple callbacks. - To overcome this issue, we can take a look at the
available libraries or async and wait for
javascript. - The process manager can use the feature of
promises to capture errors in code. - It decreases the sophistication of code and makes
code more readable.
14 Handling Errors Centrally
- Any logic that handles errors such as logging
errors, sending emails about errors should be
written in such a way that when any error
happens, all APIs, night-jobs, unit testing will
debug messages and call this process.
15Validating Request Body
- To ensure that the request body is proper and
does not contain any malicious material,
developers may use available open-source packages
like Joi. - Before executing actual logic, we can validate
all the request parameters and body parameters to
satisfy the intended schema. - Through doing so, before executing real logic, we
can throw an error at the user input that the
requested body is not correct.
16Always Await Promises before Returning to Avoid a
Partial Stacktrace
- If an error occurs, whether from a synchronous or
asynchronous flow, a complete stack trace of the
error flow is imperative. - Surprisingly, if an async function returns a
commitment without waiting (e.g. calls another
async function), then an error that causes the
caller function to vanish in the stacktrace
should occur. - This will allow the individual to diagnose the
mistake with partial data. - Even more, if the cause of the error lies within
the caller feature, then there is a v8 feature,
also known as "zero-cost async stacktraces," that
allows stacktraces not to be cut on the most
recent wait.
17Code Style Node.js Best Practices
- Use Linting Packages
- Name Your Functions
- Use Const Over Let, Do Not Use Var
- Use of Strict Equality Operator ()
- Dont Use Callbacks, Instead Use Async Await
- Using Arrow Functions (gt)
18Use Linting Packages
- ESLint is one of the most common linting kits,
which is used to check potential code errors and
also check code types to conform with best
practise standards. - There are several linting tools available.
- It detects spacing problems in any potential
patterns of code that could lead to any security
risks as well as possible future app-breaking. - Other tools are also available that format code
automatically and place it in a more readable
way. - It also resolves minor syntax errors at the end
of each sentence, such as adding semicolons, etc.
19Name Your Functions
- Many of the functions that may include closures
and callbacks can be called. - You may limit the use of functions which are
anonymous. - Make sure you use a function called Naming.
- Naming will allow you to easily execute and then
take a memory snapshot of what you want.
20Use Const Over Let, Do Not Use Var
- Const variables allocated can not be updated,
this will help you avoid several times from using
a single variable so that we can keep our code
safe. - We'll use the let keyword in certain situations
where we need to re-assign variables. - For example, we can use let in a loop if we want
to re-declare the variable value. - Apart from this, the domain has been blocked by
"let variables," meaning they are accessible
within a specific block where they are declared. - It is possible to use variables declared using
var anywhere within the function.
21Use of Strict Equality Operator ()
- Instead of weaker abstract equality operator
, use the strict equality operator . - will convert two variables to a similar form
and then compare them while does not type
case variables and guarantees that all variables
are identical and of the same type.
22Dont Use Callbacks, Instead Use Async Await
- In all node js versions above Node 8 LTS,
Async-await is supported. - To better deal with asynchronous code, we can
minimise the use of 'callbacks' and 'promises'. - It makes the code appear synchronous, but it's a
non-blocking mechanism in fact. - The best thing we can do with async-await is to
compact code and render the syntax of code like
try-catch.
23Using Arrow Functions (gt)
- Arrow functions make the code more compact and
maintain the root function's lexical context
(i.e. this). - It is, however, a suggestion to use async-await
applications when working with old APIs that can
accept promises or callbacks to stop the use of
functional parameters.
24Node.js Security Best Practices
- Prevent DOS Attacks by Using Middlewares
- Prevent SQL Injections
- Secure Transmission of Data
- Manage HTTP Headers
- Control Request Payload Size
- Configure 2FA for NPM or Yarn
25Prevent SQL Injections
- This raises the possibility of database abuse
when you often use JS strings or string
concatenations. - This practise renders your data invalidated and
highly vulnerable to SQL injection attacks by the
created application. - For ORMs like Sequelize and Mongoose, in-built
protection against certain SQL injection attacks
is available. - In order to prevent these attacks, you must
always use the built-in indexed parameterized
queries supported by Object-Relational
Mapping/Object Document Mapper ORM/ODM or
database libraries supporting indexed
parameterized queries.
26Prevent DOS Attacks by Using Middlewares
- If legitimate users do not receive the requested
service or if degraded services are received, we
should ensure that our node application is
threatened with a DOS attack. - To avoid this situation from happening, we should
use middleware for apps to enforce rare
limitations. - Some plug-ins, such as rate-limiter-flexible kit,
Nginx, cloud firewalls, cloud load balancer, are
available for larger applications.
27Secure Transmission of Data
- The credibility and confidentiality of our
application data in transit is very critical. - Some encryption misconfigurations in the tested
infrastructure are one of the key reasons that
compromise the application security of our data
and confidentiality. - Protocols such as TLS (Transport Layer Security)
and SSL (Secure Sockets Layer) are used to create
an end-to-end encrypted client-server connection
(web server and a browser).
28Manage HTTP Headers
- You can build impactful Node js applications with
stable HTTP headers to prevent clickjacking,
cross-site scripting (XSS attacks) and other
malicious attacks. - We can use plug-ins like the easy-to-configure
helmet and create our own security rules for
Node.js.
29Control Request Payload Size
- It is difficult to process other large requests
as the traffic on our application rises, which
reduces the efficiency of the app and exposes our
application to Denial-Of-Service (DOS) attacks. - One single thread is executed by a larger request
entity. - Because of the bigger payload size, even without
making several requests, attackers can enforce
vulnerabilities. - By using an express body-parser that only accepts
small-size payloads, we can restrict the body
size.
30Configure 2FA for NPM or Yarn
- Even if we apply multi-factor authentication,
attackers will manipulate user-sensitive
information and instal malicious software in
project libraries (MFA). - If malicious code is introduced into the public
domain by the attackers, the entire web programme
and web app may be demoted. - Therefore, we must use two-factor authentication
2FA with npm/yarn, which leaves hackers with
little hope.
31Conclusion
- We want to ensure that all Node.js applicants
embrace them from the beginning of their
development journey to deliver high-quality
production apps by enlisting the
industry-standard Node.js best practises that are
adopted by us. - For advanced developers looking to hone their
Node.js abilities, these best practises can also
be equally useful. - You can easily enhance your application
efficiency with the aid of these coding best
practises, style guides and techniques.
32References
- 1https//www.tatvasoft.com/blog/node-js-best-prac
tices/