29,99 €
Node.js revolutionizes server-side JavaScript development and empowers developers to build efficient, scalable, and versatile applications across a range of use cases. This book is written by a Node.js core collaborator and releaser and is the only book for beginners on Node.js. It takes you on a progressive learning path that will give you the skills needed to leverage Node.js.
You’ll learn Node.js fundamentals and refresh your knowledge of JavaScript before transitioning to the development of modern web applications using Node.js, Express.js, and MongoDB. You’ll get hands-on with complex topics such as asynchronous programming, npm libraries, event-driven patterns for HTTP servers, RESTful API, and JSON Web Tokens. The final chapters will walk you through the deployment process, offering insights into various strategies, including bare metal setups, virtual machines, and containerization with Docker. You’ll also be guided through the use of Process Manager 2 (PM2) for efficient process management.
By the end of this Node.js book, you'll have the skills to craft, test, and deploy Node.js web applications confidently and use this powerful stack in your day-to-day projects.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 421
Veröffentlichungsjahr: 2024
Node.js for Beginners
A comprehensive guide to building efficient, full-featured web applications with Node.js
Ulises Gascón
Copyright © 2024 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Group Product Manager: Rohit Rajkumar
Publishing Product Manager: Vaideeshwari Roshan
Senior Content Development Editor: Feza Shaikh
Technical Editor: K Bimala Singha
Copy Editor: Safis Editing
Project Coordinator: Shagun Saini
Indexer: Subalakshmi Govindhan
Production Designer: Joshua Misquitta
Marketing Coordinators: Anamika Singh and Nivedita Pandey
First published: May 2024
Production reference: 2240424
Published by Packt Publishing Ltd.
Grosvenor House
11 St Paul’s Square
Birmingham
B3 1RB, UK
ISBN 978-1-80324-517-1
www.packtpub.com
To all the maintainers who are thanklessly keeping the modern world turning.
– Ulises Gascón
Ulises Gascón is a member of the Express Technical Committee (TC), as well as a Node.js core collaborator and releaser. With over 10 years of experience as a software engineer, he has worked for prominent companies such as Google and IBM, as well as various consultancy firms and start-ups. Additionally, he is a leading contributor to numerous open-source organizations and projects, with several packages ranking in the top 25 on the npm registry.
He has earned recognition as a Docker Captain, Microsoft Most Valuable Professional (MVP), and Google Developer Expert (GDE) for his noteworthy contributions to the Node.js community. With extensive experience, he specializes in building IoT solutions with open hardware, developing SaaS products, creating developer tools, managing microservices, migrating legacy systems, and designing distributed systems.
I want to thank the people who have been close to me and supported me, especially my family.
Abhijeet De Sarkar is a senior engineer with experience in designing and building scalable systems in the fraud detection, Fintech, and Edtech domains. His expertise is in Node.js, TypeScript, Golang, MongoDB, PostgreSQL, and Kafka. He is the founder of Hyperlearn.
Jon Wexler, senior engineer and leader of Hacky Apps, combines his vast experience in tech with deep Node.js expertise. Known for turning complex concepts into accessible projects, Jon’s work spans from leading innovative app development to educating at coding bootcamps. His practical approach has earned him accolades, making him a guiding force in the industry. As the author of Get Programming with Node.js, he empowers developers to elevate their skills through real-world applications, reflecting his commitment to tech excellence and leadership.
Pranshu Jain is a dynamic software engineer renowned for his innovative approach and user-centric solutions. With a strong background in open source development, he has revolutionized user experiences with creations such as the Sunbird ED-Search widget. Pranshu’s talent lies in translating complex business requirements into practical solutions, showcased through his successful roles at Parentheses Labs and DigiLocker. Proficient in cloud technologies, full stack, and API development, Pranshu is committed to driving noble initiatives forward. His collaborative spirit and unwavering commitment to excellence make him a valuable asset in any project. Follow Pranshu’s journey on LinkedIn at @pranshu32 to stay updated on his impactful contributions.
In Part 1, you will learn how Node.js works and why it is one of the most popular tools used to build web projects today. Together, we will set up the development environment and you will learn the details of the JavaScript language and how you can take advantage of its asynchronous programming.
This part includes the following chapters:
Chapter 1, Introduction to Node.jsChapter 2, Setting Up the Development EnvironmentChapter 3, JavaScript FundamentalsChapter 4, Asynchronous ProgrammingWelcome to the first chapter of the book! Node.js is one of the most relevant technologies available and allows you to build any kind of project (web, desktop, CLI tools, microservices, IoT, and so on) within the same stack. The community around the project is very powerful and innovative.
In this chapter, we will explore the main features of Node.js and why it became so popular over time. Then, we will explore the Node.js architecture and how it works. Finally, we will explore the different versions of Node.js available to us.
In this chapter, we’re going to cover the following main topics:
What makes Node.js so special and why it is a revolutionary technologyThe Node.js architecture and how it worksHow to identify the right Node.js version for your projectsThis knowledge will help you to decide when it is a good fit for your projects and will guide you around the complex ecosystem.
The code files for the chapter can be found at https://github.com/PacktPublishing/NodeJS-for-Beginners.
The official definition of Node.js is very simple, but it doesn’t explain why Node.js has become so popular over time:
“Node.js® is an open-source, cross-platform JavaScript runtime environment.”
In Figure 1.1, we can see how the popularity of Node.js has been increasing over time, and even today, it is still growing fast.
Figure 1.1 – The interest in Node.js, generated using Google Trends
Next, let’s explore the main reasons why Node.js is so popular.
Node.js is a lightweight and fast runtime based on the V8 JavaScript engine, which is the same engine that powers Google Chrome and Microsoft Edge, among others. It is based on a single-thread architecture and event-driven model, which means that it doesn’t need to create a new thread for each request, as in other popular tools such as PHP. This is a huge advantage because the memory consumption is very low and the performance is very high.
We will explore the single-thread architecture in detail in the upcoming sections.
Node.js is cross-platform, which means that we can run it on any operating system and architecture available in the modern market.
Node.js is not only used to build web applications but it can also be used to build any kind of application, from a simple command-line tool to a complex desktop application such as Slack or Visual Studio Code.
Node.js is based on JavaScript, which is one of the most popular programming languages in the world. This means that millions of developers already know the language and they can easily start using Node.js.
Any application that can be written in JavaScript, will eventually be written in JavaScript.
– Jeff Atwood (Atwood’s Law)
Also, the Node.js application programming interface (API) – the methods, libraries, and utilities that Node.js provides for us to use – is very simple and easy to use, so the learning curve is very small. You don’t need to master the Node.js API to start building web applications; you can progressively learn while you are building your application.
There are a lot of resources available to learn Node.js, from official documentation to online courses and tutorials in many languages and oriented to different profiles.
Node.js has a huge ecosystem of packages, JavaScript libraries, and resources developed by the community that can be used to build any kind of application. There are more than two and a half million packages available in the npm Registry (https://www.npmjs.com/), which is the official package manager for Node.js.
Also, Node.js has huge support from cloud providers, which means that you can easily deploy your application to the cloud and scale it as much as you need.
Most of the emerging technologies provide software development kits (SDKs) for Node.js, so you can easily integrate your application with them. Many companies are using Node.js in production, so you can easily find support and resources to solve any problem that you may have.
Also, many popular libraries are isomorphic, which means that they can be used in the browser and in the server, so you can reuse your code and avoid duplications.
For me, the most important reason why Node.js is so popular is the community. Node.js has a huge community of developers that are constantly contributing to the project. This means that you can easily find support and resources to solve any problem that you may have and also to include new features or solve specific bugs.
The Node.js Foundation merged with the JS Foundation in 2019 to create the OpenJS Foundation https://openjsf.org/, which is the current organization that governs the Node.js project and other key projects in the JavaScript ecosystem, such as Appium, jQuery, Electron, Express, and webpack.
Important information
You can find the governance model of the OpenJS Foundation at https://openjsf.org/about/governance/ and the Node.js project at https://nodejs.org/en/about/governance.
Many companies are members of the OpenJS Foundation, such as Google, IBM, Microsoft, Netflix, Red Hat, GitHub, and many others (https://openjsf.org/about/members/). These provide a lot of support and resources to keep the project alive.
As you can see, many factors are helping Node.js to become so popular, from a proven community-powered model to a solid ecosystem that brings many capabilities to Node.js. It appears that Node.js will remain popular in the future!
In the next section, we will explore how the architecture works under the hood.
When Node.js came out in 2009, it was a revolution in the web development world, as Ryan Dahl, the creator of Node.js, decided to use a very unusual approach at that time: a single-thread architecture.
In his presentation about Node.js at the JSConf (https://www.youtube.com/watch?v=EeYvFl7li9E), Ryan Dahl said he wanted to achieve two key things when building Node.js: server-side JavaScript and non-blocking I/O.
The common approach for I/O operations in web applications is to create a new thread for each request. This is a very expensive operation because the memory consumption is very high and the performance is very low.
The idea behind this approach is to split the system resources and assign them to each thread. This is a very inefficient approach because, most of the time, the CPUs are idle, just waiting for the resources.
The other problem is that we are limited in the amount of memory that we can use because each thread needs to have its own memory space.
Overall, this process was very inefficient, and it was not scalable.
With Node.js, we use a different approach. We won’t split the resources; we keep a single thread and use a non-blocking I/O model that allows us to free the resources while waiting, so we can continue processing requests.
To make this possible, Node.js has two key dependencies: libuv (https://libuv.org/) and V8 (https://v8.dev/).
Figure 1.2 – Diagram that showcase the relationship between the user code, v8, Node API and libuv (event queue and worker threads)
As you can see, the architecture has many pieces and it can be a bit overwhelming at first. This diagram is not the full picture but it is a good starting point to understand how Node.js works in the context of this chapter. There are many pieces to understand from this figure, so let’s go step by step.
This is the code that we write to build our application. It will be done in JavaScript and it can use Node.js APIs and third-party libraries.
This is the engine encapsulated in Node.js that will execute our JavaScript code. V8 is the same engine that is used in the Chrome browser under the hood.
It is surprising for many developers to see that Node.js is written mostly in C/C++, but this is one of the reasons why Node.js is so fast. The Node.js bindings are the C/C++ code that will be executed when we use the Node.js APIs under the hood.
This is the C library that will handle the I/O operations with multi-platform support. It will use the thread pool to execute the blocking operations and it will notify the Node.js bindings when the operation is completed. We will program Node.js defining functions that will be executed when certain async operations are completed. For example, when we try to read the content from a file, we will execute certain code when the content is available. libuv handles the low-level logic for this coordination to happen.
The event loop is the most critical part of the Node.js architecture. Keeping this in mind will help you to understand how Node.js works.
As we have seen before, the new I/O operations approach is not magic, just a very smart way to handle and abstract using an asynchronous layer that is easily handled with JavaScript. This introduces the need for us to know how to do asynchronous programming. We will cover this topic in more detail in Chapter 4, but for now, we need to understand how the event loop works.
One fantastic resource to understand the event loop in more depth is this talk from Philip Roberts at JSConf EU 2014: What the heck is the event loop anyway? (https://www.youtube.com/watch?v=8aGhZQkoFbQ). It also includes a tool called Loupe (http://latentflip.com/loupe) to experiment with the event loop architecture yourself.
As you can see, Node.js is the product of combining several technologies. The event loop is quite an advanced topic that you will require some time to digest and understand fully, but don’t worry, as you can start working with Node.js even if you are not yet 100% clear on how the event loop and all the pieces work together. You will be able to learn about it better in practice with the exercises from the book. Now, let’s explore how Node.js organizes the versions.
Node.js follows semantic versioning (SemVer) (https://semver.org/) and it is important to understand how this versioning works in order to choose the best version for the project.
When considering semantic versioning, it helps to determine what changes to anticipate as a user, especially whether they might cause disruptions or not. This understanding assists our end users in preparing for potential updates.
Semantic versioning is one of the most popular ways to version software. In the following figure, we can differentiate the elements used to build the release version.
Figure 1.3 – Parts of a semantic version number (source: Devopedia 2020, https://devopedia.org/images/article/279/2766.1593275997.svg)
When a new version is released, the version number is incremented following the SemVer rules:
Major versions add incompatible API changesMinor versions add functionality in a backward-compatible mannerPatch versions add backward-compatible bug fixesFollowing these rules, we can easily upgrade the Node.js version in any project without breaking the code when the changes are cataloged as minor or a patch.
If we want to upgrade to a new major version, we will need to check whether there are any breaking changes that we need to address before upgrading. In most cases, the breaking changes are not related to our own code but to the dependencies that we are using in the project.
Important note
Metadata is optional, and it is not used to define the version of the software but provides additional information. In general, we will try to avoid using versions with metadata as they are not stable versions but they can be used for testing purposes.
Before we move on to the release schedule, it is important to understand how we can check the details of any release. This is very important if we plan to upgrade to a major version, as it contains breaking changes.
In this case, we will analyze the Node.js 20.0.0 release, so we can see the details of the latest LTS version through the blog details: https://nodejs.org/en/blog/release/v20.0.0/.
Every release has a structured blog post with the following information:
Summary: Here, we can find a brief description of the release.Notable Changes: Here, we can find the most important changes in the release, including examples and a lot of contexts behind the new features or deprecations. We can also see the more relevant changes in the dependencies that may affect the Node.js APIs.Semver-(*) Commits: Here, we can find the commits that are related to the SemVer changes (Semver-Major Commits, Semver-Minor Commits, and Semver-Patch Commits) and access the code changes directly using the commits reference.Information
The release information is available directly in the changelog. The changelog version includes references to all the commits and pull requests included in the release, so it is a great source of information when you need to migrate from another Node.js version. You can find the changelog version at https://github.com/nodejs/node/blob/main/doc/changelogs/CHANGELOG_V20.md#2023-04-18-version-2000-current-rafaelgss.
One of the best ways to explore the change in a release in more detail is to directly use the Node.js documentation – for example, https://nodejs.org/dist/latest-v20.x/docs/api/. The website offers the option to navigate through the different versions so we can check the changes in the APIs between versions more easily.
Figure 1.4 – Node.js official documentation screenshot
The Node.js project has a release schedule that is published on the official website (https://nodejs.org/en/about/releases/) and it is updated by the Node.js Release Working Group.
Figure 1.5 – Official release schedule from the Node.js website
In Node.js, releases have three different phases:
Current is the phase where new features (non-major changes) are added to the project. This phase is very active, and it is not always recommended to use it in production as it is not a stable version.Active Long-Term Support (LTS) is the phase where the version is stable and has been updated by the LTS team. This phase still includes new features, bug fixes, and updates. This phase is stable, so it is recommended to use it in production.Maintenance is the phase where the version is not receiving any new features, only critical bug fixes and security updates. This phase is recommended for projects that are not able to upgrade yet to the latest active LTS version.Important note
Odd-numbered release lines are not promoted to active LTS, so they are not recommended for production use.
As of today, for any new project, I will recommend using the latest LTS version, which is 20.11.0. This version will be supported until April 2026, so it is a good choice for any new project.
For any existing project using Node.js v18, it is recommended to start migrating to Node.js 20 as v18 is entering the maintenance phase.
Important note
While releasing a new version seems like an easy task, it is not. The Release Working Group has defined the complete process, which includes more than 20 steps. You can find all the relevant information in the official documentation (https://github.com/nodejs/node/blob/main/doc/contributing/releases.md) or this talk: The Life and Times of a Node.js Release, by Danielle Adams at NodeConf EU 2022 (https://www.youtube.com/watch?v=OiSBodpU174).
In this chapter, we explored what makes Node.js so special and how it differs from other backend systems. We also covered the history of Node.js and how it has evolved over the years.
Additionally, we covered the Node.js architecture and how it works under the hood. We learned about the event loop and how it allows Node.js to handle many concurrent requests efficiently.
In the next chapter, we will learn how to set up the development environment and start using Node.js.
To use Node.js, we first need to prepare our development environment. In this chapter, we will cover the details of how to install Node.js and check that everything is working as expected, so we can execute JavaScript and Node.js.
Node.js is one of the most simple and easy-to-install software, so we will not spend too much time on this topic. However, we will cover some important details that you need to know in order to be able to work with Node.js in any environment.
To sum up, here are the main topics that we will explore in this chapter:
Installing Node.js in any environmentManaging Node.js versionsUsing Chrome DevTools and the Node.js REPL to interact with JavaScript and Node.js.In this chapter, you will learn how to properly set up Node.js in any environment, such as Windows, Linux, or macOS. This knowledge will also be applicable when you deploy your projects to the cloud or a specific device.
Additionally, you will learn how to debug any issues using the debugging tools included in your web browsers and the Node.js REPL.
Finally, you will learn how to manage multiple versions of Node.js running on the same machine. This skill will be very useful when you need to migrate a project between different Node.js versions.
The code files for the chapter can be found at https://github.com/PacktPublishing/NodeJS-for-Beginners.
Check out the code in action video for this chapter on https://youtu.be/xElsOS9Pz4k
Node.js can be installed in three different ways:
Downloading the binaries from the official website: This is the recommended option for beginners, as it is the easiest way to install Node.js. You just need to download the binaries from the official website and execute the installer.Using a package manager: This is the most common way to install Node.js in Linux, FreeBSD, IBM i, Android, and similar environments. You just need to use your system’s package manager and install Node.js from there.Build from source: This is the most advanced way to install Node.js and opens the door to many customizations, and it is only recommended for advanced users. You need to download the source code from the official repository and compile it on your machine.Important note
As part of Node.js continuous integration, there are many different environments and architectures where Node.js is tested, which means that Node.js maintains solid cross-platform support over time.
While writing this book, the latest Node.js version is 20.11.0, so we will use this version as a reference. However, you can use the last LTS version available, as the installation process is the same for all versions.
The upcoming sections will explain how to install Node.js on various operating systems, beginning with macOS.
The easiest way to install Node.js on macOS is by downloading the binaries from the official website. You just need to go to the Node.js download page at https://nodejs.org/en/download/, download the macOS installer, and follow the installation wizard.
You can also install Node.js using a package manager, but this is not recommended for beginners. If you want to install Node.js using a package manager, you can use Homebrew (https://brew.sh/) or MacPorts (https://www.macports.org/).
To use Homebrew, open your Terminal and type the following command, which will manage the installation process for you:
brew install nodeTo use MacPorts, open the Terminal and type the following command to start the installation process:
port install nodejs20Next, we’ll see how to install it on Windows.
The easiest way to install Node.js on Windows is by downloading the binaries from the official website.
You just need to go to the Node.js download page at https://nodejs.org/en/download/, download the Windows installer, and follow the installation wizard.
Let’s see how to install it on Linux next.
The best way is to install Node.js using your package manager, but you can also use the binaries distributed by NodeSource (https://github.com/nodesource/distributions/blob/master/README.md). This will cover Debian and Ubuntu-based distributions (deb) as well as Enterprise Linux-based distributions (rpm).
Let’s look at an example using Ubuntu.
First, download the setup script from NodeSource using curl:
curl -sL https: //deb .nodesource. com/setup_20. x -o / tmp/ nodesource_setup. shThen, review the content of the script (optional):
cat /tmp/nodesource_setup.shFinally, execute the script as root and install Node.js:
sudo bash /tmp/nodesource_setup.sh sudo apt install nodejsThe Node.js Build Working Group provides an official platform list that includes all the supported platforms and architectures with their different tiers of support. You can find it at https://github.com/nodejs/node/blob/main/BUILDING.md#platform-list.
Additionally, Node.js has an initiative called the unofficial-builds project that provides support for other platforms and architectures, including loong64, riscv64, linux-armv6l, linux-x86, linux-x64-glibc-217, and linux-x64-musl. You can find more information at https://github.com/nodejs/unofficial-builds.
If you have solid skills with Docker, you can also use the official Docker images provided by Node.js to avoid installing the Node.js binaries on your machine (https://hub.docker.com/_/node).
Node.js is shipped with npm. We will now check that both Node.js and npm are installed correctly. The installed versions can be different depending on the Node.js version that you have installed, but if it is not throwing an error, the installation was correct.
We will use the terminal to check that the installation was done properly for both (Node.js and npm).
To verify the Node.js installation, open your terminal and type the following command:
node –vThe expected output is the Node.js version installed:
v20.11.0To verify that npm is installed, type the following command:
npm -vThe expected output is the npm version installed:
10.2.4Congratulations! You just installed Node.js on your machine! In the next section, we will get familiarized with the Node.js versions so we will have a better understanding of which Node.js version we should use for our next project.
Node.js is a fast-moving project, so new versions are released every few months. To manage the Node.js versions on your machine, you will need to use a Node.js version manager.
There are several Node.js version managers available, but the most popular are as follows:
Node Version Manager (nvm): https://github.com/nvm-sh/nvmn: https://github.com/tj/nFast Node Manager (fnm): https://github.com/Schniz/fnmVolta: https://github.com/volta-cli/voltaIn this book, we will use nvm as the Node.js version manager, but you can use any other version manager that you prefer.
Important info
In production environments, you should use the latest LTS version available, as this version is the most stable and is supported for a longer time. In most cases, there is no need to install a version manager on your production machine, as you will use a specific version.
Now that we are familiar with how the Node.js versions are organized, we will need some tools to help us handle several Node.js versions in the same environment. We will start in the next section with nvm.
nvm is the most popular and beginner-friendly way to manage multiple Node.js versions on your machine.
I use nvm to manage my Node.js versions, as it is a great tool, but nvm can be tricky to install so you will need to follow the installation instructions carefully. There is a troubleshooting guide with common issues and solutions at https://github.com/nvm-sh/nvm#installing-and-updating.
This is my preferred way to install nvm in macOS, as it is the easiest way to install it:
brew install nvmFor Linux and macOS, download and execute the installation script from the official repository:
curl -o- https: //raw. githubusercontent. com/ nvm- sh/ nvm/v0. 39.3/install. sh | bashnvm doesn’t work in Windows, so if you are using Windows, you will need to use another version manager or Windows Subsystem for Linux (WSL).
Alternatives to nvm for Windows are as follows:
nodist: https://github.com/nullivex/nodistnvm-windows: https://github.com/coreybutler/nvm-windowsNode Version Switcher (NVS): https://github.com/jasongin/nvsOnce you have installed nvm, you can use it to install and manage Node.js versions.
In order to use a specific Node.js version, you will need to install it first:
nvm install 20.11.0Then, you can use it:
nvm use 20.11.0 # Now using node v20.11.0 (npm v10.2.4)You can check the Node.js version in use with the following:
node -v # v20.11.0You can also set a default Node.js version for your machine:
nvm alias default 20.11.0You can list the installed Node.js versions with the ls command:
nvm lsThe output will be a list of all the installed Node.js versions.
We can list the available Node.js versions with the ls-remote command:
nvm ls-remoteThe output will be a list of all the available Node.js versions, and it is a very long list!
We tend to accumulate Node.js versions over time, so it is a good practice to uninstall the Node.js versions that you are not using anymore.
To uninstall a Node.js version, you will need to use the uninstall command:
nvm uninstall 20.11.0You can also use a .nvmrc file to specify the Node.js version that you want to use in a project. This is useful when you are working on a project with other developers and you want to make sure that everyone is using the same Node.js version.
To use a .nvmrc file, you will need to create a file called .nvmrc in the root of your project with the Node.js version that you want to use:
20.11.0Then, nvm can use the Node.js version specified in the .nvmrc file when you enter the project directory and run the following command:
nvm use # Now using node v20.11.0 (npm v10.2.4)If the Node.js version specified in the .nvmrc file is not installed, nvm will throw an error and will not change the Node.js version in use:
