# Introduction to Node.js

Course: [Node.js](https://www.devtutorials.ai/learn/nodejs) · Section: Node.js Foundations
Source: https://www.devtutorials.ai/learn/nodejs/foundations/introduction-to-nodejs

> What Node.js is and why it was made, its history, V8, libuv and C++ bindings, Node.js versus browser JavaScript, Deno and Bun, LTS versus Current, installing Node.js and version managers, running scripts, the REPL, common CLI flags, and the global object, console and built-in globals.

## Node.js Introduction

**Node.js** = a program that runs JavaScript outside the web browser.

- You already know JavaScript from web pages.
- Node.js lets the same JavaScript run on your own computer or on a server.
- It can read files, talk to networks and start web servers.
- You start it from the terminal with the `node` command.

**Simple lesson:** Node.js takes JavaScript out of the browser and lets it work on your computer.

### A Real-World Example

Think of a class teacher at Greenfield School.

- She has the marks of 40 students in a file.
- She wants a report: total, average and the topper.
- Doing this by hand takes an hour.
- A 20-line Node.js script reads the file and prints the report in one second.
- No web page and no browser is needed. Only the terminal.

Node.js is not a new language. It is a place where JavaScript runs, just like the browser is a place where JavaScript runs.

## What You Will Learn

In this lesson, you will learn:

1. What Node.js is and why it was made
2. A short history of Node.js
3. What is inside Node.js: V8, libuv and C++ bindings
4. How Node.js is different from browser JavaScript
5. Node.js, Deno and Bun, and LTS versus Current versions
6. How to install Node.js and check its version
7. How to run scripts, use the REPL and common command-line flags
8. The global object, the `console` toolbox and other built-in tools

## Your First Node.js Program

A Node.js program is a normal `.js` file.

- You write JavaScript in a file, such as `app.js`.
- You run it with the command `node app.js`.
- Node.js reads the file from top to bottom.
- Everything you pass to `console.log` appears in the terminal.

Click **▶ Run** and read the **Terminal** panel.

- **The command:** the first line shows `$ node app.js`. This is what you would type on your own computer.
- **The output:** each `console.log` printed one line.
- **No browser:** there is no page preview. A Node.js program talks through the terminal.

Change the marks in the `marks` array and press ▶ Run again. The total changes. Press Restore code to go back.

**Simple lesson:** write JavaScript in a file, run it with `node`, and read the answer in the terminal.

## What Is Node.js?

**Runtime** = a program that runs your code and gives it tools to use.

- The browser is a runtime. It gives JavaScript tools like `document` and buttons.
- Node.js is also a runtime. It gives JavaScript tools like files, folders and networks.
- **JavaScript** = the language. **Node.js** = one place where it runs.

<figure className="ngc-fig node-fig">
<svg viewBox="0 0 560 240" role="img" aria-labelledby="fig-node-where" style={{ width: "100%", maxWidth: 560, height: "auto" }}>
  <title id="fig-node-where">Animation: the same JavaScript file can run in a browser or in Node.js</title>
  <rect x="220" y="12" width="120" height="40" rx="10" style={{ fill: "var(--ngc-orange-soft)", stroke: "var(--ngc-orange)", strokeWidth: 1.5 }} />
  <text x="280" y="37" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontFamily: "var(--mono)", fontSize: 13, fontWeight: 700 }}>app.js</text>
  <path d="M 250 52 L 140 104" style={{ fill: "none", stroke: "var(--ngc-slate)", strokeWidth: 2, strokeDasharray: "5 4" }} />
  <path d="M 310 52 L 420 104" style={{ fill: "none", stroke: "var(--ngc-slate)", strokeWidth: 2, strokeDasharray: "5 4" }} />
  <rect x="30" y="104" width="220" height="116" rx="10" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1.5 }} />
  <text x="140" y="128" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>Browser (Chrome, Edge)</text>
  <text x="140" y="154" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 12, fontWeight: 500 }}>window and document</text>
  <text x="140" y="176" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 12, fontWeight: 500 }}>buttons, forms, pages</text>
  <text x="140" y="198" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 12, fontWeight: 500 }}>runs when a page opens</text>
  <rect x="310" y="104" width="220" height="116" rx="10" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1.5 }} />
  <text x="420" y="128" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>Node.js (your computer)</text>
  <text x="420" y="154" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 12, fontWeight: 500 }}>files and folders</text>
  <text x="420" y="176" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 12, fontWeight: 500 }}>servers and networks</text>
  <text x="420" y="198" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 12, fontWeight: 500 }}>runs from the terminal</text>
  <circle r="7" style={{ fill: "var(--ngc-orange)" }}><animateMotion path="M 250 52 L 140 104" dur="4s" keyPoints="0;1;1" keyTimes="0;0.4;1" calcMode="linear" repeatCount="indefinite" /><animate attributeName="opacity" values="1;1;0;0" keyTimes="0;0.4;0.45;1" dur="4s" repeatCount="indefinite" /></circle>
  <circle r="7" opacity="0" style={{ fill: "var(--ngc-orange)" }}><animateMotion path="M 310 52 L 420 104" dur="4s" keyPoints="0;0;1;1" keyTimes="0;0.5;0.9;1" calcMode="linear" repeatCount="indefinite" /><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.5;0.52;0.9;1" dur="4s" repeatCount="indefinite" /></circle>
