Hey, I'm Marco and welcome to my newsletter!
As a software engineer, I created this newsletter to share my first-hand knowledge of the development world. Each topic we will explore will provide valuable insights, with the goal of inspiring and helping all of you on your journey.
In this episode, I'll show you the Node.js libraries I use in almost all of my projects. I've collected them over about four years of use, and I think it's interesting to share them with you.
👋 Introduction
Node.js libraries are powerful tools that developers use to add functionality to their applications.
They provide ready-made solutions for common programming tasks, saving time and effort in development. Libraries also promote code reusability, allowing developers to leverage existing code instead of reinventing the wheel. Additionally, using libraries can improve code quality and maintainability by following established best practices and standards maintained by the library authors. Overall, smart use of Node.js libraries can make development processes smoother and improve how applications work.
However, it's important not to overuse them. Using libraries excessively can make your code too big and slow down how it runs. It's better to use libraries wisely, concentrating on their main features and avoiding unnecessary extras. This keeps your code organized and makes sure your application runs smoothly.
📚 My Libraries
Here are the libraries I typically install for most of my projects, along with specific examples of how to use them:
axios
dotenv
jsonwebtoken
lodash
luxon
memoizee
nodemon
nodemailer
p-queue
yargs
📡 Axios
Axios is a popular library with 40M+ weekly downloads, used for making HTTP requests from both the browser and Node.js environment. It provides a simple and intuitive API for handling asynchronous HTTP requests, supports Promises for efficient request handling, and offers features like interceptors for request/response manipulation. Axios also automatically handles JSON data conversion, making it a versatile choice for web development on both the client and server sides.
I use it because it makes HTTP calls to external services easy to use, whether the content type is application/json, application/x-www-form-urlencoded or FormData.
You can install it in your project with:
yarn add axios
I'll show you an example of how I used it within a method to make an external call to ChatGPT:
const computeSummaryEndpoint = async (text, user_message) => {
const body = {
model: "gpt-3.5-turbo-0125",
messages: [
{
role: "user",
content: text
},
{
role: "user",
content: user_message
}
],
temperature: 1,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0
};
const { data } = await axios.post('https://api.openai.com/v1/chat/completions', body, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`
},
});
const summary = data.choices[0].message.content
return summary
}
NPM Package: https://www.npmjs.com/package/axios
🔑 Dotenv
Dotenv is a library used to manage environment variables. It simplifies the process of loading configuration settings stored in a .env
file into the application's runtime environment. This allows developers to keep sensitive information, such as API keys or database credentials, out of their source code repository and ensures better security practices. By using dotenv, developers can easily access these environment variables throughout their application, making development and deployment more manageable and secure.
Starting from Node v20.6.0, it became possible to use a native built-in feature --env-file=<path-to-env-file> to replace dotenv. This feature can be specified in the node process start command. However, it doesn't support loading environment variables directly in the code, which is why I continue to use dotenv and I may consider replacing it in the future.
You can install it in your project with:
yarn add dotenv
add these two lines to your js file:
import dotenv from 'dotenv';
dotenv.config({ path: './.env' });
// you now have access to all environment variables via the process.env object
NPM Package: https://www.npmjs.com/package/dotenv
🔐 Jsonwebtoken
The jsonwebtoken library enables to easily generate, sign, and verify JSON Web Tokens (JWTs) for use in authentication and secure data transmission within web applications. JWTs are compact, URL-safe tokens that can securely store user information and other data, making them ideal for implementing stateless authentication mechanisms and transmitting claims between parties in a secure and tamper-proof manner.
With jsonwebtoken, developers can create JWTs using a variety of algorithms such as HMAC, RSA, or ECDSA, allowing flexibility in choosing the level of security and compatibility required for their applications. The library also provides methods for verifying the integrity and authenticity of JWTs, ensuring that only tokens signed with the correct key or secret are accepted.
In addition to basic token creation and verification, jsonwebtoken supports features such as token expiration, custom payload data, and token refreshing, making it a comprehensive solution for implementing secure authentication and authorization workflows in Node.js applications.
You can install it in your project with:
yarn add jsonwebtoken
I am sharing with you a JS module that I utilize for generating and validating JWT tokens. It relies on a secret retrieved from an environment variable.
import jwt from 'jsonwebtoken';
import {APIError401} from "../errors.js";
export const createAuthToken = (payload) => jwt.sign(payload, process.env.JWT_AUTH_SECRET, {expiresIn: '1h'});
export const decodeToken = (token, secret) => {
try {
jwt.verify(token, secret); // check if token is expired
return jwt.decode(token); // decode payload
} catch (error) {
throw new APIError401();
}
};
NPM Package: https://www.npmjs.com/package/jsonwebtoken
🛠️ Lodash
Lodash is a popular utility library that provides a wide range of functions for simplifying common programming tasks. It includes methods for working with arrays, objects, strings, and more, making it easier to write efficient and readable code. Lodash also supports functional programming paradigms, helping developers write more modular and reusable code. Overall, it's a powerful tool for improving productivity and code quality in JavaScript projects.
You can install it in your project with:
yarn add lodash
The methods I use most are:
groupBy: group elements of a collection by a specified key, creating an object where unique values of the key serve as keys, and the corresponding elements are stored in arrays as values.
cloneDeep: creates a deep copy of an object, including all nested objects, ensuring that changes made to the copy do not affect the original, and vice versa.
uniq: returns an array containing only unique values from the original array.
here is an example of how to use them:
const _ = require('lodash');
const users = [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 30 },
{ id: 3, name: 'Alice', age: 35 },
{ id: 4, name: 'Charlie', age: 25 }
];
// Group objects by 'name' property
const groupedUsers = _.groupBy(users, 'name');
console.log(groupedUsers);
// {
// Alice: [
// { id: 1, name: 'Alice', age: 25 },
// { id: 3, name: 'Alice', age: 35 }
// ],
// Bob: [ { id: 2, name: 'Bob', age: 30 } ],
// Charlie: [ { id: 4, name: 'Charlie', age: 25 } ]
// }
// Deep clone the grouped object, if I make a change on groupedUsers I // do not alter the structure clonedUsers
const clonedUsers = _.cloneDeep(groupedUsers);
console.log(clonedUsers);
// {
// Alice: [
// { id: 1, name: 'Alice', age: 25 },
// { id: 3, name: 'Alice', age: 35 }
// ],
// Bob: [ { id: 2, name: 'Bob', age: 30 } ],
// Charlie: [ { id: 4, name: 'Charlie', age: 25 } ]
// }
// Extract unique values from an array
const ages = _.uniq(users.map(user => user.age));
console.log(ages);
// [ 25, 30, 35 ]
NPM Package: https://www.npmjs.com/package/lodash
📅 Luxon
Luxon is a powerful library for time management. With clear APIs and comprehensive features for date manipulation, Luxon simplifies time zone management, time calculations, and date formatting. It is highly customizable and suitable for a wide range of development applications.
You can install it in your project with:
yarn add luxon
I use it to perform operations such as adding or subtracting hours/days/minutes, converting timezones, and parsing string formats like ISO Date:
const { DateTime } = require('luxon');
// Create a DateTime object with the current date and time:
const now = DateTime.now();
console.log(now.toISO());
// 2024-03-17T22:59:20.492+01:00
// Adding days to a date
const date = DateTime.fromISO('2024-03-17');
const newDate = data.plus({ days: 3 });
console.log(newData.toISODate());
// 2024-03-20
// Subtracting hours from a DateTime
const hour = DateTime.now();
const newHour = hour.minus({ hours: 2 });
console.log(newHour.toISOTime());
// 20:59:20.492+01:00
// Convert the time zone of a DateTime
const newDate = DateTime.fromISO('2024-03-12T16:00:00-05:00');
const newDateUTC = newDate.toUTC();
console.log(newDateUTC.toISO());
// 2024-03-12T21:00:00.000Z
NPM Package: https://www.npmjs.com/package/luxon
💾 Memoizee
Memoizee offering efficient memory caching for function results. It provides a straightforward alternative to using external caching systems like Redis, especially in scenarios where simplicity and reduced dependencies are priorities. By storing and retrieving function results from memory, Memoizee optimizes performance by eliminating redundant computations, making it ideal for applications with frequently called and computationally intensive functions. Its customizable caching options allow to fine-tune caching strategies based on specific application needs, resulting in faster response times and improved overall efficiency in Node.js applications.
You can install it in your project with:
yarn add memoizee
I use it to store the results of complex operations or when the expected output remains consistent over time. For example, I utilized it in the redirect system I created for HackerNews to cache the query result from the database that retrieves the Implementing post from the redirect frontend route (getByPath static method).
Find the post here:
NPM Package: https://www.npmjs.com/package/memoizee
🔄 Nodemon
Nodemon restarts your application automatically when you change your code. This saves you from having to restart the server manually, so you can focus on coding without interruptions. Nodemon also lets you customize settings like ignoring specific files/folders and setting restart delays to fit your project's requirements.
You can use Nodemon as a “dev dependency” during development because it's specifically designed for that purpose. Unlike production dependencies needed to run the application in a live environment, dev dependencies like Nodemon are only required during development. They are not included in the production build, helping keep the final application light and efficient.
You can install it in your project with:
yarn add nodemon --dev
I used nodemon in my backend template for Node.js, you can find it specified in the package.json file in the serve:development script, you can retrieve the post, and the template, here:
NPM Package: https://www.npmjs.com/package/nodemon
✉️ Nodemailer
Nodemailer allows to send emails easily from their applications. It provides a simple and straightforward API for sending various types of emails, including plain text, HTML content, attachments, and more. Nodemailer supports different email services and protocols such as SMTP, sendmail, and direct transport. You can configure SMTP settings, authentication methods, and transport options according to their email service provider requirements. Additionally, Nodemailer offers features like built-in email templating, MIME support, and error handling, making it a versatile and reliable choice for email functionality in Node.js applications.
You can install it in your project with:
yarn add nodemailer
I used this library in a podcast project where I implemented an email-based magic link authentication system, are you interested?
Sign up, I'll be sharing a detailed post about it in the upcoming weeks.
NPM Package: https://www.npmjs.com/package/nodemailer
⏳ P-queue
p-queue is designed to manage and control the concurrency of asynchronous tasks. It provides a flexible and efficient way to limit the number of concurrently running Promises, allowing developers to avoid overwhelming system resources or external APIs. With p-queue, you can easily create queues of tasks with customizable concurrency settings, ensuring optimal performance and resource utilization in your Node.js applications. Whether you're handling I/O-bound operations or managing API requests, p-queue offers a robust solution for managing asynchronous workflows effectively.
You can install it in your project with:
yarn add p-queue
I've used p-queue library in my projects to create systems that manage HTTP calls on outputs. This helps prevent exceeding the rate limits imposed by external systems that are being utilized.
import PQueue from 'p-queue';
import axios from 'axios';
// Create a queue with a limit of 2 concurrent calls
const queue = new PQueue({ concurrency: 2 });
// Function to make an HTTP request using axios
const makeHttpRequest = async (url) => {
try {
const response = await axios.get(url);
return response.data;
} catch (error) {
throw new Error(`Error making request to ${url}: ${error.message}`);
}
}
// Array of URLs to call
const urls = [
'https://jsonplaceholder.typicode.com/posts/1',
'https://jsonplaceholder.typicode.com/posts/2',
'https://jsonplaceholder.typicode.com/posts/3',
'https://jsonplaceholder.typicode.com/posts/4',
];
// Add HTTP calls to the queue
const processUrls = async () => {
for (const url of urls) {
await queue.add(async () => {
try {
const data = await makeHttpRequest(url);
console.log(`Response from ${url}:`, data);
} catch (error) {
console.error(error.message);
}
});
}
}
// Start the URL processing process
processUrls();
NPM Package: https://www.npmjs.com/package/p-queue
📟 Yargs
Yargs is a Node.js library for parsing command-line arguments. It simplifies the process of defining commands, options, and arguments for CLI applications. With Yargs, you can create intuitive and robust command-line interfaces with minimal code, making it easier to build and maintain CLI tools in JavaScript. Key features include command parsing, option handling with aliases and validation, argument parsing, interactive prompts and configuration file support.
You can install it in your project with:
yarn add yargs
I used yargs to create a CLI for my ChatGPT-based YouTube video summary system, more details can be found here:
NPM Package: https://www.npmjs.com/package/yargs
🌟 Top lectures of the week
Every Developer Thinks Remote Work Is Good, But…
Why You Need to Work With Less Experienced Engineers
How universe conspired to get me a job at Meta ?
And that’s it for today! If you are finding this newsletter valuable, consider doing any of these:
🍻 Read with your friends — Implementing lives thanks to word of mouth. Share the article with someone who would like it.
📣 Provide your feedback — We welcome your thoughts! Please share your opinions or suggestions for improving the newsletter, your input helps us adapt the content to your tastes.
💬 Chat with me — If you have any doubts or curiosity, please write to me, I will be happy to answer you!
I wish you a great day! ☀️
Marco
Great article! I don't use nodeJS that often to be honest. As, I work mostly in backend and infrastructure. But, I did use it once, and it wasn't the easiest experience.
I think after this article, I am more curious to explore it more.
Thanks for mentioning me, Marco! And, keep up the great work. :)
Thank you for mentioning our newsletter.