TL;DR: The 16 essential Node.js packages available through NPM include Express.js for building web apps, Axios for making HTTP requests, and Mongoose for working with MongoDB databases.
In web development, Node.js has proved to be among the best environments in which applications should be both effective and scalable. This is mainly attributed to the large ecosystem of packages at the disposal of a developer through the Node Package Manager. Such packages help developers by streamlining their tasks, boosting performance, and removing the need to build solutions from scratch.
In this article, we’ll discuss 16 must-have NPM packages for any Node.js developer. We will discuss them in detail, including their key features, how to install them, and exactly how you can use them within your projects for better development workflows.
Express is a minimalist web app and API framework for Node.js. It simplifies HTTP requests and response handling, giving developers the freedom to build apps as needed.
You can use the following command to install the Express NPM package.
npm install express
Express provides flexible routing using methods like app.get() and app.post(), and middleware functions such as express.json() for tasks like JSON parsing, security, and logging. Helper methods like res.send() and res.json() make sending HTML or JSON responses easy.
Here’s an example of a simple Express server with two routes:
const express = require('express'); const app = express(); app.use(express.json()); // Middleware to handle JSON request bodies. // Route for handling GET requests. app.get('/', (req, res) => { res.send('Welcome to the Express web server!'); }); // Route for handling POST requests. app.post('/submit', (req, res) => { const data = req.body; res.send(Data received: ${JSON.stringify(data)} ); });
You can find a working demo of Express on StackBlitz.
Axios is a promise-based HTTP client that makes it easy to send HTTP requests from Node.js and browsers. By default, Axios handles promises, so the retrieval of asynchronous data feels simple and readable.
You can use the following command to install the Axios NPM package.
npm install axios
Axios automatically performs tasks like data transformation for JSON data and handling of errors. For example, if a developer retrieves data using the axios.get() method, it automatically parses the response into a JavaScript object.
axios.get('https://api.example.com/data') .then(response => { console.log(response.data); }) .catch(error => { console.error(error); });
With Axios interceptors, you can change requests or responses to make modifications, such as adding authentication tokens or logging. The following is an example with authentication headers.
axios.interceptors.request.use(config => { config.headers.Authorization = 'Bearer token'; return config; });
You can find a working demo of Axios on StackBlitz.
Mongoose is a MongoDB ORM library for Node.js. It allows developers to define the format in which MongoDB data should be stored and provides a straightforward way of interacting with MongoDB through JavaScript objects.
You can use the following command to install the Mongoose NPM package.
npm install mongoose
Mongoose works with schemas, which define the structure of data to be stored. A schema in Mongoose maps to a MongoDB collection and defines the shape of the documents in that collection. Once defined, Mongoose models enable developers to easily perform create, read, update, and delete operations on data.
Refer to the following code example to define a schema in Mongoose.
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const userSchema = new Schema({ name: String, email: String, age: Number });
In this schema, Mongoose defines that each document in the user collection will have a name, email, and age field.
Mongoose also handles validations.
const userSchema = new Schema({ name: { type: String, required: true }, email: { type: String, required: true }, age: { type: Number, min: 0 } });
Now, every time you attempt to save a user document, Mongoose will insist that your name and email are required and that your age must be a positive number.
Mongoose middleware functions execute at various stages of the query lifecycle (before or after a document is saved, updated, etc.). For example, you can add a middleware that automatically updates a timestamp before saving a document. Refer to the following code example.
userSchema.pre('save', function(next) { this.updatedAt = Date.now(); next(); });
Sequelize is one of the most famous ORMs for Node.js. It allows developers to define models in JavaScript, access CRUD operations, and manage database relationships and migrations without writing raw SQL.
You can use the following command to install the Sequelize NPM package.
npm install sequelize npm install mysql2 // or another database driver such as pg for PostgreSQL
With Sequelize, you can define models that will be the representations of tables in your database.
const { Sequelize, DataTypes } = require('sequelize'); const sequelize = new Sequelize('database', 'username', 'password', { host: 'localhost', dialect: 'mysql' // You can use 'postgres', 'sqlite', etc. }); const User = sequelize.define('User', { username: { type: DataTypes.STRING, allowNull: false }, age: { type: DataTypes.INTEGER } });
In the following example, the User is a model representing a user table in your database. Sequelize wraps it, allowing you to use the model as if it were a JavaScript object.
// Create a new user. User.create({ username: 'JohnDoe', age: 30 }); // Find a user. User.findOne({ where: { username: 'JohnDoe' } }); // Update a user. User.update({ age: 31 }, { where: { username: 'JohnDoe' } }); // Delete a user. User.destroy({ where: { username: 'JohnDoe' } });
Sequelize also supports associations, which manage relationships between tables. For example, if a User has many Posts :
const Post = sequelize.define('Post', { title: DataTypes.STRING }); User.hasMany(Post); Post.belongsTo(User);
This creates the necessary foreign key relationships between the users and posts tables.
You can find a working demo of Sequelize on StackBlitz.
Socket.io is a library that enables real-time, bidirectional communication between web clients and servers. A good example of this would be chat apps, live notifications, or multi-player games.
You can use the following command to install the Socket.io NPM package.
npm install socket.io
Here is an example setup for a chat where users can send messages to others in real time. The server will listen for incoming connections from the client. It sends a greeting message when the connection is established and then broadcasts messages of chat to all the currently connected clients.
Server-side (Node.js):
const io = require('socket.io')(3000); io.on('connection', socket => { console.log('A user connected'); socket.emit('message', 'Welcome to the chat!'); socket.on('chatMessage', msg => { io.emit('message', msg); // Broadcast message to all clients }); socket.on('disconnect', () => { console.log('User disconnected'); }); });
Client-side (HTML/JavaScript):
const socket = io('http://localhost:3000'); socket.on('message', message => { console.log(message); }); document.getElementById('sendButton').addEventListener('click', () => { const msg = document.getElementById('messageInput').value; socket.emit('chatMessage', msg); });
You can find a working demo of Socket.io on StackBlitz.
Webpack is a popular module bundler for JavaScript apps, primarily used to bundle and manage dependencies for web development. It takes in various modules (JavaScript, CSS, images, etc.) and compiles them into one or more optimized bundles for deployment.
You can use the following command to install the Webpack NPM package.
npm install webpack webpack-cli --save-dev
Webpack starts with an entry point, typically your main JavaScript file, and builds a dependency graph by analyzing all the modules (JavaScript, CSS, images, etc.) required by your project. It then bundles these files into optimized output files for deployment.
The process works as follows:
// webpack.config.js const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader' } } ] } };
You can find a working demo of Webpack on StackBlitz.
Jest is a powerful, zero-config testing platform from Facebook that is built with simplicity in mind. With Jest, expect a full complement of features such as test assertions, mocking, and snapshot testing-out-of-the-box solutions for unit tests, integration tests, and end-to-end tests. Quite easy to use, Jest can also be set up out-of-the-box with many libraries and frameworks in JavaScript, including React and Node.js.
You can use the following command to install the Jest NPM package.
npm install --save-dev jest
Here’s a basic test using Jest to check if a function correctly adds two numbers.
// sum.js function sum(a, b) { return a + b; } module.exports = sum; // sum.test.js const sum = require('./sum'); test('adds 1 + 2 to equal 3', () => { expect(sum(1, 2)).toBe(3); });
You can find a working demo of Jest on StackBlitz.
JsonWebToken is one of the popular Node.js libraries for token-based authentications. It provides a compact, URL-safe means to securely transmit information. JWTs are digitally signed and widely used for stateless authentication, eliminating the need for the server to store session data.
You can use the following command to install the JWT NPM package.
npm install jsonwebtoken
The following example creates a JWT that includes a payload of userId: 123. It signs the token with a secret key, setting it to expire in 1 hour. Now, when the client sends that token back to your server, your server is able to verify that the token is authentic and unaltered, as it was signed with the correct secret key. The jwt.verify function checks the token’s signature and expiration. If the token is valid, it returns the decoded payload, allowing the server to access the userId and any other information included in the token. If the token is invalid or expired, an error is returned, preventing unauthorized access.
const jwt = require('jsonwebtoken'); const token = jwt.sign({ userId: 123 }, 'your-secret-key', { expiresIn: '1h' }); console.log(token); jwt.verify(token, 'your-secret-key', (err, decoded) => { if (err) { console.log('Invalid token'); } else { console.log('Valid token:', decoded); } });
You can find a working demo of JsonWebTokens on StackBlitz.
CORS stands for Cross-Origin Resource Sharing. It’s something browser manufacturers implement as a line of defense that prevents web pages from calling out to domains other than their own. The CORS package in Node.js configures the domains that are allowed to communicate specifically with your API. That becomes especially useful when hosting the client and server on different domains or ports. You can make certain that data is shared across origins securely and with control.
You can use the following command to install the CORS NPM package.
npm install cors
Here is how to enable CORS for all domains.
const cors = require('cors'); const express = require('express'); const app = express(); app.use(cors()); // Enable CORS for all origins.
You can also configure CORS to allow only specific domains.
app.use(cors({ origin: 'https://example.com' // Only allow this domain. }));
Additionally, you can specify other options like allowed HTTP methods or headers.
app.use(cors({ origin: 'https://example.com', methods: ['GET', 'POST'], allowedHeaders: ['Content-Type', 'Authorization'] }));
You can find a working demo of CORS on StackBlitz.
Lodash is a utility library in JavaScript for deep cloning, manipulations with arrays, merging objects, and more. It makes developers’ lives easier when working with complex data transformations, allowing them to write cleaner, more efficient code.
You can use the following command to install the Lodash NPM package.
npm install lodash
Lodash provides many utility functions that make it easier to work with standard JavaScript data structures. One of the most powerful features is support for deep cloning, which is a way to get an actual copy of an object or an array and preserve nested data.
An example of deep cloning an object:
const _ = require('lodash'); const original = { name: 'Mark', age: 30, nested: { city: 'London' } }; const clone = _.cloneDeep(original); console.log(clone); // Output: { name: 'Mark', age: 30, nested: { city: 'London' } }
The rest of the nice array manipulation utilities available in Lodash are _.chunk(); chunk splits an array with a length of specified size:
const array = [1, 2, 3, 4, 5, 6]; const chunked = _.chunk(array, 2); console.log(chunked); // Output: [[1, 2], [3, 4], [5, 6]]
In addition to these utilities, Lodash provides functions for working with objects, arrays, and strings in a functional programming style, making your code more concise and easier to read.
You can find a working demo of Lodash on StackBlitz.
Bcrypt is one of the most utilized libraries for password hashing in Node.js. It provides a secure method for password hashing and comparison, a feature critical in securing user data in apps that use authentication.
You can use the following command to install the Bcrypt NPM package.
npm install bcryptjs
Bcrypt basically works on a mechanism of hashing the password and storing it in the database. On login, the entered password is compared with the stored hash.
Here’s how to hash a password using Bcrypt:
const bcrypt = require('bcryptjs'); const password = 'myPassword123'; bcrypt.hash(password, 10, (err, hash) => { if (err) throw err; console.log(hash); // Hashed password });
To compare a password with a stored hash:
bcrypt.compare('myPassword123', hash, (err, res) => { if (res) { console.log('Password matches'); } else { console.log('Password does not match'); } });
You can find a working demo of Bcrypt on StackBlitz.
Dotenv is a popular NPM package for maintaining environment variables in Node.js apps. It allows you to securely store sensitive details, like API keys or database credentials, outside your main codebase, keeping your configuration clean and secure.
You can use the following command to install the Dotenv NPM package.
npm install dotenv
To use Dotenv, create a .env file in your project root and define your environment variables.
DATABASE_URL=postgres://user:password@localhost:5432/mydb API_KEY=123456789abcdef
Then, in your app, load these variables using Dotenv.
require('dotenv').config(); console.log(process.env.DATABASE_URL); // Output: postgres://user:password@localhost:5432/mydb
You can create separate .env files to manage different environments. Change environments with ease without touching your codebase.
You can find a working demo of Dotenv on StackBlitz.
Winston is a multi-purpose, flexible Node.js logging library for capturing and formatting log data. It supports logging to a file, the console, or external logging services, making it suitable for tracking errors, warnings, and informational messages in production.
You can use the following command to install the Winston NPM package.
npm install winston
Here’s how to set up Winston to log messages to a console or a file.
const winston = require('winston'); const logger = winston.createLogger({ level: 'info', format: winston.format.combine( winston.format.colorize(), winston.format.simple() ), transports: [ new winston.transports.Console(), new winston.transports.File({ filename: 'logs/app.log' }) ] }); logger.info('This is an informational message'); logger.error('This is an error message');
In this example, Winston logs messages to the console and a file called app.log. It formats the log messages with colors and simple text for easier readability in the console. Winston also supports error handling by logging uncaught exceptions and unhandled promise rejections, ensuring that critical errors are captured and logged for later analysis.
You can find a working demo of Winston on StackBlitz.
Morgan is an HTTP request logger middleware for Node.js. It logs all of the HTTP requests to your server in a format that you define. It’s probably most well-known for its use in Express apps to log incoming requests to track traffic and help debug problems by logging detailed information about each request, including the request method, request URL, response time, and response status.
You can use the following command to install the Morgan NPM package.
npm install morgan
Here’s how to use Morgan with an Express app.
const morgan = require('morgan'); const express = require('express'); const app = express(); // Use the 'combined' log format app.use(morgan('combined')); app.get('/', (req, res) => { res.send('Hello, Morgan!'); }); app.listen(3000, () => { console.log('Server is running on port 3000'); });
The above example shows how Morgan sets up the logger for every incoming HTTP request in a combined format, including remote IP, method – URL, response time, and status code. Morgan also allows you to define custom log formats by specifying your format string. For example, you can log just the request method, URL, and status code.
app.use(morgan(':method :url :status'));
You can find a working demo of Morgan on StackBlitz.
Moment.js is one of the most popular JavaScript libraries for parsing, validating, and manipulating dates and times. It streamlines date manipulation, supports time zones, and offers locale-specific formatting.
You can use the following command to install the Moment NPM package.
npm install moment
Here is how to create a Moment object from a date string and then format it as needed.
const moment = require('moment'); const now = moment(); // Current date and time console.log(now.format('MMMM Do YYYY, h:mm:ss a'));
You can find a working demo of Moment on StackBlitz.
Joi is a schema validation library for JavaScript, commonly used for validating API request payloads or user input in Node.js apps. It allows you to define and enforce complex data validation rules in a simple, readable format. Joi ensures that incoming data matches the expected structure and format, helping to avoid issues like invalid or malicious data in your app.
You can use the following command to install the Joi NPM package.
npm install joi
Here’s an example of using Joi to validate a user object.
const Joi = require('joi'); const schema = Joi.object({ name: Joi.string().min(3).required(), age: Joi.number().integer().min(0).required() }); const userInput = { name: 'John', age: 25 }; const validation = schema.validate(userInput); if (validation.error) { console.log('Validation error:', validation.error.details); } else { console.log('Valid data:', userInput); }
In the previous example, Joi will check whether the userInput fits the schema or not. The schema expects the name to be a string of at least three characters and age a positive integer. If validation fails, it returns an error message.
Joi also supports custom validation rules, allowing you to extend its functionality for more specific needs:
const customSchema = Joi.string().custom((value, helpers) => { if (value === 'forbidden') { return helpers.error('any.invalid'); } return value; // Valid data });
You can find a working demo of Joi on StackBlitz.
In summary, the NPM ecosystem provides Node.js developers with a versatile set of packages to streamline development, enhance functionality, and simplify complex tasks. From Express for web frameworks to Joi for data validation, these packages cover essential areas of modern app development. These well-liked NPM packages will allow developers to create more productive, scalable, and maintainable apps, which, in turn, boost productivity and quality.