</svg>
<figcaption>The same JavaScript language runs in two places. Each place gives it different tools.</figcaption>
</figure>

### What Can You Build with Node.js?

- **Command-line tools,** such as a script that makes report cards
- **Web servers and APIs,** such as the backend of a shopping app
- **Build tools,** such as Vite, which React and Vue projects use
- **Real-time apps,** such as chat apps and live scoreboards
- **Automation scripts,** such as renaming 500 photos in one go

**Simple lesson:** JavaScript is the language. Node.js is the runtime that lets it work outside the browser.

## Why Node.js Was Created

Here is a small story first.

- A restaurant has one waiter.
- Table 1 orders food. The waiter goes to the kitchen.
- He stands there until the food is ready.
- Table 2 and Table 3 wait. Nobody takes their order.
- A smarter waiter gives the order to the kitchen and walks back.
- He takes orders from Table 2 and Table 3 while the food cooks.

Now the mapping: the smart waiter is how Node.js works.

<figure className="ngc-fig node-fig">
<svg viewBox="0 0 560 240" role="img" aria-labelledby="fig-node-waiter" style={{ width: "100%", maxWidth: 560, height: "auto" }}>
  <title id="fig-node-waiter">Animation: a blocking waiter serves tables one by one, a non-blocking waiter takes all orders first and serves them as food gets ready</title>
  <text x="20" y="24" textAnchor="start" style={{ fill: "var(--ngc-red)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>Blocking: the waiter waits at the kitchen</text>
  <text x="20" y="134" textAnchor="start" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>Non-blocking (Node.js): the waiter keeps taking orders</text>
  <text x="20" y="51" textAnchor="start" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 12, fontWeight: 600 }}>Table 1</text>
  <rect x="90" y="36" width="40" height="22" rx="5" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1 }} />
  <text x="110.0" y="51" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>order</text>
  <rect x="130" y="36" width="120" height="22" rx="5" style={{ fill: "var(--ngc-orange-soft)", stroke: "var(--ngc-orange)", strokeWidth: 1 }} />
  <text x="190.0" y="51" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>cooking</text>
  <rect x="250" y="36" width="40" height="22" rx="5" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1 }} />
  <text x="270.0" y="51" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>serve</text>
  <text x="20" y="79" textAnchor="start" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 12, fontWeight: 600 }}>Table 2</text>
  <rect x="290" y="64" width="40" height="22" rx="5" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1 }} />
  <text x="310.0" y="79" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>order</text>
  <rect x="330" y="64" width="120" height="22" rx="5" style={{ fill: "var(--ngc-orange-soft)", stroke: "var(--ngc-orange)", strokeWidth: 1 }} />
  <text x="390.0" y="79" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>cooking</text>
  <rect x="450" y="64" width="40" height="22" rx="5" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1 }} />
  <text x="470.0" y="79" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>serve</text>
  <text x="20" y="107" textAnchor="start" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 12, fontWeight: 600 }}>Table 3</text>
  <rect x="490" y="92" width="40" height="22" rx="5" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1 }} />
  <text x="510.0" y="107" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>order</text>
  <text x="540" y="107" textAnchor="middle" style={{ fill: "var(--ngc-red)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>…</text>
  <text x="20" y="161" textAnchor="start" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 12, fontWeight: 600 }}>Table 1</text>
  <rect x="90" y="146" width="40" height="22" rx="5" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1 }} />
  <text x="110.0" y="161" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>order</text>
  <rect x="130" y="146" width="120" height="22" rx="5" style={{ fill: "var(--ngc-orange-soft)", stroke: "var(--ngc-orange)", strokeWidth: 1 }} />
  <text x="190.0" y="161" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>cooking</text>
  <rect x="250" y="146" width="40" height="22" rx="5" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1 }} />
  <text x="270.0" y="161" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>serve</text>
  <text x="20" y="189" textAnchor="start" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 12, fontWeight: 600 }}>Table 2</text>
  <rect x="130" y="174" width="40" height="22" rx="5" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1 }} />
  <text x="150.0" y="189" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>order</text>
  <rect x="170" y="174" width="120" height="22" rx="5" style={{ fill: "var(--ngc-orange-soft)", stroke: "var(--ngc-orange)", strokeWidth: 1 }} />
  <text x="230.0" y="189" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>cooking</text>
  <rect x="290" y="174" width="40" height="22" rx="5" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1 }} />
  <text x="310.0" y="189" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>serve</text>
  <text x="20" y="217" textAnchor="start" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 12, fontWeight: 600 }}>Table 3</text>
  <rect x="170" y="202" width="40" height="22" rx="5" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1 }} />
  <text x="190.0" y="217" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>order</text>
  <rect x="210" y="202" width="120" height="22" rx="5" style={{ fill: "var(--ngc-orange-soft)", stroke: "var(--ngc-orange)", strokeWidth: 1 }} />
  <text x="270.0" y="217" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>cooking</text>
  <rect x="330" y="202" width="40" height="22" rx="5" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1 }} />
  <text x="350.0" y="217" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 700 }}>serve</text>
  <text x="450" y="224" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 12, fontWeight: 700 }}>all 3 served early</text>
  <line x1="90" y1="30" x2="90" y2="230" style={{ stroke: "var(--ngc-purple)", strokeWidth: 2 }}><animate attributeName="x1" values="90;540" dur="6s" repeatCount="indefinite" /><animate attributeName="x2" values="90;540" dur="6s" repeatCount="indefinite" /></line>
