Key Takeaways
- Utilize npm scripts for organizing tasks such as builds, tests, and starting the app. This provides a single source of truth when developers look at a new project.
- Employ environment variables, such as process.env.NODE_ENV, from the early stages of a project. This ensures no leakage of sensitive info and builds the code properly from the start.
- Understand the event loop and how to use setImmediate() or setTimeout() to offload CPU-intensive tasks to the next event loop cycle.
- Use functional inheritance for simplicity and to avoid the complexities of prototypal inheritance or classes. This is a preferred method among many prolific Node contributors.
- Consider alternatives to JavaScript, such as TypeScript, Flow, Elm, ClojureScript, or CoffeeScript depending on the expertise level and the nature of the app. This can potentially benefit the team with very little setup.
10 Node.js Best Practices: Enlightenment from the Node Gurus is by guest author Azat Mardan. SitePoint guest posts aim to bring you engaging content from prominent writers and speakers of the Web community.
In my previous article 10 Tips to Become a Better Node Developer in 2017, I introduced 10 Node.js tips, tricks and techniques you could apply to your code today. This post continues in that vein with a further 10 best practices to help you take your Node skills to the next level. This is what we’re going to cover:
- Use npm scripts — Stop writing bash scripts when you can organize them better with npm scripts and Node. E.g., npm run build, start and test. npm scripts are like the single source of truth when Node developers look at a new project.
- Use env vars — Utilize process.env.NODE_ENV by setting it to development, or production. Some frameworks will use this variable too, so play by the convention.
- Understand the event loop — setImmediate() is not immediate while nextTick() is not next. Use setImmediate() or setTimeout() to offload CPU-intensive tasks to the next event loop cycle.
- Use functional inheritance — Avoid getting into mindless debates and a brain-draining trap of debugging and understanding prototypal inheritance or classes by just using functional inheritance like some of the most prolific Node contributors do.
- Name things appropriately — Give meaningful names which will serve as a documentation. Also, please no uppercase filenames, use a dash if needed. Uppercase in filenames not just look strange but can cause cross-platform issues.
- Consider NOT Using JavaScript — ES6/7 is pathetic addition which was born out of 6 years of meetings when we already had a better JavaScript called CoffeeScript. Use it if you want ship code faster and stop wasting time debating var/const/let, semi-colons, class and other arguments.
- Provide native code — When using transpilers, commit native JS code (result of the builds) so your projects can run without the builds
- Use gzip — Duh! npm i compression -S and sane logging — not too much not to little depending on the environment. npm i morgan -S
- Scale up — Start thinking about clustering and having stateless services from day one of your Node development. Use pm2 or strongloop’s cluster control
- Cache requests — Get maximum juice out of your Node servers by hiding them behind a static file server such as nginx and/or request level cache like Varnish Cache and CDN caching.
So let’s bisect and take a look at each one of them individually. Shall we?
Use npm Scripts
It’s almost a standard now to create npm scripts for builds, tests, and most importantly to start the app. This is the first place Node developers look at when they encounter a new Node project. Some people (1, 2, 3, 4) have even ditched Grunt, Gulp and the likes for the more low-level but more dependable npm script. I can totally understand their argument. Considering that npm scripts have pre and post hooks, you can get to a very sophisticated level of automation:
<span>"scripts": { </span> <span>"preinstall": "node prepare.js", </span> <span>"postintall": "node clean.js", </span> <span>"build": "webpack", </span> <span>"postbuild": "node index.js", </span> <span>"postversion": "npm publish" </span><span>} </span>
Often times when developing for the front-end, you want to run two or more watch processes to re-build your code. For example, one for webpack and another for nodemon. You can do this with && since the first command won’t release the prompt. However, there’s a handy module called concurrently which can spawn multiple processes and run them at the same time.
Also, install dev command line tools such as webpack, nodemon, gulp, Mocha, etc. locally to avoid conflicts. You can point to ./node_modules/.bin/mocha for example or add this line to your bash/zsh profile (PATH!):
<span>export <span>PATH</span>="./node_modules/.bin:<span>$PATH"</span> </span>
Use Env Vars
Utilize environment variables even for the early stages of a project to ensure there’s no leakage of sensitive info, and just to build the code properly from the beginning. Moreover, some libraries and frameworks (I know Express does it for sure) will pull in info like NODE_ENV to modify their behavior. Set it to production. Set your MONGO_URI and API_KEY values as well. You can create a shell file (e.g. start.sh) and add it to .gitignore:
<span>NODE_ENV=production MONGO_URL=mongo://localhost:27017/accounts API_KEY=lolz nodemon index.js </span>
Nodemon also has a config file where you can put your env vars (example):
<span>{ </span> <span>"env": { </span> <span>"NODE_ENV": "production", </span> <span>"MONGO_URL": "mongo://localhost:27017/accounts" </span> <span>} </span><span>} </span>
Understand the Event Loop
The mighty and clever event loop is what makes Node so fast and brilliant by utilizing all the time which would have been wasted waiting for input and output tasks to complete. Thus, Node is great at optimizing I/O-bound systems.
If you need to perform something CPU-intensive (e.g., computation, hashing of passwords, or compressing), then in addition to spawning new processes for those CPU-tasks, you might want to explore the deferring of the task with setImmediate() or setTimeout() — the code in their callbacks will continue on the next event loop cycle. nextTick() works on the same cycle contrary to the name. Argh!
Here’s a diagram from Bert Belder who worked on the event loop. He clearly knows how the event loop works!
Use Functional Inheritance
JavaScript support prototypal inheritance which is when objects inherit from other objects. The class operator was also added to the language with ES6. However, it’s overtly complex compared to functional inheritance. Most Node gurus prefer the simplicity of the latter. It’s implemented by a simple function factory pattern, and does NOT require the use of prototype, new or this. There are no implicit effects when you update the prototype (causing all the instances to change as well) since in functional inheritance each object uses its own copy of methods.
Consider code from TJ Holowaychuk, the prolific genius behind Express, Mocha, Connect, Superagent and dozens of other Node modules. Express uses functional inheritance (full source code):
<span>"scripts": { </span> <span>"preinstall": "node prepare.js", </span> <span>"postintall": "node clean.js", </span> <span>"build": "webpack", </span> <span>"postbuild": "node index.js", </span> <span>"postversion": "npm publish" </span><span>} </span>
To be objective, core Node modules use prototypal inheritance a lot. If you follow that pattern, make sure you know how it works. You can read more about JavaScript inheritance patterns here.
Name Things Appropriately
This one is obvious. Good names serve as a documentation. Which one would you prefer?
<span>export <span>PATH</span>="./node_modules/.bin:<span>$PATH"</span> </span>
I have no idea what dexter is doing when I only look at app.use(). How about a different more meaningfulname:
<span>NODE_ENV=production MONGO_URL=mongo://localhost:27017/accounts API_KEY=lolz nodemon index.js </span>
In the same fashion, file names must correctly reflect what is the purpose of the code inside. If you take a look at the lib folder of Node (GitHub link) which has all the core modules bundled with the platform, then you will see clear naming of the files/modules (even if you are not very familiar with all the core modules):
<span>{ </span> <span>"env": { </span> <span>"NODE_ENV": "production", </span> <span>"MONGO_URL": "mongo://localhost:27017/accounts" </span> <span>} </span><span>} </span>
The internal modules are marked with an underscore (_debugger.js, _http_agent.js, _http_client.js) just like methods and variable in the code. This helps to warn developers that this is an internal interface and if you are using it, you are on your own — don’t complain if it gets refactored or even removed.
Consider NOT Using JavaScript
Huh? Did you just read it correctly? But what the heck? Yes. That’s correct. Even with ES6 and the two features added by ES2016/ES7, JavaScript still has its quirks. There are other options besides JavaScript which you or your team can benefit from with very little setup. Depending on the expertise level and the nature of the app, you might be better off with TypeScript or Flow which provide strong typing. On the other end of the spectrum, there’s Elm or ClojureScript which are purely functional. CoffeeScript is another great and battle-tested option. You might take a look at Dart 2.0 as well.
When all you need is just a few macros (macros allow you to build exactly the language you want), not an entire new language, then consider Sweet.js which will do exactly that — allow you to write code which generates code.
If you go the non-JavaScript route, please still include your compiled code because some developers might not understand your language well enough to build it properly. For example, VS Code is one of the largest TypeScript projects, maybe after Angular 2, and Code uses TypeScript to patch Node’s core module with types. In the vscode/src/vs/base/node/ of VS Code repo (link), you can see familiar module names like crypto, process, etc. but with the ts extension. There are other ts files in the repo. However, they also included vscode/build with native JavaScript code.
Know Express Middleware
Express is a great and very mature framework. It’s brilliance comes from allowing myriads of other modules to configure its behavior. Thus, you need to know the most used middleware and you need to know how to use it. So why not grab my Express cheat sheet. I have the main middleware modules listed there. For example, npm i compression -S will give reduce the download speed by deflating the responses. logger('tiny') or logger('common') will provide less (dev) or more (prod) logs respectively.
Scale up
Node is great at async due to its non-blocking I/O and it keeps this async way of coding simple because there’s just one thread. This is an opportunity to start scaling early on, maybe even with the first lines of code. There’s the core cluster module which will allow you to scale vertically without too many problems. However, an even better way would be is to use a tool such as pm2 or StrongLoop’s cluster control.
For example, this is how you can get started with pm2:
<span>"scripts": { </span> <span>"preinstall": "node prepare.js", </span> <span>"postintall": "node clean.js", </span> <span>"build": "webpack", </span> <span>"postbuild": "node index.js", </span> <span>"postversion": "npm publish" </span><span>} </span>
Then you can start four instances of the same server:
<span>export <span>PATH</span>="./node_modules/.bin:<span>$PATH"</span> </span>
For Docker, pm2 version 2 has pm2-docker. So your Dockerfile can look like this:
<span>NODE_ENV=production MONGO_URL=mongo://localhost:27017/accounts API_KEY=lolz nodemon index.js </span>
The official Alpine Linux pm2 image is in the Docker Hub.
Cache Requests
This is a DevOps best practice which will allow you to get more juice out of your Node instances (you get more than one with pm2 or the like, see above). The way to go is to let Node servers do app stuff like making requests, processing data and executing business logic and offload the traffic to static files to another web server such as Apache httpd or Nginx. Again, you probably should use Docker for the set up:
<span>{ </span> <span>"env": { </span> <span>"NODE_ENV": "production", </span> <span>"MONGO_URL": "mongo://localhost:27017/accounts" </span> <span>} </span><span>} </span>
I like to use Docker compose to make multiple containers (nginx, Node, Redis, MongoDB) work with each other. For example:
exports <span>= module.exports = createApplication; </span><span>// ... </span><span>function createApplication() { </span> <span>var app = function(req<span>, res, next</span>) { </span> app<span>.handle(req, res, next); </span> <span>}; </span> <span>mixin(app, EventEmitter.prototype, false); </span> <span>mixin(app, proto, false); </span> app<span>.request = { __proto__: req, app: app }; </span> app<span>.response = { __proto__: res, app: app }; </span> app<span>.init(); </span> <span>return app; </span><span>} </span>
Summary
In this day and age of open-source software, there are no excuses not to learn from the trusted and tested code which is out in the open. You don’t need to be in the inner circle to get in. Learning never stops and I’m sure soon we will have different best practices based on the failures and successes which we will experience. They are guaranteed.
Finally, I wanted to write about how software is eating the world and how JavaScript is eating the software… there are great things like yearly standard releases, lots and lots of npm modules, tools and conferences… but instead I’ll finish with a word of caution.
I see how more and more people chase the next new framework or language. It’s the shiny object syndrome. They learn a new library every week and a new framework every month. They compulsively check Twitter, Reddit, Hacker News and JS Weekly. They use the overwhelming level of activity in the JavaScript world to procrastinate. They have empty public GitHub histories.
Learning new things is good but don’t confuse it for actually building stuff. What matters and what pays your salary is actually building things. Stop over engineering. You’re not building the next Facebook. Promises vs. generators vs. async await is a moot for me, because by the time someone replied to a thread in a discussion, I already wrote my callback (and used CoffeeScript to do it 2x faster than in plain ES5/6/7!).
The final best practice is to use best practices and the best of the best is to master fundamentals. Read source code, try new things in code and most importantly write tons of code yourself. Now, at this point, stop reading and go ship code that matters!
And just in case this post is not enough here is some more reading on best Node practices:
- https://blog.risingstack.com/nodejs-at-scale-npm-best-practices
- https://devcenter.heroku.com/articles/node-best-practices
- https://blog.risingstack.com/node-js-best-practices
- https://expressjs.com/en/advanced/best-practice-performance.html
- https://www.codementor.io/nodejs/tutorial/nodejs-best-practices
Frequently Asked Questions (FAQs) on Node.js Best Practices
What are some of the most important best practices for Node.js development?
Node.js development involves several best practices that can significantly enhance the efficiency and scalability of your applications. These include using asynchronous programming, which allows for non-blocking operations and improves performance. It’s also crucial to handle errors properly to prevent application crashes. Other best practices include using a linter to enforce code quality, using environment variables for configuration, and writing small modules to keep your codebase manageable and understandable.
How can I improve the performance of my Node.js application?
There are several ways to improve the performance of your Node.js application. One of the most effective methods is to use the Cluster module, which allows you to create child processes that all share server ports. This can significantly improve the performance of your application by allowing it to handle more requests simultaneously. Additionally, you can use tools like PM2 to manage and monitor your Node.js applications, which can help you identify and address performance issues.
What are some common mistakes to avoid when developing with Node.js?
Some common mistakes to avoid when developing with Node.js include blocking the event loop, not handling errors properly, and not using tools like linters to enforce code quality. Blocking the event loop can lead to performance issues, as it prevents other operations from being executed. Not handling errors properly can lead to application crashes, while not using linters can lead to inconsistent code quality and potential bugs.
How can I ensure that my Node.js application is secure?
Ensuring the security of your Node.js application involves several best practices. These include using HTTPS for secure communication, validating and sanitizing user input to prevent injection attacks, and using security headers to protect against common web vulnerabilities. It’s also important to keep your dependencies up to date, as outdated dependencies can contain known security vulnerabilities.
What are some best practices for testing Node.js applications?
Testing is a crucial part of Node.js development, and there are several best practices to follow. These include writing unit tests to test individual components of your application, integration tests to test how these components interact, and end-to-end tests to test your application as a whole. It’s also important to use a continuous integration (CI) system to automatically run your tests whenever changes are made to your codebase.
How can I manage dependencies in Node.js?
Managing dependencies in Node.js is typically done using npm, the default package manager for Node.js. It’s important to specify exact versions of your dependencies in your package.json file to ensure that your application works as expected. You should also regularly update your dependencies to benefit from bug fixes and security patches.
What are some best practices for error handling in Node.js?
Error handling is a crucial part of Node.js development. Best practices include using try/catch blocks to catch synchronous errors, using error-first callbacks to handle asynchronous errors, and using a centralized error handling mechanism to handle all errors in one place. It’s also important to log errors for debugging purposes and to respond to the client with appropriate error messages.
How can I ensure code quality in Node.js?
Ensuring code quality in Node.js involves several best practices. These include using a linter to enforce code quality, following a consistent coding style, and writing tests to catch bugs early. It’s also important to use version control (like Git) to track changes to your codebase and to perform code reviews to catch potential issues.
How can I scale my Node.js application?
Scaling a Node.js application can be achieved in several ways. One common method is to use the Cluster module to create child processes that share server ports, allowing your application to handle more requests simultaneously. You can also use load balancing to distribute incoming network traffic across multiple servers, and horizontal scaling (adding more machines) or vertical scaling (adding more resources to a single machine) depending on your needs.
What are some best practices for deploying Node.js applications?
Deploying Node.js applications involves several best practices. These include using environment variables for configuration, using a process manager like PM2 to manage your application, and using a continuous integration (CI) system to automatically deploy your application when changes are made to your codebase. It’s also important to monitor your application to identify and address performance issues.
The above is the detailed content of 10 Node.js Best Practices: Enlightenment from the Node Gurus. For more information, please follow other related articles on the PHP Chinese website!

