320 likes | 325 Views
Node.js is popular among developers as an asynchronous and event-driven language used for backend development. It has a syntax easy enough to understand even for beginners.
E N D
Managing Project Structure Error Handling of the App Code Style Node.js Best Practices Node.js Security Best Practices Conclusion Reference Table of Content
Introduction • 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.
Managing 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
Divide 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.
Layering 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.
Use 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.
Wrap 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.
Using 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
Avoiding 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.
Hook 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.
Error 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
Using 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.
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.
Validating 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.
Always 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.
Code Style Node.js Best Practices • Use Linting Packages • Name Your Functions • Use Const Over Let, Do Not Use Var • Use of Strict Equality Operator (===) • Don’t Use Callbacks, Instead Use Async Await • Using Arrow Functions (=>)
Use 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.
Name 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.
Use 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.
Use 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.
Don’t 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.
Using Arrow Functions (=>) • 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.
Node.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
Prevent 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.
Prevent 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.
Secure 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).
Manage 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.
Control 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.
Configure 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.
Conclusion • 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.
References 1:https://www.tatvasoft.com/blog/node-js-best-practices/