The Complete Developer: Master the Full Stack with TypeScript, React, Next.js, MongoDB, and Docker
()
About this ebook
Whether you’ve been in the developer kitchen for decades or are just taking the plunge to do it yourself, The Complete Developer will show you how to build and implement every component of a modern stack—from scratch.
You’ll go from a React-driven frontend to a fully fleshed-out backend with Mongoose, MongoDB, and a complete set of REST and GraphQL APIs, and back again through the whole Next.js stack.
The book’s easy-to-follow, step-by-step recipes will teach you how to build a web server with Express.js, create custom API routes, deploy applications via self-contained microservices, and add a reactive, component-based UI. You’ll leverage command line tools and full-stack frameworks to build an application whose no-effort user management rides on GitHub logins.
You’ll also learn how to:
- Work with modern JavaScript syntax, TypeScript, and the Next.js framework
- Simplify UI development with the React library
- Extend your application with REST and GraphQL APIs
- Manage your data with the MongoDB NoSQL database
- Use OAuth to simplify user management, authentication, and authorization
- Automate testing with Jest, test-driven development, stubs, mocks, and fakes
Covers: Docker, Express.js, JavaScript, Jest, MongoDB, Mongoose, Next.js, Node.js, OAuth, React, REST and GraphQL APIs, and TypeScript
Related to The Complete Developer
Related ebooks
Hands-On Microservices with JavaScript: Build scalable web applications with JavaScript, Node.js, and Docker Rating: 0 out of 5 stars0 ratingsTypeScript in Action: Building Modern Web Applications with TypeScript Rating: 0 out of 5 stars0 ratingsAngularJS Web Application Development Blueprints Rating: 0 out of 5 stars0 ratingsReact JS and Express Framework: A Comprehensive Guide Rating: 0 out of 5 stars0 ratingsThe JavaScript Journey: From Basics to Full-Stack Mastery Rating: 0 out of 5 stars0 ratingsFrom JavaScript to TypeScript: Navigating the Modern Web Transition Rating: 0 out of 5 stars0 ratingsAdvanced Express Web Application Development Rating: 0 out of 5 stars0 ratingsTypeScript Programming: From Basics to Expert Proficiency Rating: 0 out of 5 stars0 ratingsMastering the Art of Node.js Programming: Unraveling the Secrets of Expert-Level Programming Rating: 0 out of 5 stars0 ratingsJavascript Mastery: In-Depth Techniques and Strategies for Advanced Development Rating: 0 out of 5 stars0 ratingsNode.js: The Definitive Resource Rating: 0 out of 5 stars0 ratingsModern Full-Stack React Projects: Build, maintain, and deploy modern web apps using MongoDB, Express, React, and Node.js Rating: 0 out of 5 stars0 ratingsModernizing Legacy Applications in PHP Rating: 0 out of 5 stars0 ratingsWeb Services and XML The Ultimate Step-By-Step Guide Rating: 0 out of 5 stars0 ratingsThe Ultimate TypeScript Developer's Handbook : A Comprehensive Journey for New Developers Rating: 0 out of 5 stars0 ratingsGit Repository Management in 30 Days: Learn to manage code repositories like a pro (English Edition) Rating: 0 out of 5 stars0 ratings200+ JavaScript Programs for Beginners Rating: 0 out of 5 stars0 ratingsA Pythonic Adventure: From Python basics to a working web app Rating: 0 out of 5 stars0 ratingsCSS Mastery: Styling Web Pages Like a Pro Rating: 0 out of 5 stars0 ratingsNoSQL Essentials: Navigating the World of Non-Relational Databases Rating: 0 out of 5 stars0 ratingsHybrid Mobile Development with Ionic Rating: 0 out of 5 stars0 ratingsWeb Development with Blazor: A practical guide to building interactive UIs with C# 12 and .NET 8 Rating: 0 out of 5 stars0 ratingsSecuring the CI/CD Pipeline: Best Practices for DevSecOps Rating: 0 out of 5 stars0 ratingsMastering Python: A Journey Through Programming and Beyond Rating: 0 out of 5 stars0 ratingsJump Start Web Performance Rating: 0 out of 5 stars0 ratingsGoogle Cloud Run for DevOps: Automating Deployments and Scaling Rating: 0 out of 5 stars0 ratings
Internet & Web For You
More Porn - Faster!: 50 Tips & Tools for Faster and More Efficient Porn Browsing Rating: 3 out of 5 stars3/5How to Be Invisible: Protect Your Home, Your Children, Your Assets, and Your Life Rating: 4 out of 5 stars4/5Coding For Dummies Rating: 5 out of 5 stars5/548 Really Useful Web Sites Rating: 5 out of 5 stars5/5Everybody Lies: Big Data, New Data, and What the Internet Can Tell Us About Who We Really Are Rating: 4 out of 5 stars4/5The $1,000,000 Web Designer Guide: A Practical Guide for Wealth and Freedom as an Online Freelancer Rating: 4 out of 5 stars4/5No Place to Hide: Edward Snowden, the NSA, and the U.S. Surveillance State Rating: 4 out of 5 stars4/5Python: Learn Python in 24 Hours Rating: 4 out of 5 stars4/5Coding All-in-One For Dummies Rating: 4 out of 5 stars4/5The Digital Marketing Handbook: A Step-By-Step Guide to Creating Websites That Sell Rating: 5 out of 5 stars5/5The Gothic Novel Collection Rating: 5 out of 5 stars5/5The Beginner's Affiliate Marketing Blueprint Rating: 4 out of 5 stars4/5Cybersecurity For Dummies Rating: 5 out of 5 stars5/5JavaScript All-in-One For Dummies Rating: 5 out of 5 stars5/5Ultimate guide for being anonymous: Avoiding prison time for fun and profit Rating: 5 out of 5 stars5/5How to Disappear and Live Off the Grid: A CIA Insider's Guide Rating: 0 out of 5 stars0 ratingsSurveillance and Surveillance Detection: A CIA Insider's Guide Rating: 3 out of 5 stars3/5UX/UI Design Playbook Rating: 4 out of 5 stars4/5Beginner's Guide To Starting An Etsy Print-On-Demand Shop Rating: 0 out of 5 stars0 ratingsThe Hacker Crackdown: Law and Disorder on the Electronic Frontier Rating: 4 out of 5 stars4/5Introduction to Internet Scams and Fraud: Credit Card Theft, Work-At-Home Scams and Lottery Scams Rating: 4 out of 5 stars4/5Ready, Set, Brand!: The Canva for Work Quickstart Guide Rating: 5 out of 5 stars5/5Notion for Beginners: Notion for Work, Play, and Productivity Rating: 4 out of 5 stars4/5How To Start A Profitable Authority Blog In Under One Hour Rating: 5 out of 5 stars5/5The Darknet Superpack Rating: 0 out of 5 stars0 ratingsPrinciples of Web Design Rating: 0 out of 5 stars0 ratingsSEO For Dummies Rating: 4 out of 5 stars4/5
Reviews for The Complete Developer
0 ratings0 reviews
Book preview
The Complete Developer - Martin Krause
INTRODUCTION
Nearly all programming jobs today require at least a cursory understanding of full-stack development, but if you’re a beginner, you might struggle to find the right entry point to this overwhelming topic. You might not even know what the term means.
Simply put, full-stack web development typically refers to the creation of complete web applications using JavaScript and the many frameworks built for it. It requires a mastery of the traditional disciplines of frontend and backend development, as well as the ability to write middleware and various kinds of application programming interfaces (APIs).
Lastly, a well-rounded full-stack developer can handle databases and has professional skills, such as the ability to craft automated tests and deploy their code by themselves. To do all of this, they must understand HTML, CSS, and JavaScript, as well as the language’s typed counterpart, TypeScript. For a crash course on some of this terminology, see The Parts of a Full-Stack Application
on page xxiv.
If this sounds like a lot, you’ve come to the right place. This book will introduce you to each component of a modern application and teach you how to use some of the most widely used technologies to build them.
Who Should Read This Book?
There are two primary audiences for the book. The first includes professional frontend or backend engineers who want to advance their careers by mastering full-stack development. The second includes inexperienced, beginning developers interested in learning about web development.
While the book introduces many technologies from scratch, it assumes some prior familiarity with HTML, CSS, and JavaScript, as well as the client/server architecture of most web applications. For a refresher, see The Coding Workbook by Sam Taylor (No Starch Press, 2020), which teaches you how to build a website with HTML and CSS, and The Book of CSS3, 2nd edition, by Peter Gasston (No Starch Press, 2014) to sharpen your CSS skills. To familiarize yourself with JavaScript, I recommend JavaScript Crash Course by Nick Morgan (No Starch Press, 2024), which is a fast-paced JavaScript tutorial for beginners, and Eloquent JavaScript, 3rd edition, by Marijn Haverbeke (No Starch Press, 2018), for a deep dive into JavaScript.
What’s in This Book?
The book is split into two parts. Part I, comprising Chapters 1 through 10, introduces you to the components of a modern technology stack. Each chapter focuses on one technology and highlights the topics you need to know as a full-stack developer. The exercises will encourage you to begin writing application code from page 1.
Chapter 1: Node.js Introduces you to Node.js and its ecosystem, which let you run JavaScript code outside a browser. Then you’ll use Node.js and the Express.js framework to create your own simple web server with JavaScript.
Chapter 2: Modern JavaScript Focuses on contemporary JavaScript syntax useful for full-stack developers, including how to use modules to write maintainable code packages. We look at the different ways to define variables and constants, the arrow function, and techniques for asynchronous code. You’ll use these to rewrite your JavaScript server.
Chapter 3: TypeScript Introduces TypeScript, a superset of JavaScript, and highlights how modern full-stack development benefits from it. We discuss the shortcomings and pitfalls of JavaScript and how to effectively leverage TypeScript’s type system through inference. You’ll conclude the chapter by refactoring your JavaScript server with type annotations, custom types, and interfaces.
Chapter 4: React Discusses React, one of the most common libraries for creating user interface components. You’ll see how its components simplify full-stack development and learn how to use its JSX elements, the virtual DOM, and hooks. You’ll then use React to add a reactive user interface to your Express.js server.
Chapter 5: Next.js Focuses on Next.js, the leading web application framework built on top of React. You’ll create pages and custom API routes with Next.js’s file-based routing before learning different ways to render a page within the framework. Finally, you’ll migrate the Express.js server to Next.js as an exercise.
Chapter 6: REST and GraphQL APIs Teaches you all about APIs, what they are, and how to use them for full-stack web development. We explore two kinds of APIs: REST and GraphQL. You’ll conclude the chapter by adding an Apollo GraphQL server to your Next.js full-stack application.
Chapter 7: MongoDB and Mongoose Discusses the differences between traditional relational databases and non-relational databases such as MongoDB. You’ll add the Mongoose object data modeling tool to your technology stack to simplify working with a database. You’ll then connect the GraphQL API to your own MongoDB database.
Chapter 8: Testing with the Jest Framework Explains the importance of automated tests and test-driven development to full-stack development. We explore different types of tests, common test patterns, and the concepts of test doubles, stubs, fakes, and mocks. Lastly, you’ll add a few basic snapshot tests to your Next.js application with the Jest framework.
Chapter 9: Authorization with OAuth Discusses authentication and authorization and how full-stack developers can use the OAuth protocol to handle those tasks by integrating with a third-party service. We walk through this authorization flow and its components. You’ll run through a complete OAuth interaction on the command line to explore each step in depth.
Chapter 10: Containerization with Docker Introduces you to using Docker to deploy your application. We cover the concept of a microservice architecture, then cover all relevant components of the Docker ecosystem: the host, the Docker daemon, Dockerfiles, images, containers, volumes, and Docker Compose. You’ll conclude by splitting your application into self-contained microservices.
In Part II, you’ll use your newfound knowledge to build a web application that applies the concepts, tools, and frameworks introduced in Part I. The Food Finder application is a location search service that lets users log in with their GitHub account and maintain a wish list of places to visit.
Chapter 11: Setting Up the Docker Environment Create the foundation of your Food Finder application by using your knowledge of Docker and containerization to set up your development environment. You’ll use Docker Compose to decouple the application development from your local system and then add a MongoDB server as its own service.
Chapter 12: Building the Middleware Create the first part of the Food Finder application’s middleware. Here you’ll connect Mongoose to the MongoDB service and create its schema, model, services, and custom types. With these pieces in place, you’ll be able to create, read, update, and delete data from your database.
Chapter 13: Building the GraphQL API Use your knowledge of GraphQL to add an Apollo GraphQL server to your Food Finder application, then implement a public GraphQL API. You’ll be able to use the Apollo sandbox to read and update data with GraphQL on your MongoDB server.
Chapter 14: Building the Frontend Use React components and the Next.js framework to build the frontend for the Food Finder application. At this point, you’ll have implemented a complete modern full-stack application that reads data from the database through your custom middleware and renders the data to your application’s frontend.
Chapter 15: Adding OAuth Add an OAuth flow to your app so that visitors can log in to maintain a personal wish list of locations. You’ll use the next-auth package from Auth.js to add login options using GitHub.
Chapter 16: Running Automated Tests in Docker Set up automated snapshot tests with Jest and configure a new service to run the tests automatically.
Then, in the appendices, you’ll get detailed information on the TypeScript Compiler options and the most common Jest matchers. Also, you’ll use your newfound knowledge to explore and understand Next.js’s modern app directory approach.
Appendix A: TypeScript Compiler Options Shows the most common TypeScript Compiler (TSC) options so that you can customize your own TypeScript projects to your liking.
Appendix B: The Next.js app Directory Explores a new routing pattern using the app directory that Next.js introduced in version 13. You can then choose to work with either the traditional pages approach covered in Chapter 5 or the modern app directory in your own upcoming projects.
Appendix C: Common Matchers Shows the most common matchers for testing your applications with Jest and the Jest DOM.
The Parts of a Full-Stack Application
Throughout this book, we’ll discuss various portions of an application. This section gives you a crash course on what we mean when we use the terms frontend, middleware, and backend.
The Frontend
The frontend is the user-facing part of a website or web application. It runs on the client, typically a web browser. You can think of it as the front office
of the web application. For example, on https://www.google.com, the frontend is a page with a simple search bar, though of course, frontend development can be much more complex than this; take a look at Google’s search results page or the interface of the last website you visited.
Frontend developers focus on user engagement, experiences, and interfaces. They rely on HTML for creating the elements of the website’s interface, CSS for styling, JavaScript for user interactions, and frameworks such as Next.js to pull everything together.
The Middleware
The middleware connects an application’s frontend and backend and performs all of its chores, such as integrating with third-party services and transferring and updating data. You can think of it as the employees on the company floor.
As full-stack developers, we often write middleware for routing our applications, which means serving the correct data for a particular URL, handling database connections, and performing authorization. For example, on https://www.google.com, the middleware asks the server for the landing page’s HTML. Then a different part of the middleware checks whether the user is logged in, and if so, which personal data it should show. Meanwhile, a third part of the middleware consolidates the information from each of these data streams and then answers the server’s requests with the correct HTML.
One essential part of a full-stack application’s middleware is its API layer, which exposes the application’s APIs. Generally, an API is code written to connect two machines. Often, an API lets the frontend code (or a third party) access the application’s backend. JavaScript-driven development relies on two primary architectural frameworks for creating APIs: REST and GraphQL, both of which are covered in Chapter 6.
You could write the middleware by using any programming language. Most full-stack developers use modern JavaScript or TypeScript, but they could instead use PHP, Ruby, or Go.
The Backend
The backend is the invisible part of a web application. In a JavaScript-driven application, the backend runs on a server, typically Express.js, though others might use Apache or NGINX. You can think of it as the back office
of the web application.
More concretely, the backend handles any operations involving the application’s data. It performs create, read, update, and delete (CRUD) operations on the values stored in the database and returns the datasets requested by the user through the middleware’s API layer. For https://www.google.com, the backend is the code that searches the database for the keywords you entered in the frontend, which the backend received through the middleware. The middleware would combine these search results with other relevant pieces of information. Then the user would see the search results page rendered by the frontend.
Backend development can be done in any programming language. Full-stack developers usually employ modern JavaScript or TypeScript. Other options include PHP, Ruby, Elixir, Python, Java, and frameworks like Symfony, Ruby on Rails, Phoenix, and Django.
A Brief History of JavaScript and Full-Stack Development
All developers should understand the context of the tools they’re using. Before we begin developing, let’s start with a bit of history.
The full-stack developer position evolved alongside JavaScript, which began as nothing more than a scripting language that ran in users’ browsers. Developers used it to add elements to their websites, such as accordions, pop-up menus, and overlays, that reacted immediately to a user’s behavior, without requiring requests to the application’s server.
Until the late 2000s, most JavaScript libraries were designed to provide consistent interfaces to handle vendor-specific quirks. Often, the JavaScript engines were slow, especially when interacting with, updating, or modifying the HTML. Hence, JavaScript was considered a quirky scripting language for the frontend and was frowned upon by backend developers.
Several projects attempted to popularize the use of JavaScript in the backend, but until the release of Node.js in 2009, these didn’t gain any traction. Node.js, covered in Chapter 1, is a JavaScript tool for developing backends. Shortly thereafter, the Node.js package manager npm built the missing ecosystem for full-stack JavaScript development.
This ecosystem includes a host of JavaScript libraries for working with databases, building user interfaces, and writing server-side code (many of which we’ll explore in this book). These new tools allowed developers to use JavaScript reliably on both the client and the server. Of particular importance, Google released the Angular framework in 2010, and Meta (known as Facebook at the time) released React in 2013. The commitment of these internet giants to building JavaScript tools turned full-stack web development into a sought-after role.
Setting Up
Throughout this book, you’ll write code and run command line tools. You can use any development environment you’d like, but here are some guidelines.
The most common code editor these days is Visual Studio Code, which you can download from https://code.visualstudio.com. It is Microsoft’s open source editor and is free for Windows, macOS, and Linux. In addition, you can extend and configure it through a plethora of third-party plug-ins and adjust its appearance to your liking. However, if you’re used to a different editor, such as Vim or Emacs, you can keep using it. The book doesn’t require a particular tool.
Depending on your operating system, your default command line program will be either the Command Prompt (on Windows) or the Terminal (on macOS and Linux). These programs use slightly different syntax for tasks like creating, changing, and listing the contents of a directory. This book shows the Linux and macOS versions of these commands. If you’re using Windows, you’ll have to adapt the commands for your operating system. For example, instead of ls, Windows uses dir to list files and folders in the current directory. Microsoft’s official command line reference lists all available commands here: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/windows-commands#command-line-reference-a-z.
The most notable difference between operating systems relevant to this book is the escape character used for line breaks in multiline cURL commands. This escape character is \ on macOS and ^ on Windows. We’ll point out these differences in Chapter 6, when we first use cURL.
You can download the code listings for the first part of the book and the complete source code for the Food Finder application from https://www.usemodernfullstack.dev/downloads.
PART I
THE TECHNOLOGY STACK
1
NODE.JS
Node.js is an open source runtime environment that executes JavaScript code outside a web browser. You could, for example, use it as a scripting language to perform all kinds of chores, such as deleting and moving files, logging data on the server side, or even creating your own web server (as we’ll do in this chapter’s exercise).
Knowing how to use Node.js is not really about understanding individual commands or packages, because it relies on standard JavaScript and you can refer to the documentation for details about its syntax and parameters. Instead, all developers should strive to understand the Node.js ecosystem and use it to their advantage. This chapter will introduce you to it.
Installing Node.js
Begin by checking whether Node.js is already available on your local machine by running the node command from your command line. The version flag (-v) should return the current Node.js version:
$ node -v
If you see an output with a version number, Node.js is installed. If you don’t, or if the version is lower than the currently recommended stable release listed on https://nodejs.org, you should install this stable version.
To install Node.js locally, go to https://nodejs.org/en/download and select the installer for your operating system. I recommend installing the long-term support (LTS) version of Node.js because many Node.js modules require this version. Run the installer package for Node.js LTS and npm, then check the version number again. It should match the one you’ve just installed.
Next, we’ll review the basic commands and features of the Node.js runtime environment. If you prefer not to install Node.js, you can run the Node.js command line examples and JavaScript code in the online playgrounds at https://codesandbox.io/s/new and https://stackblitz.com.
Working with npm
The default package manager for Node.js is npm. You can find modules for every task there, taken from the online registry at https://www.npmjs.com. Verify that npm is available on your local machine by running the following on the command line:
$ npm -v
If there is no listed version or if the version is lower than the current release, install the latest Node.js LTS version, including npm.
Be aware that there is no vetting process or quality control on https://www.npmjs.com. Anyone can publish packages, and the site relies on the community to report any that are malicious or broken.
Running the following shows a list of available commands:
$ npm
NOTE
The most popular alternative to npm is yarn, which also uses the https://www.npmjs.com registry and is fully compatible with npm.
The package.json File
The package.json file is a key element of each Node.js-based project. While the node_modules folder contains actual code, the package.json file holds all the metadata about the project. Found in the project’s root, it must contain the project’s name and version; in addition, it can contain optional data, such as the project’s description, a license, scripts, and many more details.
Let’s take a look at the package.json file for the web server you’ll create in Exercise 1 on page 13. It should look similar to the one shown in Listing 1-1.
{
name
: sample-express
,
version
: 1.0.0
,
description
: sample express server
,
main
: index.js
,
scripts
: {
test
: echo \"Error: no test specified\" && exit 1
,
run
: node index.js
},
author
: ,
license
: ISC
,
dependencies
: {
express
:^4.18.2
}
}
Listing 1-1: The package.json file for the Express.js server project in Exercise 1
The package.json file includes all the information others will need to install required modules on their machine and run the application. As a result, you never have to ship or store the node_modules folder in your code repository, which minimizes the repository’s size. Let’s take a detailed look at the package.json file.
Required Fields
The package.json file must contain a name field and a version field. All other fields are optional. The name field contains the package’s name, which must be one lowercase word but can contain hyphens and underscores.
The version field must follow semantic versioning guidelines, which suggest this format: major.minor.patch; for example, 1.2.3. We call this semantic versioning because each number conveys a meaning. A major version introduces an incompatible API change. You should generally be very careful about switching to another major version, as you won’t be able to expect that your application will work flawlessly. A minor version change adds new functionality in a backward-compatible manner and therefore shouldn’t pose problems for your application. A patch version applies backward-compatible bug fixes, and you should always keep it up to date.
NOTE
You can read more about semantic versioning and how to define different ranges at https://semver.org.
Dependencies
The most important optional fields specify the dependencies and development dependencies. The dependencies field lists all the dependencies needed to run the project, along with their required version ranges, following the semantic versioning syntax. By default, npm requires only the major version and keeps the minor and patch ranges flexible. This way, npm can always initialize your project with the latest compatible version.
These dependencies are part of your bundled application. When you install a project on a new machine, all dependencies listed in the package .json file will be installed and placed in the node_modules folder, next to package.json.
Your application could require all sorts of dependencies, such as frameworks and helper modules. For example, the Food Finder application we’ll build in Part II must contain at least Next.js as a single-page application framework, and Mongoose with MongoDB for the database layer.
Development Dependencies
The devDependencies field lists all the dependencies necessary to develop the project, along with their versions. Again, only the major version is fixed. These are required only to develop, and not to run, the application. Hence, they are ignored by the packaging scripts and are not part of the deployed application. When you install a project on a new machine, all the development dependencies listed in the package.json file will be installed and placed in the node_modules folder next to package.json. For our Food Finder application, our development dependencies will include TypeScript’s type definitions. Other typical entries are testing frameworks, linters, and build tools such as webpack and Babel.
The package-lock.json File
The npm package manager automatically generates the package-lock.json file for each project. This lock file resolves a problem introduced by the use of semantic versioning for dependencies. As mentioned earlier, the npm default is to define only the major version and to use the latest minor and patch versions available. While this ensures that your application includes the latest bug fixes, it introduces a new issue: without an exact version, builds aren’t reproducible. Because there’s no quality control in the npm registry, even a patch or minor version update could introduce an incompatible API change that should have been a major version change. Consequently, a slight deviation between versions could result in a broken build.
The package-lock.json file solves this by tracking the exact version of every package and its dependencies. This file is usually quite big, but its entries for the web server you’ll create at the end of this chapter will look similar to Listing 1-2.
{
name
: sample-express
,
lockfileVersion
: 2,
requires
: true,
packages
: {
: {
dependencies
: {
express
: ^4.18.2
}
},
node_modules/accepts
: {
version
: 1.3.8
,
resolved
: https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz
,
integrity
: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEhosdQ==
,
--snip--
},
--snip--
node_modules/express
: {
version
: 4.18.2
,
resolved
: https://registry.npmjs.org/express/-/express-4.18.2.tgz
,
integrity
: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEI==
,
dependencies
: {
accepts
: ~1.3.8
,
--snip--
vary
: ~1.1.2
},
engines
: {
node
: >= 0.10.0
}
},
--snip--
vary
: {
version
: 1.1.2
,
resolved
: https://registry.npmjs.org/vary/-/vary-1.1.2.tgz
,
integrity
: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+bfhskkh==
}
}
}
Listing 1-2: The package-lock.json file for Exercise 1
The lock file contains a reference to the project and lists the information from the corresponding package.json file. Then it lists all the project’s dependencies; for us, the only dependency is Express.js, with a pinned version. (We’ll cover Express.js in Exercise 1.) In addition, the file lists all the dependencies for the Express.js version in use, in this case the accept and vary packages. The stored artifact’s SHA hash enables npm to verify the integrity of the resource after downloading it.
Now, with all modules version-locked, every npm install command will create an exact clone of the original setup. Like package.json, the package-lock.json file is part of the code repository.
Creating a Project
Let’s cover the most important commands for your day-to-day work, in the order in which you would logically use them to create and maintain a project. After performing these steps, you’ll have a package.json file and a production-ready project folder with one installed package, Express.js.
Initializing a New Module or Project
To start a new project, run npm init, which initializes a new module. This should trigger an interactive guide through which you’ll populate the project’s package.json file based on your input:
$ mkdir sample-express
$
cd sample-express
$
npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
--snip--
Is this OK?
(yes)
At the beginning of each project, you need to initialize a new Node.js setup in an empty folder (created here with mkdir sample-express) using npm init. For simplicity, keep the default suggestions here. The assistant creates a basic package.json file in your project folder. It should look similar to Listing 1-3.
{
name
: sample-express
,
version
: 1.0.0
,
description
: ,
main
: index.js
,
scripts
: {
test
: echo \"Error: no test specified\" && exit 1
},
author
: ,
license
: ISC
}
Listing 1-3: The default package.json file
When we compare this file with the one shown in Listing 1-1, we see that they are fairly similar, except for the dependencies and development dependencies. With the package.json file ready, we can now install these dependencies with npm install.
Installing the Dependencies
Node.js provides modules for tasks like accessing the filesystem’s input and output, using networking protocols (such as DNS, HTTP, TCP, TLS/SSL, and UDP), and handling binary data. It also provides cryptography modules, interfaces for working with data streams, and much more.
Running npm install
Say you want to create a new Express.js-based server. You’ll need to install the Express.js package from https://npmjs.com. Here we install a particular version, but to install the latest version, omit the version number and use npm install express instead:
$ npm install [email protected]
added 57 packages, and audited 58 packages in 1s
found 0 vulnerabilities
Now the node_modules folder contains an express folder and additional folders with its dependencies. Also, Express.js is listed as a dependency in package.json, as shown in Listing 1-4.
{
name
: sample-express
,
version
: 1.0.0
,
description
: ,
main
: index.js
,
scripts
: {
test
: echo \"Error: no test specified\" && exit 1
},
author
: ,
license
: ISC
,
dependencies
: {
express
: ^4.18.2
}
}
Listing 1-4: The default package.json file with Express.js as a dependency
We’ve successfully added Express.js as a dependency.
Installing the Development Dependencies
Now let’s say you want to use a package called karma for end-to-end testing of the server. Instead of being a dependency like Express.js, this package is used only during development and is not necessary for running the actual application.
In cases like this, you should run npm install --save-dev package to download this package and add it to the devDependencies list in the local package.json file:
$ npm install --save-dev [email protected]
added 128 packages, and audited 186 packages in 3m
9 vulnerabilities (1 moderate, 4 high, 4 critical)
To address issues that do not require attention, run:
npm audit fix
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
Notice that, after installing the karma package, npm indicates that this version has known vulnerabilities. Nonetheless, it is added to the node_modules folder and listed as a devDependency in package.json. We will follow the suggestions to fix the issues in a bit.
Auditing the package.json File
During installation, npm indicated that karma has a vulnerability, so let’s verify this. The npm audit command inspects the local package.json file for any known vulnerabilities:
$ npm audit
# npm audit report
--snip--
karma <=6.3.15
Severity: high
Open redirect in karma - https://github.com/advisories/GHSA-rc3x-jf5g-xvc5
Cross-site Scripting in karma - https://github.com/advisories/GHSA-7x7c-qm48-pq9c
Depends on vulnerable versions of log4js
Depends on vulnerable versions of ua-parser-js
fix available via `npm audit fix --force`
Will install [email protected], which is a breaking change
--snip--
9 vulnerabilities (1 moderate, 4 high, 4 critical)
To address issues that do not require attention, run:
npm audit fix
To address all issues (including breaking changes), run:
npm audit fix --force
Running the command returns a detailed report about the version and severity of each problematic package, as well as a summary of all the issues found in the currently installed Node.js modules.
The npm package manager also indicated that the issues could be fixed automatically with npm audit fix. Alas, it warns us about breaking changes in the latest karma version. To accommodate those, we need to use the --force flag. I recommend using npm audit every few months, along with npm update, to avoid using outdated dependencies and creating security risks:
$ npm audit fix --force
added 13 packages, removed 41 packages, changed 27 packages, and audited 158 packages in 5s
Now we see that the devDependencies list in package.json has the latest karma version, and another run of npm audit reports that there are no more known vulnerabilities in the installed packages.
Cleaning Up the node_modules Folder
Running npm prune inspects the local package.json file, compares it to the local node_modules folder, and removes all unnecessary packages. You should use it during development, after adding and removing packages, or when performing general cleanup chores.
Let’s check that the audit we just performed didn’t install any unnecessary packages:
$ npm prune
up to date, audited 136 packages in 1s
found 0 vulnerabilities
The output looks fine; there are no issues with our packages.
Updating All Packages
Running npm update updates all installed