Mastering Node.js Web Development: Go on a comprehensive journey from the fundamentals to advanced web development with Node.js
By Adam Freeman
()
Adam Freeman
Adam Freeman is an experienced IT professional who started his career as a programmer. He has held senior positions in a range of companies, most recently serving as Chief Technology Officer and Chief Operating Officer of a global bank. He has written 50 programming books, focusing mostly on web application development.
Read more from Adam Freeman
Genius Vol. 1: Siege Rating: 0 out of 5 stars0 ratingsGenius Vol. 02: Cartel Rating: 0 out of 5 stars0 ratingsThree Famous Impostors?: An Inquiry About Judaism, Christianity and Islam Rating: 0 out of 5 stars0 ratings
Related to Mastering Node.js Web Development
Related ebooks
Node.js Design Patterns - Second Edition Rating: 4 out of 5 stars4/5Node.js Basics for New Developers: A Practical Guide with Examples Rating: 0 out of 5 stars0 ratingsNode.js for Beginners: A comprehensive guide to building efficient, full-featured web applications with Node.js Rating: 0 out of 5 stars0 ratingsNode.js By Example Rating: 2 out of 5 stars2/5Building Scalable Web Apps with Node.js and Express Rating: 0 out of 5 stars0 ratingsJasmine JavaScript Testing - Second Edition Rating: 0 out of 5 stars0 ratingsJavaScript Unleashed: Scripting the Web: A Comprehensive Guide to JavaScript Programming Rating: 0 out of 5 stars0 ratingsLearning JavaScript Fast: Build Web Interactivity Using Powerful JavaScript Tools Rating: 0 out of 5 stars0 ratingsRESTful Web API Design with Node.js - Second Edition Rating: 1 out of 5 stars1/5JavaScript Made Easy: A Practical Guide with Examples Rating: 0 out of 5 stars0 ratingsYour First Week With Node.js Rating: 0 out of 5 stars0 ratingsJavaScript Fundamentals Made Easy: A Practical Guide with Examples Rating: 0 out of 5 stars0 ratingsJavaScript for Beginners Rating: 5 out of 5 stars5/5Javascript Mastery: In-Depth Techniques and Strategies for Advanced Development Rating: 0 out of 5 stars0 ratingsThe JavaScript Journey: From Basics to Full-Stack Mastery Rating: 0 out of 5 stars0 ratingsNode.js Blueprints Rating: 0 out of 5 stars0 ratingsNode.js Web Development - Third Edition Rating: 2 out of 5 stars2/5Mastering JavaScript Secure Web Development+: Unlock the Secrets of Expert-Level Skills Rating: 0 out of 5 stars0 ratingsMastering Node.js Rating: 1 out of 5 stars1/5Coding with JavaScript For Dummies Rating: 0 out of 5 stars0 ratingsThe Ultimate Guide to Mastering JavaScript: A Beginner's Journey Rating: 0 out of 5 stars0 ratingsProjects with IOTA Rating: 0 out of 5 stars0 ratingsNode.js, Express.js, and More Rating: 0 out of 5 stars0 ratingsJavaScript for Kids: Start Your Coding Adventure Rating: 0 out of 5 stars0 ratingsNode.js Unleashed: Mastering Scalable JavaScript Applications Rating: 0 out of 5 stars0 ratingsMastering the Craft of JavaScript Programming: Unraveling the Secrets of Expert-Level Programming Rating: 0 out of 5 stars0 ratings
Internet & Web For You
Coding All-in-One For Dummies Rating: 4 out of 5 stars4/5How to Be Invisible: Protect Your Home, Your Children, Your Assets, and Your Life Rating: 4 out of 5 stars4/548 Really Useful Web Sites Rating: 5 out of 5 stars5/5Coding For Dummies Rating: 5 out of 5 stars5/5Social Engineering: The Science of Human Hacking Rating: 3 out of 5 stars3/5Everybody Lies: Big Data, New Data, and What the Internet Can Tell Us About Who We Really Are 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/5The Beginner's Affiliate Marketing Blueprint Rating: 4 out of 5 stars4/5Python: Learn Python in 24 Hours Rating: 4 out of 5 stars4/5How to Disappear and Live Off the Grid: A CIA Insider's Guide Rating: 0 out of 5 stars0 ratingsThe $1,000,000 Web Designer Guide: A Practical Guide for Wealth and Freedom as an Online Freelancer Rating: 4 out of 5 stars4/5Ultimate Guide for Being Anonymous: Hacking the Planet, #4 Rating: 5 out of 5 stars5/5Cybersecurity For Dummies Rating: 5 out of 5 stars5/5Web Design For Dummies Rating: 4 out of 5 stars4/5HTML in 30 Pages Rating: 5 out of 5 stars5/5Six Figure Blogging Blueprint Rating: 5 out of 5 stars5/5Beginner's Guide To Starting An Etsy Print-On-Demand Shop Rating: 0 out of 5 stars0 ratingsContent Chemistry: The Illustrated Handbook for Content Marketing Rating: 5 out of 5 stars5/5Blogging For Dummies Rating: 0 out of 5 stars0 ratingsThe Hacker Crackdown: Law and Disorder on the Electronic Frontier Rating: 4 out of 5 stars4/5Tor and the Dark Art of Anonymity Rating: 5 out of 5 stars5/5Wordpress for Beginners: The Easy Step-by-Step Guide to Creating a Website with WordPress Rating: 5 out of 5 stars5/5Surveillance and Surveillance Detection: A CIA Insider's Guide Rating: 3 out of 5 stars3/5Notion for Beginners: Notion for Work, Play, and Productivity Rating: 4 out of 5 stars4/5
Reviews for Mastering Node.js Web Development
0 ratings0 reviews
Book preview
Mastering Node.js Web Development - Adam Freeman
Mastering Node.js Web Development
Go on a comprehensive journey from the fundamentals to advanced web development with Node.js
Adam Freeman
Mastering Node.js Web Development
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.
Senior Publishing Product Manager: Suman Sen
Acquisition Editor – Peer Reviews: Jane Dsouza
Project Editor: Parvathy Nair
Content Development Editor: Shazeen Iqbal
Copy Editor: Safis Editing
Technical Editors: Kushal Sharma and Anirudh Singh
Proofreader: Safis Editing
Indexer: Hemangini Bari
Presentation Designer: Ganesh Bhadwalkar
Developer Relations Marketing Executive: Priyadarshini Sharma
First published: June 2024
Production reference: 1100624
Published by Packt Publishing Ltd.
Grosvenor House
11 St Paul’s Square
Birmingham
B3 1RB, UK.
ISBN 978-1-80461-507-2
www.packt.com
Dedicated to my lovely wife, Jacqui Griffyth.
(And also to Peanut.)
Contributors
About the author
Adam Freeman is an experienced IT professional who started his career as a programmer. He held senior positions in a range of companies, where he was most recently serving as Chief Technology Officer and Chief Operating Officer of a global bank. He has written 53 programming books, focusing mostly on web application development. Now retired, he spends his time writing and trying to make furniture.
About the reviewer
Fabio Claudio Ferracchiati is a senior consultant and a senior analyst/developer using Microsoft technologies. He works for TIM (an Italian telecommunications company). He is a Microsoft Certified Solution Developer for .NET, a Microsoft Certified Application Developer for .NET, a Microsoft Certified Professional, and a prolific author and technical reviewer. Over the past ten years, he’s written articles for Italian and international magazines and co-authored a number of books on a variety of computer topics.
I would like to thank Adam, who has always wanted me by his side in his works, which are of a quality superior to the norm. I would like to thank my wife for giving me two wonderful daughters who are my whole life, currently nicknamed Peguin and Rani. I love you.
Part I
Putting Node.js in Context
Start your Node.js development journey by learning the essential tools, exploring fundamental JavaScript features, and understanding core Node.js support for web applications.
This part comprises the following chapters:
Chapter 1, Getting Ready
Chapter 2, Working with the Node.js Tools
Chapter 3, JavaScript and TypeScript Primer
Chapter 4, Understanding Node.js Concurrency
Chapter 5, Handling HTTP Requests
Chapter 6, Using Node.js Streams
Chapter 7, Using Bundles and Content Security
Chapter 8, Unit Testing and Debugging
1
Getting Ready
Node.js is a server-side JavaScript runtime that has become one of the most popular platforms for creating web applications. Node.js benefits from a vast library of packages and frameworks, providing every kind of feature and function imaginable, built on a rich API that Node.js provides for handling low-level tasks.
This book is different from most other Node.js books because it explains the relationship between the Node.js API and popular web application packages. Each chapter explains how a core feature required for web development can be implemented using the Node.js API, before replacing the custom implementation with a popular and well-tested open-source package.
Understanding the Node.js API gives you a solid understanding of how web application features really work, and using popular packages lets you build those features without having to write custom code. When problems arise, as they will in any project, your knowledge of the Node.js API will give you a solid foundation to demystify the way that specific packages work and to figure out what’s going wrong.
The first part of this book provides an overview of the tools used in Node.js development and provides a primer for the most important language and platform features, including how concurrency is implemented by JavaScript, and how this relates to handling HTTP requests using Node.js.
The second part of this book focuses on the key building blocks for web applications: generating HTML content, processing forms, using databases, and authenticating users.
The third and final part of this book demonstrates how the features described in earlier chapters can be combined to create a simple but realistic web store application.
This is the SportsStore example that I have used in many of my books, and which includes common features such as a product catalog, a shopping cart, a checkout process, and administration features.
What do you need to know?
To follow the examples in this book, you should be familiar with HTML and CSS and understand the basics of JavaScript development. I provide a primer for the JavaScript features that are useful for this book, but this isn’t a complete language tutorial.
How do you set up your development environment?
The tools needed for Node.js development are set up in Chapter 2. Later chapters require additional tools and packages, with full instructions provided for each.
Are there lots of examples?
There are loads of examples. The best way to learn is by example, and I have packed as many of them into this book as I can. To maximize the number of examples in this book, I have adopted a simple convention to avoid listing the same code or content repeatedly. When I create a file, I will show its full contents, just as I have in Listing 1.1. I include the name of the file and its folder in the listing’s header, and I show the changes that I have made in bold.
Listing 1.1: Asserting an unknown value in the index.ts file in the primer folder
function getUKCapital() : string { return London
; } function writeCity(f: () => string) { console.log(`City: ${f()}`) } writeCity(getUKCapital); writeCity(() => Paris
);
let myCity = Rome
;
writeCity(() => myCity);
This is a listing from Chapter 3, which shows the contents of a file called
index.ts
that can be found in the
primer
folder. Don’t worry about the content of the listing or the purpose of the file; just be aware that this type of listing contains the complete contents of a file and that the changes you need to make to follow the example are shown in bold.
Some code files become long, and the feature I will describe will require only a small change. Rather than list the complete file, I use an ellipsis (three periods in succession) to indicate a partial listing, which shows just a portion of the file, as shown in Listing 1.2.
Listing 1.2. Including user input in the sql_repository.Ts file in the src/server/data folder
... getResultsByName($name: string, $limit: number): Promise
return this.executeQuery
(`
SELECT Results.*, name, age, years, nextage FROM Results
INNER JOIN People ON personId = People.id
INNER JOIN Calculations ON calculationId = Calculations.id
WHERE name = ${$name}
`, {});
} ...
This is a listing from Chapter 12, and it shows a set of changes applied to one part of a larger file. When you see a partial listing, you will know that the rest of the file does not have to change and that only the sections marked in bold are different.
In some cases, changes are required in different parts of a file, which makes it difficult to show as a partial listing. In this situation, I omit part of the file’s contents, as shown in Listing 1.3.
Listing 1.3. Defining model relationships in the orm_helpers.ts file in the src/server/data folder
import { DataTypes, Sequelize } from sequelize
; import { Calculation, Person, ResultModel } from ./orm_models
; const primaryKey = { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true } }; export const initializeModels = (sequelize: Sequelize) => { // ...statements omitted for brevity... }
export const defineRelationships = () => {
ResultModel.belongsTo(Person, { foreignKey: personId
});
ResultModel.belongsTo(Calculation, { foreignKey: calculationId
});
}
In this listing, the changes are still marked in bold, and the parts of the file that are omitted from the listing are not affected by this example.
Where can you get the example code?
You can download the example projects for all the chapters in this book from https://github.com/PacktPublishing/Mastering-Node.js-Web-Development. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
What if you have problems following the examples?
The first thing to do is to go back to the start of the chapter and start over. Most problems are caused by skipping a step or not fully applying the changes shown in a listing. Pay close attention to the bold emphasis in code listings, which highlights the changes that are required.
Then, check the errata/corrections list, which is included in the book’s GitHub repository. Technical books are complex, and mistakes are inevitable, despite my best efforts and those of my editors. Check the errata list for the list of known errors and instructions to resolve them.
If you still have problems, then download the project for the chapter you are reading from the book’s GitHub repository (https://github.com/PacktPublishing/Mastering-Node.js-Web-Development) and compare it to your project. I created the code for the GitHub repository by working through each chapter, so you should have the same files with the same contents in your project.
If you still can’t get the examples working, then you can contact me at [email protected] for help. Please make it clear in your email which book you are reading, and which chapter/example is causing the problem. A page number or code listing is always helpful. Please remember that I get a lot of emails and that I may not respond immediately.
What if you find an error in the book?
You can report errors to me by email at [email protected] or visit http://www.packtpub.com/submit-errata, click Submit Errata, and fill in the form, although I ask that you first check the errata/corrections list for this book, which you can find in the book’s GitHub repository at https://github.com/PacktPublishing/Mastering-Node.js-Web-Development, just in case it has already been reported.
I add errors that are likely to confuse readers, especially problems with example code, to the errata/corrections file on the GitHub repository, with a grateful acknowledgment to the first reader who reported it. I also publish a list of less serious issues, which usually means errors in the text surrounding the code that are less likely to confuse.
How do you contact the author?
You can email me at [email protected]. It has been a few years since I started publishing an email address in my books. I wasn’t entirely sure that it was a good idea, but I am glad that I did it. I have received emails from around the world, from readers working or studying in every industry, and – for the most part, anyway – the emails are positive, polite, and a pleasure to receive.
I try to reply promptly, but I get many emails, and sometimes I get a backlog, especially when I have my head down trying to finish writing a book. I always try to help readers who are stuck with an example in the book, although I ask that you follow the steps described earlier in this chapter before contacting me.
While I welcome reader emails, there are some common questions for which the answers will always be no.
I am afraid that I won’t write the code for your new start-up, help you with your college assignment, get involved in your development team’s design dispute, or teach you how to program.
What if you really enjoyed this book?
Please email at [email protected] and let me know. It is always a delight to hear from a happy reader, and I appreciate the time it takes to send those emails. Writing these books can be difficult, and those emails provide essential motivation to persist in an activity that can sometimes feel impossible. Alternatively, you can also send feedback to [email protected].
What if this book has made you angry?
You can still email at [email protected], and I will still try to help you. Bear in mind that I can help only if you explain what the problem is and what you would like me to do about it. You should understand that, sometimes, the only outcome is to accept I am not the writer for you and that we will have closure only when you return this book and select another. I’ll give careful thought to whatever has upset you, but after 25 years of writing books, I have come to accept that not everyone enjoys reading the books I like to write. Alternatively, you can also send feedback to [email protected].
Now that you understand the structure of the book, the next chapter explores the tools used for Node.js development.
Download a free PDF copy of this book
Thanks for purchasing this book!
Do you like to read on the go but are unable to carry your print books everywhere?
Is your eBook purchase not compatible with the device of your choice?
Don’t worry, now with every Packt book you get a DRM-free PDF version of that book at no cost.
Read anywhere, any place, on any device. Search, copy, and paste code from your favorite technical books directly into your application.
The perks don’t stop there, you can get exclusive access to discounts, newsletters, and great free content in your inbox daily.
Follow these simple steps to get the benefits:
Scan the QR code or visit the link below:
https://packt.link/free-ebook/9781804615072
Submit your proof of purchase.
That’s it! We’ll send your free PDF and other benefits to your email directly.
Share your thoughts
Once you’ve read Mastering Node.js Web Development, we’d love to hear your thoughts! Please click here to go straight to the Amazon review page for this book and share your feedback.
Your review is important to us and the tech community and will help us make sure we’re delivering excellent quality content.
2
Working with the Node.js Tools
In this chapter, I explain the simple process of getting started with Node.js, beginning with the simple steps that are required to prepare for development. I explain how to execute JavaScript code using Node.js and then I introduce the real power in Node.js development: the Node Package Manager (npm).
npm
is the tool that does most of the work during development, taking responsibility for everything from downloading and installing JavaScript packages, reporting on security vulnerabilities, and running development commands. Table 2.1 summarizes the chapter.
Table 2.1: Chapter summary
Getting ready
The key step to prepare for Node.js development is, as you would expect, to install Node.js and its supporting tools. The version of Node.js I have used in this book is 20.9.0, which is the Long-Term Support (LTS) version at the time of writing. There may be later versions available by the time you read this, but you should stick to this release for the examples in this book.
A complete set of installers for Node.js version 20.10.0 is available at https://nodejs.org/download/release/v20.10.0. Download and run the installer for your platform and ensure the npm package manager and the Add to PATH options are checked, as shown in Figure 2.1:
A screenshot of a computer setup Description automatically generatedFigure 2.1: Installing Node.js
When the installation is complete, open a new command prompt and run the command shown in Listing 2.1:
Listing 2.1: Running Node.js
node -v
If the installation has been successful, you will see the following version number displayed:
v20.10.0
The installer should have set up the package manager, which plays a key role in Node.js development. Run the command shown in Listing 2.2 to ensure the package manager is working:
Listing 2.2: Running the package manager
npm -v
If the installation was successful, you will see the following version number:
10.1.0
Installing Git
Some packages depend on Git, which is a popular version control system. Download the installer for your platform from https://git-scm.com/downloads and follow the installation instructions.
Once you have completed the installation, use a command prompt to run the command shown in Listing 2.3 to check that Git is working. You may have to manually configure the executable paths:
Listing 2.3: Checking Git
git --version
At the time of writing, the latest version of Git for Windows and Linux is 2.42.0.
Selecting a code editor
An editor is required to write the code that will be executed by Node.js, and any editor that supports JavaScript and TypeScript can be used to follow the examples in this book. If you don’t already have a preferred editor, then Visual Studio Code (https://code.visualstudio.com) has become the most popular editor because it is good (and free), and it is the editor that I used while writing this book.
If you are using Visual Studio Code, run the command code to start the editor or use the program icon created during installation, and you will see the welcome screen shown in Figure 2.2. (You may need to add Visual Studio Code to your command prompt path before using the command code.)
Figure 2.2: The Visual Studio Code Welcome screen
Using Node.js
The entire purpose of Node.js is to execute JavaScript code. Open a command prompt, navigate to a convenient location, and create a folder named
tools
. Add a file named
hello.js
to the
tools
folder, with the content shown in Listing 2.4:
Listing 2.4: The Contents of the hello.js File in the tools Folder
console.log(Hello, World
);
The Node.js API has some features that are also provided by modern JavaScript browsers, including the
console.log
method, which writes a message to the console. Run the command shown in Listing 2.5 in the
tools
folder to execute the JavaScript code:
Listing 2.5: Executing the JavaScript Code
node hello.js
The
node
command starts the Node.js runtime and executes the specified JavaScript file, producing the following output:
Hello, World
That’s all there is to know about executing JavaScript code. The rest of the functionality that Node.js provides is delivered through an API, which is described in the rest of this book, starting with Chapter 4.
Understanding the npm tool
The
node
command isn’t often used directly, and most development activities rely on the
npm
tool, which is installed alongside Node.js. The headline
npm
feature is that it provides access to the
npm
repository (npmjs.com), which contains an incredible collection of open-source JavaScript packages that can be added to projects.
npm
has grown from its original purpose to add related features and has become an integral part of working with Node.js, as I describe in the following sections. For quick reference, Table 2.2 lists the most useful commands supported by
npm
, which is the package manager command.
Table 2.2: Useful
npm
commands
Initializing a project
npm
relies on a configuration file named
package.json
, which describes the development project, keeps track of the packages on which it depends, and stores configuration settings related to packages. Run the command shown in Listing 2.6 in the
tools
folder to create the
package.json
file for the example project:
Listing 2.6: Initializing the project
npm init -y
The
init
command prompts the user for the values to put in the
package.json
file, but the
-y
argument selects the default values, which are suitable for most projects, including the example for the chapter. The
init
command creates a
package.json
file with the following contents:
{ name
: tools
, version
: 1.0.0
, description
: , main
: hello.js
, scripts
: { test
: echo \"Error: no test specified\" && exit 1
}, keywords
: [], author
: , license
: ISC
}
Most of the initial contents of the
package.json
file describe the project so that it can be published to a package registry, which is why there are settings for version numbers and licenses. Additional settings will be added to the file in later sections, and you can see the complete list of supported settings at https://docs.npmjs.com/cli/v10/configuring-npm/package-json.
Managing packages
The headline
npm
feature is the management of the packages used in a project. This may not seem like a big deal, but one compelling aspect of Node.js development is the immense library of open-source packages, which are available in a public registry (npmjs.com).
npm
provides access to the registry, takes care of downloading and installing packages, and manages dependencies between packages to avoid conflicts.
Packages are added to the project with the
npm install
command. Run the command shown in Listing 2.7 in the
tools
folder to add a package to the example project:
Listing 2.7: Adding a package
npm install [email protected]
The
npm install
command adds a package to the project and the argument specifies the name of the package (
bootstrap
, in this case), followed by the
@
character, followed by a version number. You can omit the
@
character and the version number, in which case, the latest version will be installed, but it is good practice to be specific when installing a package.
The command in Listing 2.7 adds the excellent Bootstrap CSS/JavaScript package to the project. As part of this process,
npm
looks at the packages that Bootstrap depends on and installs them, too. Once the command has completed, you will see a new section in the
package.json
file:
{ name
: tools
, version
: 1.0.0
, description
: , main
: hello.js
, scripts
: { test
: echo \"Error: no test specified\" && exit 1
}, keywords
: [], author
: , license
: ISC
,
dependencies
: {
bootstrap
: ^5.3.0
}
}
The
dependencies
section is used to keep track of the packages used in the project. The version number in the
packages.json
file is prefixed with a caret (the
^
character), which is part of the
npm
system for specifying ranges of version numbers, as described in Table 2.3:
Table 2.3:
npm
version numbers
Using exact version numbers
When I specified
in Listing 2.7,
npm
gave itself some wiggle room by interpreting the version as
^5.3.0
. The process of resolving dependencies and conflicts between packages is a complex process, which is made easier by broadening the range of acceptable versions. This approach relies on the idea that version
5.4.0
, say, will be compatible with version
5.3.0
and won’t contain breaking changes.
If you can’t rely on packages to maintain compatibility, then you can configure
npm
to use exact version numbers by running this command:
npm config set save-exact false
npm
will only use the versions that you specify, but the trade-off is that resolving dependencies and version conflicts between packages may be more difficult.
Packages are stored in the
node_modules
folder, which is created automatically.
npm
creates a folder for each package that it downloads, and there can be a large number of folders as packages and their dependencies are resolved.
To ensure that dependencies are resolved consistently,
npm
creates the
package-lock.json
file, which contains a complete list of the packages that have been installed, along with specific version numbers.
Installing development packages
The
dependencies
section of the
package.json
file is for the packages that the application needs to run. The
npm
command can also be used to add packages that are only required during development, such as compilers and debuggers. Run the command shown in Listing 2.8 in the
tools
folder to add development packages to the project:
Listing 2.8: Adding a development package to the example project
npm install --save-dev [email protected] [email protected]
The
--save-dev
argument specifies a development package, and this command installs two packages that are required only during development. The
typescript
package includes the TypeScript compiler, which is used to compile TypeScript code into JavaScript that can be executed by Node.js. The
tsc-watch
package is a useful add-on that monitors TypeScript files for changes and automatically compiles and executes them.
Examine the
package.json
file and you will see a new configuration section:
{ name
: tools
, version
: 1.0.0
, description
: , main
: hello.js
, scripts
: { test
: echo \"Error: no test specified\" && exit 1
, start
: tsc message.ts
}, keywords
: [], author
: , license
: ISC
, dependencies
: { bootstrap
: ^5.3.0
},
devDependencies
: {
tsc-watch
: "
^6.0.4",
typescript
: ^5.2.2
}
}
The
devDependencies
section keeps track of the development packages, which don’t need to be included when the application is prepared for deployment. The new section contains entries for the packages specified by the command in Listing 2.8.
Choosing packages and tools
JavaScript benefits from a broad and dynamic ecosystem of open-source packages that solve just about any problem you might encounter. There is so much choice that it can be difficult to decide which packages to use, especially since there is a constant flow of online articles claiming that a particular new package is a hot way to build applications.
The sad fact is most projects die from a lack of support. Someone, somewhere, becomes frustrated with the way that a particular package works and decides to write their own replacement. They realize that other people may benefit and altruistically decide to publish their code for anyone to use. Most of the time, that’s the end of the story, either because not many other people encounter the same frustrations or because the new package solves the problem in a way that doesn’t suit other projects.
In many ways, that’s the best outcome – at least for the original developer – because as soon as a package starts to get users, the developer will start to get demands for fixes, features, and general support. The idea of open-source packages is that everyone pitches in, but that often doesn’t happen. The burdens on the package developer can be substantial, user demands can be endless and aggressive, and the amount of – unpaid – work can get out of hand. Many packages that start to become popular are abandoned at this point because the original developer can’t cope with the maintenance and no one pitches in to help.
A small number of packages make it past this point. The original developer successfully enlists help in fixing problems and writing new features and puts the package onto a project-like footing. The original developer may move on to other projects, but the package becomes important enough that someone else is willing to take on the task and the project continues. At this point, the package matures, can be widely used, and almost always becomes the unfashionable approach that attracts the ire of all those online articles.
My advice is to choose packages that suit the type of project you are working on. For mainstream commercial development, I recommend using packages that have made it past these hurdles and become well-established and well-maintained. These are the packages that have high weekly download numbers (which you can see on
npm.js
), which are updated regularly, and have an engaged team that responds to issues and queries. These are the packages that will continue to be supported throughout the life of your project, allowing you to deliver your features on a solid platform. It is this type of package that I have used throughout this book.
For hobby and experimental projects, I recommend using the less well-established packages. These won’t be as well-supported and you will encounter more problems and do more work to get everything working, but you will learn more, and you may have more fun.
Regardless of how you choose packages, remember that you are benefiting from the altruism of others. If you can, then contribute to the packages you use. Just about every package has a list of bugs waiting to be fixed, which is a good way to get involved. If you don’t feel confident contributing code, then consider making a financial contribution. Many projects accept donations, and even the largest and most widely used packages are managed by foundations that welcome individual and corporate supporters.
Listing packages
You may only rely on a small number of packages in a project but each of those packages has dependencies and it is easy to end up with hundreds of small packages in a project, each of which contributes a small amount of functionality. To see the set of packages that have been added to the project, run the command shown in Listing 2.9 in the
tools
folder:
Listing 2.9: Listing the installed packages
npm list
The output corresponds to the
npm install
commands used in earlier sections of this chapter, although you may see slightly different version numbers:
+-- [email protected] +-- [email protected] `-- [email protected]
Behind the scenes,
npm
has inspected these packages to discover their dependencies and installed those packages as well, which can be seen by running the command shown in Listing 2.10 in the
tools
folder:
Listing 2.10: Listing packages and dependencies
npm list --all
The
--all
argument tells
npm
to list dependencies as well and produces output similar to the following, although you may see different details:
+-- [email protected] +-- [email protected] | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | | `-- [email protected] | | `-- [email protected] | | `-- [email protected] | +-- [email protected] | +-- [email protected] | | `-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | | `-- [email protected] deduped | | +-- [email protected] | | | `-- [email protected] deduped | | +-- [email protected] | | | `-- [email protected] deduped | | `-- [email protected] | +-- [email protected] | `-- [email protected] deduped `-- [email protected]
You may see small differences when you run this command. Most projects rely on a deep tree of packages, and
npm
takes care of resolving the dependencies for each of them and automatically downloading all the packages that are required.
Checking for package security vulnerabilities
The large number of JavaScript packages in a project makes it difficult to know exactly which packages you are using and whether those packages may have reported security vulnerabilities.
To address this issue, package repositories maintain a list of known problems. As
npm
resolves package dependencies, it checks all of the packages that it is installing against the vulnerabilities list and emits a warning if it finds any problems. As an example, here is a command that installs a package whose dependencies contain a vulnerability:
npm install --save-dev [email protected]
This command may not have the same effect by the time this book is published because of the dynamic nature of JavaScript package dependencies, but when I ran this command, I received the following response:
added 32 packages, and audited 54 packages in 3s 5 packages are looking for funding run `npm fund` for details
3 moderate severity vulnerabilities
npm
has identified three security issues in the packages that have been installed. For more details, I ran this command:
npm audit
The
npm audit
command reports on potential problems. In this case, there is an issue with versions 7.0.0 to 7.5.1 with a package named
semver
:
# npm audit report semver 7.0.0 - 7.5.1 Severity: moderate semver vulnerable to Regular Expression Denial of Service - https://github.com/advisories/GHSA-c2qf-rxjj-qqgw fix available via `npm audit fix --force` Will install [email protected], which is a breaking change node_modules/simple-update-notifier/node_modules/semver simple-update-notifier 1.0.7 - 1.1.0 Depends on vulnerable versions of semver node_modules/simple-update-notifier nodemon 2.0.19 - 2.0.22 Depends on vulnerable versions of simple-update-notifier node_modules/nodemon 3 moderate severity vulnerabilities
The output provides a URL where details can be found and the suggestion that installing a later version of the top-level package – the one added by the
npm install
command – would fix the problem, albeit by introducing a breaking change that may stop existing code from working.
There is an
npm audit fix
command that attempts to move to fixed versions of packages but that can cause problems with deeply nested dependencies and should be used with caution.
For the packages used in this book, you should use the versions I have specified, even if there are warnings about security vulnerabilities, to ensure the examples work as expected. For real projects, you should assess each reported vulnerability and figure out whether moving to a patched package is possible without breaking code. It won’t always be possible to move away from all vulnerable packages without making corresponding changes in the project, and only you can decide what is sensible for your projects.
To be clear, I am not advising you to ignore security warnings. I am saying that not all warnings are for problems that are likely to occur in all projects and there will be times when you might decide to stick with a vulnerable package because the risk to your project is low and the amount of work required to upgrade a package is substantial. You might also form the view that problems with developer packages are less of a risk because those packages are not included when the project is deployed.
Executing packages
Some packages include shell scripts that can be used to execute the package features, and these are installed in the
node_modules/.bin
folder. The package added in Listing 2.10, for example, includes a
tsc
script, which starts the TypeScript compiler. Add a file named
message.ts
to the
tools
folder, with the content shown in Listing 2.11. (The
ts
file extension denotes a TypeScript file.)
Listing 2.11: The contents of the message.ts file in the tools folder
function writeMessage(msg: string) { console.log(`Message: ${msg}`); } writeMessage(This is the message
);
TypeScript code has to be compiled into pure JavaScript before it can be executed by Node.js. I describe this process in more detail in Chapter 3, but for this chapter, it is enough to know that I need to use the
tsc
command provided by the package added to the project in Listing 2.8.
The first step is to add the folder that contains the scripts to the path used to search for commands. Execute the command shown in Listing 2.12 if you are using PowerShell, which is what I use for development on Windows machines:
Listing 2.12: Setting the path in powershell
$env:path += ';.\node_modules\.bin'
Listing 2.13 shows the equivalent command for the Bourne shell, which is commonly encountered on Linux machines:
Listing 2.13: Setting the path in the bourne shell
PATH=$PATH:./node_modules/.bin/
Packages that provide shell scripts generally support a range of command shells. For its compiler, the
typescript
package adds three files to the
node_modules/.bin
folder:
tsc
(which supports the Bourne shell),
tsc.ps1
(which supports PowerShell), and
tsc.cmd
(which supports the older Windows Command Prompt).
These are not the only script files added to the
.bin
folder. The
typescript
package also adds scripts for the
tsserver
command, which is used to integrate TypeScript into development tools, such as editors, but which is not required for this book. Entries are added by other packages as
npm
installs packages and resolves dependencies.
Run the command shown in Listing 2.14 in the
tools
folder to run the compiler:
Listing 2.14: Running a package command
tsc message.ts
The command won’t produce any messages but it does create a file named
message.js
in the
tools
folder, with the following content:
... function writeMessage(msg) { console.log(Message:
.concat(msg)); } writeMessage(This is the message
); ...
Run the command shown in Listing 2.15 in the
tools
folder to execute the compiled JavaScript code using Node.js:
Listing 2.15: Executing JavaScript code
node message.js
The Node.js runtime executes the code in the file created by the TypeScript compiler, producing the following output:
Message: This is the message
Using the npx command
Not all packages install scripts, and another way to execute package features is to use the
npx
command. Each package added to the
node_modules
folder has its own
package.json
file. In addition to keeping track of the package’s dependencies, the
package.json
file defines a
bin
section that defines the commands that
npx
can execute. For the package added in Listing 2.8, the
package.json
file can be found in the
node_modules/typescript
folder and it contains this
bin
section:
... bin
: { tsc
: ./bin/tsc
, tsserver
: ./bin/tsserver
}, ...
The entries in the
bin
section define a command and a JavaScript file that will be executed by that command. The
typescript
package defines
bin
entries for
tsc
and
tsserver
commands, which correspond to the shell scripts used in the previous section. Run the command shown in Listing 2.16 in the
tools
folder to execute the TypeScript compiler using
npx
:
Listing 2.16: Executing the TypeScript compiler
npx tsc message.ts
This command has the same effect as the one in Listing 2.14. When multiple packages define commands with the same name, the
--package
argument can be used, as shown in Listing 2.17:
Listing 2.17: Specifying a package
npx --package=typescript tsc message.ts
If the package that contains the command isn’t installed, then the
npx
command will download the package into a cache folder and then execute the command.
Using script commands
npm
supports a set of commands that are customized by adding entries to the
scripts
section of the
package.json
file. This can feel a little odd at first, but it is a powerful way to use the features provided by JavaScript packages concisely and consistently.
npm
supports the following basic commands:
start
stop
restart
test
Projects won’t always need every command, and there are no firm rules for how these commands can be used, but the convention is to use the
start
command to start the development tools and use the
test
command to run unit tests, which I describe in Chapter 8.
Listing 2.18 adds an entry to the
scripts
section:
Listing 2.18: Configuring a command in the package.Json file in the tools folder
{ name
: tools
, version
: 1.0.0
, description
: , main
: hello.js
, scripts
: { test
: echo \"Error: no test specified\" && exit 1
,
start
: tsc-watch message.ts --onSuccess \"node message.js\"
}, keywords
: [], author
: , license
: ISC
, dependencies
: { bootstrap
: ^5.3.0
}, devDependencies
: { tsc-watch
: ^6.0.4
, typescript
: ^5.2.2
} }
Each entry in the
scripts
section consists of a command name and an associated action. The action associated with the
start
command in Listing 2.18 runs the
tsc-watch
command, which is a wrapper around the TypeScript compiler that watches TypeScript files for changes and can be configured to execute a command when compilation is successful. (The
test
command was added automatically when the
package.json
file was created and just prints out an error message.)
I could run the
tsc-watch
command directly from the command line, either using the shell scripts the package added to the
node_modules/.bin
folder or with the
npx
command, but as commands get more complex, it becomes more difficult to remember the syntax and enter them correctly. The new entry in the
package.json
file lets me define the command once and then always invoke it consistently. Run the command shown in Listing 2.19 in the
tools
folder:
Listing 2.19: Running a script command
npm start
The
npm start
command tells
npm
to perform the
start
action defined in the
package.json
file, producing the following output:
09:19:15 - Starting compilation in watch mode... 09:19:16 - Found 0 errors. Watching for file changes. Message: This is the message
Listing 2.20 makes a small change to the TypeScript file:
Listing 2.20: Making a change in the message.ts file in the tools folder
function writeMessage(msg: string) { console.log(`Message: ${msg}`); }
writeMessage(This is the new message
);
When you save the altered file, the change is detected, the TypeScript file is compiled, and Node.js is used to execute the JavaScript, producing the following output:
... Message: This is the new message ...
Most web application project development depends on tools that run continuously, monitoring files for changes, and this is a pattern that I will follow throughout this book. Use Control+C to stop the command once you have seen the output.
Defining custom commands
In addition to the built-in commands,
npm
supports custom commands as well, as shown in Listing 2.21:
Listing 2.21: Defining a custom script command in the package.json file in the tools folder
... scripts
: { test
: echo \"Error: no test specified\" && exit 1
, start
: tsc-watch message.ts --onSuccess \"node message.js\"
,
go
: tsc message.ts && node message.js
}, ...
The name of the new command is
go
and it compiles the
message.ts
TypeScript file and then uses Node.js to execute the compiled JavaScript.
Tip
Commands separated by
&&
are executed sequentially. Commands separated by a single
&
are executed in parallel.
Custom commands are executed with
npm run
, as shown in Listing 2.22:
Listing 2.22: Executing a custom script command
npm run go
The name of the custom command follows
npm run
, so that
npm run go
executes the custom
go
command, producing the following output:
Message: This is the new message
Summary
In this chapter, I explained the simple setup process to prepare for this book and introduced the core Node.js tools:
Node.js development requires the Node.js installer, the Git version control system, and a JavaScript/TypeScript code editor, such as Visual Studio Code.
JavaScript files are executed with the
node
command.
Much of the functionality provided by Node.js is presented through the API it provides, which is the topic of this book.
The node package manager (npm) is used to download JavaScript packages, execute commands, run development tools, and start unit tests.
In the next chapter, I will provide a primer that describes the essential JavaScript and TypeScript features that are required to follow the examples in this book.
3
JavaScript and TypeScript Primer
Developers come to the world of web app development via many paths and are not always grounded in the basic technologies that web apps rely on. In this chapter, I introduce the basic features of JavaScript and TypeScript. This is not a comprehensive guide to either language, but it addresses the essentials, and it will give you the knowledge you need to get started.
Preparing for this chapter
To prepare for this chapter, create a folder named
primer
in a convenient location. Navigate to the
primer
folder and run the command shown in Listing 3.1.
Listing 3.1: Preparing the project folder
npm init --yes
Run the command shown in Listing 3.2 in the
primer
folder to install the development packages that are used in this chapter.
Listing 3.2: Installing the development package
npm install [email protected] npm install [email protected] npm install [email protected] npm install @tsconfig/[email protected] npm install @types/[email protected]
The
nodemon
package will be used at the start of the chapter to monitor and execute JavaScript files. The
tsc-watc1h
package does the same thing for TypeScript files, and the
typescript
package contains the TypeScript compiler. The
@tsconfig/node20
package contains configuration settings for the TypeScript compiler for use in Node.js projects.
Replace the
scripts
section in the
package.json
file as shown in Listing 3.3, which will make it easier to use the development packages.
Listing 3.3: Replacing the scripts section in the package.json file in the primer folder
{ name
: primer
, version
: 1.0.0
, description
: , main
: index.js
, scripts
: {
use_js
: nodemon
,
"
use_ts:
tsc-watch --onSuccess \node index.js\"
}, keywords
: [], author
: , license
: ISC
, dependencies
: { @tsconfig/node20
: ^20.1.4
, @types/node
: ^20.6.1
, nodemon
: ^2.0.20
, tsc-watch
: ^6.0.4
, typescript
: ^5.2.2
} }
Add a file named
tsconfig.json
to the
primer
folder with the content shown in Listing 3.4, which creates a basic configuration for the TypeScript compiler suitable for a Node.js project.
Listing 3.4: The contents of the tsconfig.json file in the primer folder
{ extends
: @tsconfig/node20/tsconfig.json
}
Add a file named
index.js
to the
primer
folder with the content shown in Listing 3.5.
Listing 3.5: The contents of the index.js file in the primer folder
console.log(Hello, World
);
Run the command shown in Listing 3.6 in the
primer
folder to start monitoring and executing JavaScript