Different JavaScript engines have different effects when parsing and executing JavaScript code, because the implementation principles and optimization strategies of each engine differ. 1. Lexical analysis: convert source code into lexical unit. 2. Grammar analysis: Generate an abstract syntax tree. 3. Optimization and compilation: Generate machine code through the JIT compiler. 4. Execute: Run the machine code. V8 engine optimizes through instant compilation and hidden class, SpiderMonkey uses a type inference system, resulting in different performance performance on the same code.

JavaScript's applications in the real world include server-side programming, mobile application development and Internet of Things control: 1. Server-side programming is realized through Node.js, suitable for high concurrent request processing. 2. Mobile application development is carried out through ReactNative and supports cross-platform deployment. 3. Used for IoT device control through Johnny-Five library, suitable for hardware interaction.

I built a functional multi-tenant SaaS application (an EdTech app) with your everyday tech tool and you can do the same. First, what’s a multi-tenant SaaS application? Multi-tenant SaaS applications let you serve multiple customers from a sing

This article demonstrates frontend integration with a backend secured by Permit, building a functional EdTech SaaS application using Next.js. The frontend fetches user permissions to control UI visibility and ensures API requests adhere to role-base

JavaScript is the core language of modern web development and is widely used for its diversity and flexibility. 1) Front-end development: build dynamic web pages and single-page applications through DOM operations and modern frameworks (such as React, Vue.js, Angular). 2) Server-side development: Node.js uses a non-blocking I/O model to handle high concurrency and real-time applications. 3) Mobile and desktop application development: cross-platform development is realized through ReactNative and Electron to improve development efficiency.

The latest trends in JavaScript include the rise of TypeScript, the popularity of modern frameworks and libraries, and the application of WebAssembly. Future prospects cover more powerful type systems, the development of server-side JavaScript, the expansion of artificial intelligence and machine learning, and the potential of IoT and edge computing.

JavaScript is the cornerstone of modern web development, and its main functions include event-driven programming, dynamic content generation and asynchronous programming. 1) Event-driven programming allows web pages to change dynamically according to user operations. 2) Dynamic content generation allows page content to be adjusted according to conditions. 3) Asynchronous programming ensures that the user interface is not blocked. JavaScript is widely used in web interaction, single-page application and server-side development, greatly improving the flexibility of user experience and cross-platform development.

Python is more suitable for data science and machine learning, while JavaScript is more suitable for front-end and full-stack development. 1. Python is known for its concise syntax and rich library ecosystem, and is suitable for data analysis and web development. 2. JavaScript is the core of front-end development. Node.js supports server-side programming and is suitable for full-stack development.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SecLists
SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.

DVWA
Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

SublimeText3 Mac version
God-level code editing software (SublimeText3)