</svg>
<figcaption>The purple line is time. The non-blocking waiter finishes all three tables much sooner.</figcaption>
</figure>

- **Blocking** = stop and wait until a slow job finishes.
- **Non-blocking** = start a slow job, keep working, and come back when it is done.
- Slow jobs are things like reading a file, asking a database or calling another website.
- In 2009, most servers used a blocking style. Each waiting user held up memory.
- Node.js was made so one program could serve many users without waiting.

**Simple lesson:** Node.js was built to keep working while slow jobs finish in the background.

## History of Node.js

<figure className="ngc-fig node-fig">
<svg viewBox="0 0 560 205" role="img" aria-labelledby="fig-node-history" style={{ width: "100%", maxWidth: 560, height: "auto" }}>
  <title id="fig-node-history">Animation: a timeline of Node.js from 2009 to today</title>
  <line x1="40" y1="60" x2="520" y2="60" style={{ stroke: "var(--ngc-slate)", strokeWidth: 3 }} />
  <g opacity="1"><animate attributeName="opacity" values="1;1;1;0" keyTimes="0;0.5;0.95;1" dur="9s" repeatCount="indefinite" /><circle cx="50" cy="60" r="9" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 2 }} /><text x="50" y="40" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>2009</text><line x1="50" y1="69" x2="50" y2="81" style={{ stroke: "var(--ngc-blue)", strokeWidth: 1.5 }} /><text x="50" y="95" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Ryan Dahl shows</text><text x="50" y="109" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Node.js</text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.133;0.173;0.95;1" dur="9s" repeatCount="indefinite" /><circle cx="142" cy="60" r="9" style={{ fill: "var(--ngc-purple-soft)", stroke: "var(--ngc-purple)", strokeWidth: 2 }} /><text x="142" y="40" textAnchor="middle" style={{ fill: "var(--ngc-purple)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>2010</text><line x1="142" y1="69" x2="142" y2="136" style={{ stroke: "var(--ngc-purple)", strokeWidth: 1.5 }} /><text x="142" y="150" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>npm, the</text><text x="142" y="164" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>package tool,</text><text x="142" y="178" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>arrives</text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.267;0.307;0.95;1" dur="9s" repeatCount="indefinite" /><circle cx="234" cy="60" r="9" style={{ fill: "var(--ngc-orange-soft)", stroke: "var(--ngc-orange)", strokeWidth: 2 }} /><text x="234" y="40" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>2015</text><line x1="234" y1="69" x2="234" y2="81" style={{ stroke: "var(--ngc-orange)", strokeWidth: 1.5 }} /><text x="234" y="95" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Node.js</text><text x="234" y="109" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Foundation is</text><text x="234" y="123" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>formed</text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.4;0.44;0.95;1" dur="9s" repeatCount="indefinite" /><circle cx="326" cy="60" r="9" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 2 }} /><text x="326" y="40" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>2019</text><line x1="326" y1="69" x2="326" y2="136" style={{ stroke: "var(--ngc-green)", strokeWidth: 1.5 }} /><text x="326" y="150" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Moves to the</text><text x="326" y="164" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>OpenJS</text><text x="326" y="178" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Foundation</text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.533;0.573;0.95;1" dur="9s" repeatCount="indefinite" /><circle cx="418" cy="60" r="9" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 2 }} /><text x="418" y="40" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>2022</text><line x1="418" y1="69" x2="418" y2="81" style={{ stroke: "var(--ngc-blue)", strokeWidth: 1.5 }} /><text x="418" y="95" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Node.js 18:</text><text x="418" y="109" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>built-in fetch</text><text x="418" y="123" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>and test runner</text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.667;0.707;0.95;1" dur="9s" repeatCount="indefinite" /><circle cx="510" cy="60" r="9" style={{ fill: "var(--ngc-purple-soft)", stroke: "var(--ngc-purple)", strokeWidth: 2 }} /><text x="510" y="40" textAnchor="middle" style={{ fill: "var(--ngc-purple)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>2027</text><line x1="510" y1="69" x2="510" y2="136" style={{ stroke: "var(--ngc-purple)", strokeWidth: 1.5 }} /><text x="510" y="150" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Node.js 27: one</text><text x="510" y="164" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>major version a</text><text x="510" y="178" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>year</text></g>
</svg>
<figcaption>Node.js grew from one person's project into a project run by a foundation.</figcaption>
</figure>

- **2009:** Ryan Dahl showed Node.js to the world.
- **2010:** npm arrived. It made sharing code packages easy.
- **2015:** a split in the community ended, and the Node.js Foundation was formed.
- **2019:** Node.js moved to the OpenJS Foundation, which looks after it today.
- **2022:** Node.js 18 added a built-in `fetch` and a built-in test runner.
- **Today:** new major versions come out on a fixed plan. From Node.js 27 (2027), the plan is one major version a year.

**Simple lesson:** Node.js started as one person's idea and is now run by a large open community.

## Inside Node.js: V8, libuv and C++ Bindings

Node.js is built from a few parts that work together.

- **V8** = the JavaScript engine from Google Chrome. It runs your JavaScript code.
- **libuv** = a C library that talks to the operating system. It handles files, network and timers without blocking.
- **C++ bindings** = the bridge between JavaScript and those C and C++ parts.
- **Node.js APIs** = ready tools like `fs` (files) and `http` (servers) that you call from JavaScript.
- **Thread pool** = a few helper workers inside libuv. They do some slow jobs, like reading files, in the background.

<figure className="ngc-fig node-fig">
<svg viewBox="0 0 560 275" role="img" aria-labelledby="fig-node-layers" style={{ width: "100%", maxWidth: 560, height: "auto" }}>
  <title id="fig-node-layers">Animation: a file request travels from your code through V8, the C++ bindings and libuv to the operating system, and the result comes back</title>
  <rect x="110" y="12" width="340" height="38" rx="10" style={{ fill: "var(--ngc-orange-soft)", stroke: "var(--ngc-orange)", strokeWidth: 1.5 }} />
  <text x="125" y="29" textAnchor="start" style={{ fill: "var(--ngc-orange)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>Your JavaScript (app.js)</text>
  <text x="125" y="44" textAnchor="start" style={{ fill: "var(--ink)", fontFamily: "var(--mono)", fontSize: 11, fontWeight: 500 }}>readFile("marks.txt")</text>
  <rect x="110" y="58" width="340" height="38" rx="10" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1.5 }} />
  <text x="125" y="75" textAnchor="start" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>V8 engine</text>
  <text x="125" y="90" textAnchor="start" style={{ fill: "var(--ink)", fontFamily: "var(--mono)", fontSize: 11, fontWeight: 500 }}>runs your JavaScript</text>
  <rect x="110" y="104" width="340" height="38" rx="10" style={{ fill: "var(--ngc-purple-soft)", stroke: "var(--ngc-purple)", strokeWidth: 1.5 }} />
  <text x="125" y="121" textAnchor="start" style={{ fill: "var(--ngc-purple)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>Node.js APIs + C++ bindings</text>
  <text x="125" y="136" textAnchor="start" style={{ fill: "var(--ink)", fontFamily: "var(--mono)", fontSize: 11, fontWeight: 500 }}>fs, http, process</text>
  <rect x="110" y="150" width="340" height="38" rx="10" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1.5 }} />
  <text x="125" y="167" textAnchor="start" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>libuv</text>
  <text x="125" y="182" textAnchor="start" style={{ fill: "var(--ink)", fontFamily: "var(--mono)", fontSize: 11, fontWeight: 500 }}>event loop, thread pool</text>
  <rect x="110" y="196" width="340" height="38" rx="10" style={{ fill: "var(--ngc-red-soft)", stroke: "var(--ngc-red)", strokeWidth: 1.5 }} />
  <text x="125" y="213" textAnchor="start" style={{ fill: "var(--ngc-red)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>Operating system</text>
  <text x="125" y="228" textAnchor="start" style={{ fill: "var(--ink)", fontFamily: "var(--mono)", fontSize: 11, fontWeight: 500 }}>disk, network, timers</text>
  <line x1="480" y1="31" x2="480" y2="215" style={{ stroke: "var(--ngc-slate)", strokeWidth: 2, strokeDasharray: "4 4" }} />
  <circle cx="480" cy="31" r="8" style={{ fill: "var(--ngc-orange)" }}><animate attributeName="cy" values="31;215;215;31;31" keyTimes="0;0.4;0.55;0.95;1" dur="8s" repeatCount="indefinite" /></circle>
  <g opacity="1"><animate attributeName="opacity" values="1;1;0;0" keyTimes="0;0.2;0.205;1" dur="8s" repeatCount="indefinite" /><text x="280" y="262" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>1. app.js asks for a file</text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.2;0.205;0.4;0.405;1" dur="8s" repeatCount="indefinite" /><text x="280" y="262" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>2. V8 and the bindings pass the job down</text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.4;0.405;0.55;0.555;1" dur="8s" repeatCount="indefinite" /><text x="280" y="262" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>3. libuv asks the operating system</text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.55;0.555;0.97;0.975;1" dur="8s" repeatCount="indefinite" /><text x="280" y="262" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>4. The file data comes back up</text></g>
</svg>
<figcaption>Your code sits on top. Node.js passes slow jobs down to libuv and the operating system.</figcaption>
</figure>

Watch the orange dot.

- **Going down:** your request passes from JavaScript to V8, then to the bindings, then to libuv.
- **At the bottom:** the operating system does the real work.
- **Coming up:** the answer travels back and your code gets the result.

**Simple lesson:** V8 runs your code, and libuv does the slow work with the operating system.

## Node.js vs Browser JavaScript

The language is the same. The tools are different.

<div className="tscroll">

| Topic | Browser JavaScript | Node.js |
|---|---|---|
| Where it runs | Inside a web page | In the terminal or on a server |
| Main global object | `window` | `global` (and `globalThis`) |
| Page tools | `document`, buttons, forms | None, there is no page |
| Files on disk | Not allowed, for safety | Yes, with the `fs` module |
| Program details | `navigator`, `location` | `process` (version, platform, arguments) |
| Who can run it | Anyone who opens the page | The person who starts the script |

</div>

Click **▶ Run** and read the terminal.

- **`window` and `document`:** both are `undefined`. Node.js has no web page.
- **`process`:** it exists. It tells you the Node.js version and the operating system.

Code that uses `document` or `window` will crash in Node.js. Code that uses `process` or `fs` will not work in a browser.

**Simple lesson:** same language, different tools. Check which runtime your code is written for.

## Node.js vs Deno vs Bun

Node.js is not the only JavaScript runtime outside the browser.

<div className="tscroll">

| Runtime | Made by | What it is known for |
|---|---|---|
| Node.js | Ryan Dahl, now the OpenJS Foundation | The oldest and most used. Huge npm package world. |
| Deno | Ryan Dahl again, in 2018 | Built-in TypeScript and safety permissions turned on by default |
| Bun | Jarred Sumner, first released in 2022 | Speed, plus a package manager and test runner in one tool |

</div>

- Deno and Bun can run many npm packages, but not always every one.
- Most jobs, tutorials and companies still use Node.js.
- What you learn here, such as modules, async code and streams, helps with all three.

**Simple lesson:** learn Node.js first. The ideas carry over to Deno and Bun.

## LTS vs Current Releases

Node.js has two kinds of versions.

- **Current** = the newest version, with the newest features.
- **LTS** (Long Term Support) = a stable version that gets fixes for a long time.
- Up to Node.js 26, even-numbered versions, like 22 and 24, became LTS.
- Odd-numbered versions, like 23, stayed Current for a short time and then ended.
- From Node.js 27 (2027), the plan changes: one major version a year, and every version becomes LTS.
- Companies use LTS, because they want fewer surprises.

<figure className="ngc-fig node-fig">
<svg viewBox="0 0 560 215" role="img" aria-labelledby="fig-node-releases" style={{ width: "100%", maxWidth: 560, height: "auto" }}>
  <title id="fig-node-releases">Even-numbered Node.js versions get long-term support, odd-numbered versions end early</title>
  <text x="20" y="22" textAnchor="start" style={{ fill: "var(--muted)", fontFamily: "var(--sans)", fontSize: 12, fontWeight: 500 }}>Each bar is one major version. Time goes from left to right.</text>
  <text x="40" y="55" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--mono)", fontSize: 12, fontWeight: 700 }}>v20</text>
  <rect x="70" y="40" width="60" height="20" rx="4" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1 }} />
  <text x="100" y="54" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 10, fontWeight: 700 }}>Current</text>
  <rect x="130" y="40" width="170" height="20" rx="4" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1 }} />
  <text x="215" y="54" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 10, fontWeight: 700 }}>LTS: long support</text>
  <text x="40" y="85" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--mono)", fontSize: 12, fontWeight: 700 }}>v21</text>
  <rect x="120" y="70" width="60" height="20" rx="4" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1 }} />
  <text x="150" y="84" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 10, fontWeight: 700 }}>Current</text>
  <rect x="180" y="70" width="30" height="20" rx="4" style={{ fill: "var(--ngc-red-soft)", stroke: "var(--ngc-red)", strokeWidth: 1 }} />
  <text x="230" y="84" textAnchor="start" style={{ fill: "var(--ngc-red)", fontFamily: "var(--sans)", fontSize: 10, fontWeight: 700 }}>ends</text>
  <text x="40" y="115" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--mono)", fontSize: 12, fontWeight: 700 }}>v22</text>
  <rect x="170" y="100" width="60" height="20" rx="4" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1 }} />
  <text x="200" y="114" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 10, fontWeight: 700 }}>Current</text>
  <rect x="230" y="100" width="170" height="20" rx="4" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1 }} />
  <text x="315" y="114" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 10, fontWeight: 700 }}>LTS: long support</text>
  <text x="40" y="145" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--mono)", fontSize: 12, fontWeight: 700 }}>v23</text>
  <rect x="220" y="130" width="60" height="20" rx="4" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1 }} />
  <text x="250" y="144" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 10, fontWeight: 700 }}>Current</text>
  <rect x="280" y="130" width="30" height="20" rx="4" style={{ fill: "var(--ngc-red-soft)", stroke: "var(--ngc-red)", strokeWidth: 1 }} />
  <text x="330" y="144" textAnchor="start" style={{ fill: "var(--ngc-red)", fontFamily: "var(--sans)", fontSize: 10, fontWeight: 700 }}>ends</text>
  <text x="40" y="175" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--mono)", fontSize: 12, fontWeight: 700 }}>v24</text>
  <rect x="270" y="160" width="60" height="20" rx="4" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1 }} />
  <text x="300" y="174" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 10, fontWeight: 700 }}>Current</text>
  <rect x="330" y="160" width="170" height="20" rx="4" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1 }} />
  <text x="415" y="174" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 10, fontWeight: 700 }}>LTS: long support</text>
  <text x="280" y="205" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>Up to Node.js 26: even numbers become LTS, odd numbers end early.</text>
