Node.js入门教程(一):初识Node.js——服务端JavaScript的诞生与特点

前言:什么是Node.js?

简单地说,Node.js就是运行在服务端的JavaScript

在Node.js出现之前,JavaScript只能运行在浏览器中,负责页面的交互和动态效果。2009年,Ryan Dahl创造性地把Google Chrome的V8引擎从浏览器中剥离出来,让JavaScript得以在服务器端运行------这就是Node.js的起源。

Node.js不是一个编程语言,而是一个运行时平台:它让JavaScript能够读写文件、创建网络服务、操作数据库,做一切传统服务端语言(如PHP、Java、Python)能做的事情。

一句话概括:Node.js = Chrome V8引擎 + 事件驱动架构 + 丰富的标准库。

一、Node.js的核心特点

1.1 事件驱动与非阻塞I/O

这是Node.js最核心的设计哲学。

传统服务端(如PHP、Java Servlet) 在处理请求时,如果遇到I/O操作(比如读取文件、查询数据库),线程会被阻塞------必须等I/O完成后才能继续处理下一个请求。这意味着每个请求都需要占用一个线程,并发量高时,线程数量暴增,内存和CPU开销巨大。

Node.js的做法截然不同:当遇到I/O操作时,它不会等待,而是立即去处理下一个请求。等I/O操作完成后,通过"事件回调"的方式来通知处理结果。

用生活中的例子来理解:

  • 传统同步方式:你去食堂打饭,排到窗口后告诉师傅"我要一份红烧肉",然后你就站在窗口前等着,直到师傅把菜做好端给你,你才离开------这期间你什么事都做不了。

  • Node.js异步方式:你告诉师傅"我要一份红烧肉",师傅给你一个取餐号,你就可以先去找座位坐下、刷刷手机,等师傅叫号时再去取餐------等待的时间里,你完全可以做其他事情。

复制代码
// 同步方式(阻塞)—— Node.js中一般不这么用
const fs = require('fs');
const data = fs.readFileSync('/path/to/file.txt', 'utf8');
console.log(data); // 必须等文件读完后才会执行后面的代码
console.log('这句话要等文件读完才会打印');

// 异步方式(非阻塞)—— Node.js的推荐方式
const fs = require('fs');
fs.readFile('/path/to/file.txt', 'utf8', (err, data) => {
    if (err) throw err;
    console.log(data); // 文件读完才会执行这个回调
});
console.log('这句话会立即打印,不用等文件读完');

这种非阻塞I/O + 事件回调的机制,让Node.js可以用单线程处理成千上万的并发连接,非常适合I/O密集型应用。

1.2 单线程与事件循环

Node.js是单线程的------只有一个主线程在执行你的JavaScript代码。

听到"单线程",你可能会担心性能问题。但Node.js的"单线程"指的是JavaScript代码的执行是单线程的,而I/O操作实际上是由底层系统(libuv库)通过多线程来完成的。

**事件循环(Event Loop)**是Node.js的核心机制:

  1. 你的代码按顺序执行,遇到异步操作就交给底层处理,自己继续往下走

  2. 底层处理完异步操作后,把回调函数放入事件队列

  3. 当主线程空闲时,事件循环不断地从队列中取出回调并执行

这个机制让单线程的Node.js能够高效处理大量并发请求------请求来了就处理,遇到I/O就"挂起"去处理下一个,I/O完成后再回来继续。

1.3 跨平台支持

Node.js基于V8引擎(C++编写),通过libuv库抽象了操作系统底层的I/O操作,因此可以在Windows、Linux、macOS等多个平台上运行,代码几乎不用修改。

你可以用以下命令查看当前Node.js版本:

复制代码
$ node -v
v20.10.0

注意:不同版本之间可能存在API差异,建议使用LTS(长期支持)版本。

二、Node.js能做什么?

Node.js的应用场景非常广泛,以下是几个典型方向:

应用场景 说明 典型工具/框架
Web服务器 处理HTTP请求,返回HTML/JSON Express、Koa、NestJS
RESTful API / GraphQL 为前端提供数据接口 Express、Apollo Server
实时应用 聊天室、在线协作、游戏 Socket.io
命令行工具 自动化脚本、构建工具 CLI工具、Webpack
后端微服务 分布式系统中的一个服务 NestJS、gRPC
全栈开发 前后端都用JavaScript Next.js、Nuxt.js

三、开发环境搭建

3.1 安装Node.js

访问 Node.js官网,下载LTS版本安装包,按提示安装即可。

安装完成后,在终端验证:

node -v v20.10.0 npm -v 10.2.3
npm(Node Package Manager)是Node.js的包管理工具,会随Node.js一起安装。

3.2 选择合适的编辑器

编辑器 特点 推荐指数
VS Code 免费、插件丰富、调试方便 ⭐⭐⭐⭐⭐
WebStorm 功能强大、智能提示 ⭐⭐⭐⭐
Vim/Neovim 轻量、键盘流 ⭐⭐⭐

四、你的第一个Node.js程序

4.1 脚本模式(推荐方式)

创建一个文件 hello.js,写入以下代码:

复制代码
// hello.js
console.log("Hello, Node.js!");
console.log("欢迎来到RUNOOB Node.js教程!");

// 打印当前Node.js版本
console.log("Node.js版本:", process.version);

// 打印当前工作目录
console.log("当前目录:", process.cwd());

在终端运行:

复制代码
$ node hello.js

输出结果:

复制代码
Hello, Node.js!
欢迎来到RUNOOB Node.js教程!
Node.js版本: v20.10.0
当前目录: /your/project/path

4.2 交互模式(REPL)

打开终端,输入 node 进入交互模式,可以逐行执行JavaScript代码:

复制代码
$ node
> console.log('Hello World!');
Hello World!
> const x = 10;
> const y = 20;
> x + y
30
> .exit    # 退出交互模式

交互模式适合快速测试代码片段,但正式开发时还是推荐用脚本文件。

4.3 第一个HTTP服务

恭喜你,你已经写出了第一个Node.js程序。现在让我们更进一步------用Node.js创建一个最简单的HTTP服务器:

复制代码
// server.js
const http = require('http');

// 创建一个HTTP服务器
const server = http.createServer((req, res) => {
    // 设置响应头,告诉浏览器返回的是HTML
    res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
    // 返回响应内容
    res.end(`
        <h1>欢迎来到RUNOOB Node.js教程!</h1>
        <p>你的第一个Node.js HTTP服务器已成功运行 🎉</p>
        <p>请求地址: ${req.url}</p>
    `);
});

// 监听3000端口
server.listen(3000, () => {
    console.log('服务器已启动: http://localhost:3000');
    console.log('按 Ctrl+C 停止服务器');
});

保存为 server.js,然后运行:

复制代码
$ node server.js

打开浏览器访问 http://localhost:3000,你会看到:

!服务器运行效果描述

这就是一个完整的Web服务器!虽然只有短短十几行代码,但它已经能处理HTTP请求并返回HTML页面了。

五、npm与包管理基础

npm是Node.js的"应用商店",你可以通过它安装别人写好的第三方包,也可以发布自己的包。

5.1 初始化项目

复制代码
# 创建一个新目录
mkdir my-node-project
cd my-node-project

# 初始化package.json(一路回车使用默认值)
npm init -y

package.json 是项目的配置文件,记录了项目名、版本、依赖包等信息。

5.2 安装第三方包

复制代码
# 安装一个包(如moment,用于日期处理)
npm install moment

# 安装开发依赖(只在开发时使用,生产环境不需要)
npm install nodemon --save-dev

安装后,node_modules目录会存放所有依赖包,package.json中会增加依赖记录。

5.3 使用第三方包

复制代码
// app.js
const moment = require('moment');

const now = moment();
console.log('当前时间:', now.format('YYYY-MM-DD HH:mm:ss'));
console.log('今天是星期', now.day()); // 0=周日, 1=周一...

运行:

复制代码
$ node app.js

注意node_modules目录很大,不要提交到Git仓库,需要在.gitignore中忽略它。

六、第一个项目实战:欢迎页面

现在让我们把前面的知识串联起来,创建一个带路由的小项目。

复制代码
// project.js
const http = require('http');
const fs = require('fs');
const path = require('path');

const server = http.createServer((req, res) => {
    const url = req.url;

    // 根据不同路径返回不同内容
    if (url === '/') {
        res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
        res.end(`
            <h1>🏠 首页</h1>
            <p>欢迎来到RUNOOB Node.js教程!</p>
            <ul>
                <li><a href="/about">关于</a></li>
                <li><a href="/time">当前时间</a></li>
            </ul>
        `);
    } else if (url === '/about') {
        res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
        res.end(`
            <h1>📖 关于</h1>
            <p>这是RUNOOB Node.js入门教程的第一个项目。</p>
            <p>我们正在学习用Node.js创建Web服务器!</p>
            <a href="/">← 返回首页</a>
        `);
    } else if (url === '/time') {
        const now = new Date();
        res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
        res.end(`
            <h1>🕐 当前时间</h1>
            <p>服务器时间: ${now.toLocaleString('zh-CN')}</p>
            <p>时间戳: ${now.getTime()}</p>
            <a href="/">← 返回首页</a>
        `);
    } else {
        // 404 页面
        res.writeHead(404, { 'Content-Type': 'text/html; charset=utf-8' });
        res.end(`
            <h1>404 - 页面未找到</h1>
            <p>你访问的页面 "${url}" 不存在</p>
            <a href="/">← 返回首页</a>
        `);
    }
});

server.listen(3000, () => {
    console.log('🚀 项目已启动: http://localhost:3000');
    console.log('📂 按 Ctrl+C 停止服务器');
});

运行并访问不同路径,体验Node.js的HTTP服务能力。

七、常见问题与调试技巧

7.1 端口被占用

复制代码
# 报错:Error: listen EADDRINUSE: address already in use :::3000
# 解决方案:换一个端口(如3001),或关闭占用端口的进程

7.2 代码修改后需要重启

Node.js默认不会自动监测文件变化,修改代码后需要手动重启:

复制代码
# 按 Ctrl+C 停止,再重新运行
$ node project.js

开发时可以使用 nodemon 实现自动重启:

复制代码
# 全局安装nodemon
npm install -g nodemon

# 用nodemon运行
nodemon project.js

7.3 调试技巧

复制代码
// 使用console.log打印调试信息
console.log('变量值:', someVariable);

// 使用debugger语句(需要在Chrome开发者工具中调试)
debugger;

// 使用Node.js内置调试器
// node inspect project.js

八、本章小结

知识点 说明
Node.js是什么 服务端JavaScript运行环境
核心特点 事件驱动、非阻塞I/O、单线程事件循环
适用场景 Web服务、API、实时应用、CLI工具
运行方式 node xxx.js(脚本模式)/ node(交互模式)
包管理 npm(安装、管理、发布第三方包)
相关推荐
嘟嘟07171 小时前
从手写 HashRouter 到 React Router:逐层拆解 SPA 前端路由的完整实现
前端·javascript
生戎马 平安京策2 小时前
只学一点点:我的技术学习策略
前端·javascript·react.js
北冥you鱼3 小时前
Go语言大数(big.Int)比较大小:原理、方法与最佳实践
开发语言·后端·golang
宁之明起(B服)3 小时前
Java 反序列化漏洞-xmldecoder/SnakeYAM
java·开发语言
__zRainy__3 小时前
React之reduce实现compose和中间件
javascript·react.js·ecmascript
xcLeigh3 小时前
Go入门:零值与变量默认初始化机制
开发语言·后端·golang
deviant-ART3 小时前
java stream 的 findFirst 及 findAny 方法遇到 null 元素时会出现 NullPointerException
java·开发语言
银-豆豆3 小时前
Python爬虫
开发语言·爬虫·python
zmzb01033 小时前
C++课后习题训练记录Day179
开发语言·c++