Mastering Node.js Web Development - Adam Freeman - E-Book

Mastering Node.js Web Development E-Book

ADAM FREEMAN

0,0
35,99 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.
Mehr erfahren.
Beschreibung

Dive into the world of Node.js with this comprehensive guide, taking you from foundational concepts to practical web development mastery. Written by an industry veteran with over 50 programming books under his belt, this book will help both beginners and seasoned developers.

Gain a deep understanding of the most important server-side features in web development with Node.js. The first part of the book will get you up to speed with basic features of Node.js and TypeScript. In the second part, you’ll elevate your skills by creating simplified implementations of key server-side features to understand how they work and how they are presented to clients. Armed with the understanding gained from implementing each feature, you will be able to replace custom code with production-ready open-source packages.

The third part will help you understand how server-side features are combined for practical web development. Using Adam Freeman’s signature SportsStore application, you will learn how to develop client and server-side components, culminating in a thorough application deployment preparation.

By the end of this Node.js book, you will be able to build and deploy server applications to support HTTP clients, including JavaScript applications created with frameworks such as Angular and React.

Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:

EPUB
MOBI

Seitenzahl: 771

Veröffentlichungsjahr: 2024

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



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 ReadyChapter 2, Working with the Node.js ToolsChapter 3, JavaScript and TypeScript PrimerChapter 4, Understanding Node.js ConcurrencyChapter 5, Handling HTTP RequestsChapter 6, Using Node.js StreamsChapter 7, Using Bundles and Content SecurityChapter 8, Unit Testing and Debugging

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

Problem

Solution

Listing

Execute a JavaScript file.

Use the node command.

5

Initialize a project for use with JavaScript packages.

Use the npm init command.

6

Add a JavaScript package to a project.

Use the npm install command. Use the --save-dev argument for development tool packages.

7, 8

List the packages in a project.

Use the npm list command.

9, 10

List the reported security vulnerabilities in the packages used by a project.

Use the npm audit command.

N/A

Execute the code in a package.

Add the node_modules/.bin folder to the path or use the npx command.

11–17

Start the development tools used by a project.

Define commands in the scripts section of the package.json file and use the npm start or npm run commands.

18–22

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:

Figure 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.

Name

Description

npm init

This command creates a package.json file, which is used to keep track of a project’s packages.

npm install

This command adds a package to the project. The --save-dev argument is used to install packages that are used during development but are not part of the application.

npm list

This command lists all of the packages that have been added to the project. The --all argument includes package dependencies in the output.

npm audit

This command reports on security vulnerabilities that have been reported in the packages used in the project.

npm start

This command executes the start script defined in the package.json file.

npm stop

This command executes the stop script defined in the package.json file.

npm restart

This command executes the restart script defined in the package.json file.

npm test

This command executes the test script defined in the package.json file.

npm run

This command executes custom commands defined in the package.json file.

npx

This command executes a package.

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:

Name

Description

*

Using an asterisk accepts any version of the package to be installed.

5.3.0

Expressing a version number directly will accept only the package with the exact matching version number, e.g., 5.3.0.

>5.3.0>=3.3.0

Prefixing a version number with > or >= accepts any version of the package that is greater than or equal to a given version.

<5.3.0<=5.3.0

Prefixing a version number with < or <= accepts any version of the package that is less than or equal to a given version.

~5.3.0

Prefixing a version number with a tilde (the ~ character) accepts versions to be installed even if the patch level number (the last of the three version numbers) doesn’t match. For example, specifying ~5.3.0 will accept version 5.3.1 or 5.3.2 (which would contain patches to version 5.3.0) but not version 5.4.0 (which would be a new minor release).

^5.3.0

Prefixing a version number with a caret (the ^ character) will accept versions even if the minor release number (the second of the three version numbers) or the patch number doesn’t match. For example, specifying ^5.3.0 will allow versions 5.4.0 and 5.5.0 but not version 6.0.0.

Table 2.3: npm version numbers

Using exact version numbers

When I specified [email protected] 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:

startstoprestarttest

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.