</svg>
<figcaption>Use an LTS version for real projects. Try Current to see new features.</figcaption>
</figure>

For learning and for real projects, install the LTS version shown on nodejs.org.

**Simple lesson:** pick LTS for safety. Pick Current only to try new features.

## Prerequisites

You need a little JavaScript before this course.

- **Basic JavaScript:** variables, `if`, loops, functions and objects. See **Introduction**, **Function Basics** and **Object Fundamentals** in the JavaScript course.
- **Promises and async/await:** many Node.js tools are asynchronous. See **Promises and Async/Await**.
- **Command-line basics:** open a terminal and move between folders.

These terminal commands are enough to start:

<div className="tscroll">

| Job | Windows (PowerShell) | Mac and Linux |
|---|---|---|
| Show the current folder | `pwd` | `pwd` |
| List files | `dir` or `ls` | `ls` |
| Go into a folder | `cd reports` | `cd reports` |
| Go up one folder | `cd ..` | `cd ..` |
| Make a folder | `mkdir reports` | `mkdir reports` |

</div>

**Simple lesson:** basic JavaScript and a few terminal commands are all you need.

## Course Roadmap

<figure className="ngc-fig node-fig">
<svg viewBox="0 0 560 195" role="img" aria-labelledby="fig-node-roadmap" style={{ width: "100%", maxWidth: 560, height: "auto" }}>
  <title id="fig-node-roadmap">The six chapters of this course, followed by the Express.js course</title>
  <path d="M 40 70 L 520 70" style={{ stroke: "var(--ngc-slate)", strokeWidth: 3 }} />
  <g opacity="1"><animate attributeName="opacity" values="1;1;1;0" keyTimes="0;0.5;0.95;1" dur="8s" repeatCount="indefinite" /><circle cx="55" cy="70" r="18" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 2 }} /><text x="55" y="75" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 14, fontWeight: 700 }}>1</text><text x="55" y="112" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Foundations</text><text x="55" y="127" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}></text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.12;0.17;0.95;1" dur="8s" repeatCount="indefinite" /><circle cx="141" cy="70" r="18" style={{ fill: "var(--ngc-purple-soft)", stroke: "var(--ngc-purple)", strokeWidth: 2 }} /><text x="141" y="75" textAnchor="middle" style={{ fill: "var(--ngc-purple)", fontFamily: "var(--sans)", fontSize: 14, fontWeight: 700 }}>2</text><text x="141" y="112" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Async</text><text x="141" y="127" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Node.js</text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.24;0.29;0.95;1" dur="8s" repeatCount="indefinite" /><circle cx="227" cy="70" r="18" style={{ fill: "var(--ngc-orange-soft)", stroke: "var(--ngc-orange)", strokeWidth: 2 }} /><text x="227" y="75" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontFamily: "var(--sans)", fontSize: 14, fontWeight: 700 }}>3</text><text x="227" y="112" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>System and</text><text x="227" y="127" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Files</text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.36;0.41;0.95;1" dur="8s" repeatCount="indefinite" /><circle cx="313" cy="70" r="18" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 2 }} /><text x="313" y="75" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 14, fontWeight: 700 }}>4</text><text x="313" y="112" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Network and</text><text x="313" y="127" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Parallel</text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.48;0.53;0.95;1" dur="8s" repeatCount="indefinite" /><circle cx="399" cy="70" r="18" style={{ fill: "var(--ngc-red-soft)", stroke: "var(--ngc-red)", strokeWidth: 2 }} /><text x="399" y="75" textAnchor="middle" style={{ fill: "var(--ngc-red)", fontFamily: "var(--sans)", fontSize: 14, fontWeight: 700 }}>5</text><text x="399" y="112" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Quality and</text><text x="399" y="127" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Production</text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.6;0.65;0.95;1" dur="8s" repeatCount="indefinite" /><circle cx="485" cy="70" r="18" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 2 }} /><text x="485" y="75" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 14, fontWeight: 700 }}>6</text><text x="485" y="112" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Project and</text><text x="485" y="127" textAnchor="middle" style={{ fill: "var(--ink)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 600 }}>Reference</text></g>
  <rect x="190" y="150" width="180" height="34" rx="10" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1.5 }} />
  <text x="280" y="172" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>Next course: Express.js</text>
  <path d="M 280 132 L 280 148" style={{ stroke: "var(--ngc-green)", strokeWidth: 2 }} />
