Node.js: Introduction to Node.js
Alice is a backend developer. Her company needed to build a REST API backend for a mobile app within two weeks. The team consisted entirely of frontend developers who only knew JavaScript, and no one was willing to spend time learning a new language. The project manager even considered hiring a Python developer, but there simply wasn’t enough time. Just as the team was starting to feel anxious, Alice discovered Node.js—a runtime that runs JavaScript on the server. Front-end developers could write backend APIs using the syntax they were already familiar with, and the project went live successfully two weeks later. This made Alice realize that Node.js isn’t just a tool—it’s a bridge connecting the front end and the back end.
You'll learn:
- Definition and Core Purpose of Node.js
- The Underlying Architecture of the V8 Engine and Node.js
- How Event-Driven and Non-Blocking I/O Work
- Key Differences Between Node.js and Browser JavaScript
- Node.js Versioning Policies and Typical Use Cases
1. What Is Node.js?
(1) Definition
Node.js is a JavaScript runtime environment based on the Chrome V8 engine. It allows JavaScript to run directly on the server, independent of the browser. Node.js is neither a new language nor a framework, but rather a server-side execution platform for JavaScript.
(2) Background of Its Origin
In 2009, Ryan Dahl created Node.js based on the V8 engine. His original goal was to solve the problem of blocking caused by server-side I/O operations—traditional web servers block threads when handling I/O operations such as file reads and network requests, whereas Node.js uses an event-driven approach, allowing a single thread to efficiently handle a large value of concurrent connections.
▶ Example: Your First Node.js Script
Create file hello.js:
console.log('Hello, Node.js!');
console.log('Node.js version:', process.version);
console.log('Platform:', process.platform);
Run the following in the terminal:
node hello.js
Expected Output:
Hello, Node.js!
Node.js version: v20.11.0
Platform: win32
2. The V8 Engine and the Node.js Architecture
(1) The Role of the V8 Engine
V8 is a JavaScript engine developed by Google that compiles JavaScript code into machine code for execution. Node.js has the V8 engine built right in, which is why it delivers such high performance. V8’s just-in-time (JIT) compilation technology allows JavaScript to run at speeds close to those of native code.
(2) Node.js Architecture Layers
The Node.js architecture is divided into four layers from the bottom up:
| Level | Composition | Function |
|---|---|---|
| JavaScript code layer | User-written .js files | Business logic |
| Node.js API layer | Modules such as fs, http, and path | Provides server-side capabilities |
| Node.js Bindings Layer | C++ Bridge Code | Connecting JavaScript to the Underlying C Library |
| Low-level libraries | V8, libuv, OpenSSL, etc. | Engines and system calls |
(3) The Key Role of libuv
libuv is Node.js's asynchronous I/O library, providing an event loop, a thread pool, and a cross-platform abstraction for asynchronous I/O. It enables Node.js to handle asynchronous operations—such as file I/O, network operations, and timers—in a consistent manner across different operating systems.
▶ Example: Viewing Node.js dependency information
console.log('V8 version:', process.versions.v8);
console.log('libuv version:', process.versions.libuv);
console.log('OpenSSL version:', process.versions.openssl);
console.log('Node.js version:', process.version);
Output:
V8 version: 11.3.244.8
libuv version: 1.46.0
OpenSSL version: 3.0.12
Node.js version: v20.11.0
▶ Example: (4) Architecture Diagram
graph TB
A["JavaScript Code<br/>(User-written .js Documents)"] --> B["Node.js API<br/>(fs / http / path / ...)"]
B --> C["Node.js Bindings<br/>(C++ Bridge Layer)"]
C --> D1["V8 Engine<br/>(JavaScript Compile and Run)"]
C --> D2["libuv<br/>(Event Loop + Asynchronous I/O)"]
C --> D3["Other C Libs<br/>(OpenSSL / zlib / c-ares)"]
D2 --> E["Operating System<br/>(Documents / Internet / Process)"]
3. Event-Driven and Non-Blocking I/O
(1) Event-Driven Model
Node.js uses an event-driven architecture: the program responds to various operations by registering event callbacks, rather than actively polling. When an I/O operation is complete, the event loop places the corresponding callback in a queue to await execution.
(2) The Meaning of Non-Blocking I/O
Traditional servers block the current thread while reading a file until the file has been fully read. Node.js returns immediately after initiating an I/O request, continues executing the subsequent code, and then processes the result via a callback once the I/O operation is complete. This approach allows a single thread to handle hundreds of concurrent requests simultaneously.
(3) Introduction to the Event Loop
The event loop is Node.js's core scheduling mechanism, which runs in a loop through the following phases:
- timers: Execute the setTimeout / setInterval callback
- Pending callbacks: Callbacks that perform system operations
- idle, prepare: For internal use
- poll: Retrieves new I/O events and executes I/O callbacks
- check: Execute the setImmediate callback
- close callbacks: Execute close event callbacks
▶ Example: Blocking vs. Non-blocking File Reads
Blocking Mode (Not Recommended):
const fs = require('fs');
const data = fs.readFileSync('/etc/hosts', 'utf8');
console.log('File read (blocking):', data.length, 'bytes');
console.log('This line runs after file is read');
Non-blocking mode (recommended):
const fs = require('fs');
fs.readFile('/etc/hosts', 'utf8', (err, data) => {
if (err) throw err;
console.log('File read (non-blocking):', data.length, 'bytes');
});
console.log('This line runs immediately');
Output (non-blocking mode):
This line runs immediately
File read (non-blocking): 250 bytes
Note that in non-blocking mode, "This line runs immediately" is printed first, indicating that readFile did not block the subsequent code.
4. Node.js vs. Browser JavaScript
(1) Key Differences
Node.js and JavaScript in the browser use the same language specification (ECMAScript), but their runtime environments and available APIs are completely different.
| Comparison Criteria | Node.js | Browser JavaScript |
|---|---|---|
| Runtime Environment | Server | Browser |
| Module System | CommonJS / ESM | ESM |
| Global Object | global / process | window / document |
| File System | Direct access via the fs module | Cannot be accessed directly |
| Network I/O | http / net modules | fetch / XMLHttpRequest |
| DOM Manipulation | No DOM | DOM API |
| Package Manager | npm | None (or via CDN) |
| Primary Uses | Server applications, CLI tools | Web interactions, UI rendering |
(2) Similarities
- All comply with the ECMAScript standard
- Both use the V8 engine (Chrome and Node.js)
- Both support Promise / async-await
- They all have an event loop mechanism
▶ Example: Same Syntax, Different APIs
Browser code:
document.getElementById('output').textContent = 'Hello from browser';
Node.js code:
const fs = require('fs');
fs.writeFileSync('output.txt', 'Hello from Node.js');
The JavaScript syntax is the same, but the objects being manipulated are completely different: browsers manipulate the DOM, while Node.js manipulates the file system.
5. Typical Use Cases for Node.js
(1) REST API Service
Node.js is well-suited for building RESTful APIs. Its non-blocking I/O model efficiently handles many concurrent requests, and JSON is JavaScript's native data format, eliminating serialization overhead.
(2) CLI Tools
Webpack, Babel, ESLint, and npm are all CLI tools built using Node.js. Node.js provides a rich set of APIs for handling the file system, child processes, and command-line arguments.
(3) Real-Time Applications
Scenarios such as chat systems, online collaboration, and real-time notifications require persistent, bidirectional connections. Node.js’s WebSocket support and event-driven architecture are naturally well-suited to these needs.
(4) Microservices
Node.js starts up quickly and uses little memory, making it ideal for lightweight microservices. Each microservice can be deployed and scaled independently.
(5) Web Crawling and Data Collection
When combined with libraries such as Cheerio, Node.js can efficiently crawl and parse web data, and asynchronous I/O makes concurrent requests extremely efficient.
▶ Example: Comparison of Use Cases
| Scenario | Advantages | Representative Projects |
|---|---|---|
| REST API | Non-blocking I/O + Native JSON | Express / Fastify / Koa |
| CLI Tools | File Operations + Subprocesses | Webpack / Babel / ESLint |
| Real-time Applications | WebSocket + Event-Driven | Socket.IO / ws |
| Microservices | Lightweight + Quick to Set Up | NestJS / Seneca |
| Web Scraping | Asynchronous Concurrency + DOM Parsing | Puppeteer / Cheerio |
▶ Example: Create an HTTP server in 5 lines of code
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'Hello from Node.js API' }));
});
server.listen(3000, () => console.log('Server running on port 3000'));
node server.js
Server running on port 3000
Visit http://localhost:3000 to view the JSON response.
6. Node.js Version Policy
(1) LTS and Current
Node.js uses a dual-track release strategy:
| Comparison | LTS (Long-Term Support) | Current |
|---|---|---|
| Release Cycle | One major release every two years | One major release every 6 months |
| Maintenance Period | 30 months | Approximately 6 months |
| Stability | High; only bug fixes and security patches are included | Low; includes the latest features |
| Use Cases | Production Environment | Try out new features, testing |
| Version Numbering Rules | Even numbers (18, 20, 22...) | Odd numbers (19, 21, 23...) |
(2) Recommendations for Choosing a Version
- Production Projects: Always use the Active LTS version
- Learning Phase: We recommend using Active LTS, as it offers the most comprehensive resources and ecosystem.
- Experimental Feature: The Current version can be used, but it is not recommended for production use.
(3) Version Control Tools
We recommend using nvm (Node Version Manager) to manage and switch between Node.js versions.
▶ Example: Managing versions with nvm
nvm install 20
nvm use 20
nvm ls
v18.17.0
-> v20.11.0
system
default -> 20 (-> v20.11.0)
▶ Example: Check the current Node.js version and status
node -v
node -e "console.log(process.release.lts ? 'LTS: ' + process.release.lts : 'Current (non-LTS)')"
v20.11.0
LTS: Iron
❓ FAQ
package.json or node_modules directory, and includes built-in formatting and testing tools in its standard library. The Deno ecosystem is still growing, while the Node.js ecosystem is more mature.node -v in the terminal to verify it works.📖 Summary
- Node.js is a server-side JavaScript runtime based on the V8 engine; it is not a new language.
- The architecture consists of four layers: JavaScript code → Node.js API → Bindings → Underlying libraries (V8 / libuv)
- Event-driven + non-blocking I/O is the core mechanism for Node.js high concurrency
- Node.js uses the same syntax as browser JavaScript, but its APIs and runtime environments are completely different.
- Typical use cases: REST APIs, CLI tools, real-time applications, microservices, web crawlers
- Be sure to use the LTS version in production environments, and manage multiple versions with nvm.
📝 Exercises
- Install Node.js (LTS version recommended), run
node -vto verify that the installation was successful, and note down your version number and whether it is an LTS version. - Create a file named
hello.js, useconsole.logto output your name and the Node.js version number, run it, and take a screenshot - Write a script that uses the
processobject to output the following information: Node.js version, operating system platform, current working directory, and CPU architecture. - Use
fs.readFileto read a text file in non-blocking mode and output its contents, then observe the execution order of the callback functions - Compare
fs.readFileSync(blocking) andfs.readFile(non-blocking) by printing timestamps before and after the callback, respectively, while reading the same file, to illustrate the difference in their execution.
7. Comprehensive Example: Script for Reading System Information
The following script uses Node.js's built-in modules to read and output system information, demonstrating Node.js's basic capabilities as a server-side runtime:
const os = require('os');
const fs = require('fs');
const path = require('path');
const sysInfo = {
nodeVersion: process.version,
platform: process.platform,
arch: process.arch,
hostname: os.hostname(),
totalMemoryMB: Math.round(os.totalmem() / 1024 / 1024),
freeMemoryMB: Math.round(os.freemem() / 1024 / 1024),
cpuCores: os.cpus().length,
cpuModel: os.cpus()[0].model,
uptimeHours: (os.uptime() / 3600).toFixed(2),
cwd: process.cwd(),
homedir: os.homedir()
};
const output = JSON.stringify(sysInfo, null, 2);
console.log(output);
const filePath = path.join(os.homedir(), 'nodejs-sysinfo.txt');
fs.writeFile(filePath, output, 'utf8', (err) => {
if (err) {
console.error('Write failed:', err.message);
return;
}
console.log('System info saved to:', filePath);
});
Expected Output:
{
"nodeVersion": "v20.11.0",
"platform": "win32",
"arch": "x64",
"hostname": "DESKTOP-ABC123",
"totalMemoryMB": 16384,
"freeMemoryMB": 8192,
"cpuCores": 8,
"cpuModel": "Intel(R) Core(TM) i7-12700K",
"uptimeHours": "48.32",
"cwd": "C:\\projects\\node-demo",
"homedir": "C:\\Users\\Alice"
}
System info saved to: C:\Users\Alice\nodejs-sysinfo.txt
The script demonstrates three core capabilities of Node.js: retrieving operating system information (os), writing to a file (fs), and handling paths (path). It also uses non-blocking I/O to write to a file—the callback for fs.writeFile executes after console.log, illustrating the event-driven nature of Node.js.