</svg>
<figcaption>Each chapter uses what the one before it taught.</figcaption>
</figure>

- **Foundations:** what Node.js is, modules and npm packages.
- **Asynchronous Node.js:** the event loop, events and error handling.
- **System and Files:** the `process` object, the file system and streams.
- **Networking and Parallelism:** HTTP servers, child processes and worker threads.
- **Quality and Production:** testing, debugging, security and going live.
- **Project and Reference:** one full project and a cheat sheet.

After this course, the **Express.js** course shows how a framework makes web servers easier.

**Simple lesson:** each chapter builds on the last, and Express.js comes next.

## Installing Node.js

1. Open **nodejs.org** in your browser.
2. Download the **LTS** installer for your computer.
3. Run the installer and keep the default options.
4. Close any open terminal and open a new one.
5. Type `node -v` and press Enter.

```bash
node -v
npm -v
```

- `node -v` prints the Node.js version, such as `v24.11.0`. Your number may be different.
- `npm -v` prints the npm version. npm comes with Node.js.
- If you see "not recognized", close the terminal and open a new one.

### Version Managers: nvm and fnm

**Version manager** = a tool that installs many Node.js versions and switches between them.

- One project may need Node.js 22. Another may need Node.js 24.
- A version manager lets both live on one computer.
- **nvm** works on Mac and Linux. **nvm-windows** is a separate tool for Windows.
- **fnm** is a fast version manager that works on Windows, Mac and Linux.

```bash
# with nvm
nvm install --lts      # install the newest LTS version
nvm use 22             # switch to Node.js 22

# with fnm
fnm install --lts
fnm use 22
```

**Simple lesson:** install the LTS from nodejs.org, or use nvm or fnm to keep many versions.

## Running Scripts with node

- `node app.js` runs the file `app.js` in the current folder.
- `node app.ts` runs a TypeScript file. Recent Node.js versions remove the types and run the code. Pick JavaScript or TypeScript for the labs with the **Language** menu at the top.
- Words after the file name are **arguments**. The script can read them.
- `process.argv` = the list of words typed in the command.
- `process.argv[0]` is the path to Node.js. `process.argv[1]` is the script. Your own words start at `process.argv[2]`.

Click **▶ Run**. The lab runs `node app.js Ravi 8`.

- **`process.argv[2]`** became `Ravi`.
- **`process.argv[3]`** became `8`.
- **Note:** arguments always arrive as text, even numbers like `8`.

### Watch Mode

```bash
node --watch app.js
```

- `--watch` runs the script again every time you save the file.
- Press **Ctrl + C** to stop it.

**Simple lesson:** `node file.js` runs a script, and `process.argv` holds the extra words.

## The Node.js REPL

**REPL** = Read, Eval, Print, Loop.

- Type `node` with no file name and press Enter.
- Node.js **reads** the line you type.
- It **evaluates** (runs) it.
- It **prints** the answer.
- It **loops** back and waits for your next line.

<figure className="ngc-fig node-fig">
<svg viewBox="0 0 560 230" role="img" aria-labelledby="fig-node-repl" style={{ width: "100%", maxWidth: 560, height: "auto" }}>
  <title id="fig-node-repl">Animation: the REPL reads what you type, evaluates it, prints the answer and loops back for the next line</title>
  <circle cx="120" cy="120" r="80" style={{ fill: "none", stroke: "var(--ngc-slate)", strokeWidth: 2, strokeDasharray: "5 5" }} />
  <circle cx="120" cy="40" r="30" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 2 }}><animate attributeName="r" values="30;30;36;30;30" keyTimes="0;0.0;0.12;0.25;1" dur="6s" repeatCount="indefinite" /></circle>
  <text x="120" y="45" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>Read</text>
  <circle cx="200" cy="120" r="30" style={{ fill: "var(--ngc-purple-soft)", stroke: "var(--ngc-purple)", strokeWidth: 2 }}><animate attributeName="r" values="30;30;36;30;30" keyTimes="0;0.25;0.37;0.5;1" dur="6s" repeatCount="indefinite" /></circle>
  <text x="200" y="125" textAnchor="middle" style={{ fill: "var(--ngc-purple)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>Eval</text>
  <circle cx="120" cy="200" r="30" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 2 }}><animate attributeName="r" values="30;30;36;30;30" keyTimes="0;0.5;0.62;0.75;1" dur="6s" repeatCount="indefinite" /></circle>
  <text x="120" y="205" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>Print</text>
  <circle cx="40" cy="120" r="30" style={{ fill: "var(--ngc-orange-soft)", stroke: "var(--ngc-orange)", strokeWidth: 2 }}><animate attributeName="r" values="30;30;36;30;30" keyTimes="0;0.75;0.87;1.0;1" dur="6s" repeatCount="indefinite" /></circle>
  <text x="40" y="125" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>Loop</text>
  <rect x="290" y="30" width="250" height="180" rx="8" style={{ fill: "var(--ngc-win)", stroke: "var(--ngc-slate)", strokeWidth: 1.5 }} />
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.02;0.04;0.97;1" dur="6s" repeatCount="indefinite" /><text x="305" y="60" textAnchor="start" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--mono)", fontSize: 13, fontWeight: 700 }}>&gt; 2 + 3</text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.5;0.52;0.97;1" dur="6s" repeatCount="indefinite" /><text x="305" y="84" textAnchor="start" style={{ fill: "var(--ngc-green)", fontFamily: "var(--mono)", fontSize: 13, fontWeight: 700 }}>5</text></g>
  <g opacity="0"><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.75;0.77;0.97;1" dur="6s" repeatCount="indefinite" /><text x="305" y="108" textAnchor="start" style={{ fill: "var(--ngc-blue)", fontFamily: "var(--mono)", fontSize: 13, fontWeight: 700 }}>&gt; _</text></g>
  <text x="415" y="190" textAnchor="middle" style={{ fill: "var(--muted)", fontFamily: "var(--sans)", fontSize: 11, fontWeight: 500 }}>You type, Node answers</text>
</svg>
<figcaption>Read, Eval, Print, Loop: one line in, one answer out, then wait for the next line.</figcaption>
</figure>

```text
$ node
Welcome to Node.js v24.11.0.
Type ".help" for more information.
> 2 + 3
5
> const name = "Asha"
undefined
> name.toUpperCase()
'ASHA'
> _
'ASHA'
> .exit
```

- `_` (underscore) holds the last answer.
- Press the **up arrow** to bring back an earlier line.
- `.help` lists the REPL commands.
- `.exit`, or **Ctrl + C** two times, leaves the REPL.

The REPL is a quick calculator and test bench. This page's labs run whole files instead, like `node app.js`.

**Simple lesson:** type `node` alone to try one line at a time.

## Common CLI Flags

**Flag** = an extra word starting with `-` or `--` that changes what a command does.

<div className="tscroll">

| Flag | Short form | What it does | Example |
|---|---|---|---|
| `--version` | `-v` | Prints the Node.js version | `node -v` |
| `--help` | `-h` | Lists the flags Node.js knows | `node --help` |
| `--check` | `-c` | Checks the file for typing mistakes without running it | `node --check app.js` |
| `--eval` | `-e` | Runs the code inside the quotes | `node -e "console.log(5 * 2)"` |
| `--print` | `-p` | Runs the code and prints the answer | `node -p "5 * 2"` |
| `--watch` | | Runs again when you save the file | `node --watch app.js` |

</div>

```bash
$ node -e "console.log('Hi from eval')"
Hi from eval
$ node -p "365 * 24"
8760
```

- `-e` prints only what your code logs.
- `-p` prints the answer of the expression for you.

Click **▶ Run**. The lab runs `node --check app.js`.

- **The error:** `SyntaxError` means the code is typed wrongly.
- **The cause:** the closing `)` is missing after `subject`.
- **Fix it:** add the `)` and press ▶ Run again. Now nothing is printed, which means the code is fine.

**Simple lesson:** flags change what `node` does. `--check` finds typing mistakes before you run.

## Globals and Built-in APIs

**Global** = a name you can use in any file without importing it.

### global and globalThis

- **`globalThis`** = the standard name for the global object. It works in browsers and in Node.js.
- **`global`** = the older Node.js-only name for the same object.
- Tools like `console` and `setTimeout` live on it.
- Adding your own values to it is usually a bad idea, because any file can change them.

**Simple lesson:** use `globalThis` when you need the global object.

### The console Toolbox

**`console`** = a built-in tool for printing messages.

- `console.log()` prints normal output.
- `console.error()` prints error output.
- `console.table()` prints an array of objects as a table.
- `console.group()` and `console.groupEnd()` indent lines into a group.
- `console.time()` and `console.timeEnd()` measure how long code takes.

Click **▶ Run** and read the terminal.

- **The table:** `console.table` made rows from the array and columns from the object keys.
- **The group:** `Asha` is indented because it is inside the `Toppers` group.
- **The timer:** the time in `ms` may be different every run.
- **The error line:** it appears in red. In a real terminal it goes to a separate channel called **stderr**.

`console.table` is great for checking data quickly. Try adding a fourth student and run it again.

### Web-Compatible Globals

Some web tools also work in Node.js. You do not need to import them.

- **`URL`** = reads the parts of a web address.
- **`TextEncoder`** = turns text into bytes.
- **`structuredClone`** = makes a full, deep copy of an object.
- **`fetch`** = gets data from a website. Its own lesson comes later.
- **`setTimeout`** = runs a function after a delay.

- **`URL`:** `searchParams.get("class")` read `8` from the address.
- **`structuredClone`:** changing the copy did not change the original.

### Node.js-Specific Globals

These names exist only in Node.js.

- **`process`** = facts about the running program: version, platform, arguments and folder.
- **`Buffer`** = raw bytes, used with files and networks.
- **`setImmediate`** = runs a function right after the current code finishes.
- **`__dirname` and `__filename`** = the folder and file of the script, in CommonJS files only.
- **`require`** = loads a module, in CommonJS files only.

- **`setImmediate`:** line 3 printed last, even though it was written first.
- **`Buffer`:** `48 69` are the bytes for the letters `H` and `i`.
- **`__dirname` and `require`:** you will meet them in **Modules in Node.js**.

**Simple lesson:** some globals come from the web, and some, like `process`, belong only to Node.js.

## Common mistakes

<div className="tscroll">

| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| Typing `node app.js` inside the REPL | The REPL runs files | Leave the REPL with `.exit`, then run `node app.js` | `SyntaxError`, because the REPL reads it as JavaScript |
| Using `document` or `window` in a script | Node.js has a web page | Node.js has no page. Use `process` and modules | `ReferenceError: document is not defined` |
| Running a file from the wrong folder | Node.js finds files anywhere | Use `cd` to go to the folder first | `Error: Cannot find module` |
| Installing an odd-numbered version for a project | Newest is always best | Use the LTS version | Support ends soon, and tools may break |
| Treating `process.argv[2]` as a number | Arguments keep their type | Arguments are always text. Use `Number()` | `"8" + 1` gives `"81"` |
| Using an old terminal after installing | The terminal sees new programs at once | Open a new terminal | `'node' is not recognized` |

</div>

## TL;DR

1. **Node.js** = a runtime that runs JavaScript outside the browser.
2. **Runtime** = a program that runs code and gives it tools.
3. **Non-blocking** = start a slow job, keep working, handle the result later.
4. **V8** = runs JavaScript. **libuv** = does files, network and timers with the operating system.
5. **LTS** = the stable version with long support. Use it for real projects.
6. **REPL** = Read, Eval, Print, Loop. Start it with `node`.
7. **Flags** = extra words that change a command.
   - `-v` version, `--check` syntax check, `-e` run code, `-p` print an answer, `--watch` rerun on save
8. **`globalThis`** = the global object. **`process`** = facts about the running program.

## Check Yourself

## Exercises

## What to Remember

- Node.js runs JavaScript outside the browser, from the terminal.
- It was built to keep working while slow jobs finish.
- V8 runs your code. libuv talks to the operating system.
- There is no `window` or `document`. There is `process`.
- Use the LTS version, and run files with `node file.js`.
- `globalThis`, `console`, `URL` and `process` are ready to use without importing.

Next: **Modules in Node.js**. You will split a program into many files and share code between them.
