Node.js快速入门
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,让 JavaScript 可以在服务器端运行。本文面向有一定编程基础的开发者,快速介绍 Node.js 的核心概念、常用模块和开发实践。
# 一、Node.js 简介
# 什么是 Node.js
Node.js 是一个开源、跨平台的 JavaScript 运行时环境,于 2009 年由 Ryan Dahl 创建。它让 JavaScript 从浏览器走向了服务器端,使得开发者可以使用 JavaScript 编写后端代码。
Node.js 与 JavaScript 的关系:
- JavaScript 是一门编程语言,定义了语法和核心特性(变量、函数、对象等)
- Node.js 是 JavaScript 的运行环境,提供了文件系统、网络、进程等系统级 API
- 如果你还不熟悉 JavaScript,建议先阅读 JavaScript极简入门 和 JavaScript高级特性详解
Node.js 的核心特性包括:
- 事件驱动:基于事件循环的异步 I/O 模型
- 非阻塞 I/O:高效处理并发请求
- 单线程:主线程单线程,但通过事件循环实现高并发
- 跨平台:支持 Windows、macOS、Linux
- NPM 生态:拥有世界上最大的开源库生态系统
# Node.js 的优势
- 高性能:非阻塞 I/O 和事件驱动适合 I/O 密集型应用
- 统一语言栈:前后端都使用 JavaScript,降低学习成本
- 丰富的生态:NPM 拥有超过 100 万个开源包
- 实时应用:WebSocket、SSE 等实时通信场景
- 微服务友好:轻量级、启动快、适合容器化部署
# 适用场景
- Web 服务器:Express、Koa、Fastify
- RESTful API:快速构建后端接口
- 实时应用:聊天室、在线协作工具
- 微服务:轻量级服务、API 网关
- 工具链:构建工具(Webpack、Vite)、脚手架、CLI 工具
- SSR:服务端渲染(Next.js、Nuxt.js)
# 不适用场景
- CPU 密集型应用:复杂计算、图像处理(阻塞事件循环)
- 传统企业应用:复杂的事务处理、强类型要求
# 二、安装与环境配置
# 安装 Node.js
访问 Node.js 官网 (opens new window) 下载安装包:
- LTS(长期支持版):推荐生产环境使用
- Current(当前版本):包含最新特性
验证安装:
node -v # 查看 Node.js 版本
npm -v # 查看 NPM 版本
# 使用 nvm 管理版本
nvm (opens new window)(Node Version Manager)可以方便地切换 Node.js 版本:
# 安装 nvm(macOS/Linux)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
# Windows 使用 nvm-windows
# https://github.com/coreybutler/nvm-windows
# 安装指定版本
nvm install 18.20.0
nvm install 20.11.0
# 切换版本
nvm use 18.20.0
# 查看已安装版本
nvm list
# 设置默认版本
nvm alias default 18.20.0
# Hello World
创建 app.js:
console.log('Hello, Node.js!');
运行:
node app.js
# 三、模块系统
Node.js 支持两种模块系统:CommonJS(传统)和 ES Modules(现代)。
# CommonJS
// math.js
const PI = 3.14159;
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
module.exports = {
PI,
add,
subtract
};
// 或者分别导出
exports.PI = PI;
exports.add = add;
// app.js
const math = require('./math');
console.log(math.PI); // 3.14159
console.log(math.add(5, 3)); // 8
// 解构导入
const { add, subtract } = require('./math');
console.log(add(5, 3)); // 8
# ES Modules
在 package.json 中添加 "type": "module",或使用 .mjs 后缀:
// math.mjs
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
export default class Calculator {
multiply(a, b) {
return a * b;
}
}
// app.mjs
import Calculator, { PI, add } from './math.mjs';
console.log(PI); // 3.14159
console.log(add(5, 3)); // 8
const calc = new Calculator();
console.log(calc.multiply(5, 3)); // 15
# 内置模块
Node.js 提供了丰富的内置模块,无需安装即可使用:
const fs = require('fs'); // 文件系统
const path = require('path'); // 路径处理
const http = require('http'); // HTTP 服务器
const url = require('url'); // URL 解析
const os = require('os'); // 操作系统信息
const crypto = require('crypto'); // 加密
const util = require('util'); // 工具函数
# 四、文件系统(fs)
# 同步读取文件
const fs = require('fs');
try {
const data = fs.readFileSync('file.txt', 'utf8');
console.log(data);
} catch (err) {
console.error('读取文件失败:', err);
}
# 异步读取文件(回调)
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) {
console.error('读取文件失败:', err);
return;
}
console.log(data);
});
# 异步读取文件(Promise)
const fs = require('fs').promises;
async function readFile() {
try {
const data = await fs.readFile('file.txt', 'utf8');
console.log(data);
} catch (err) {
console.error('读取文件失败:', err);
}
}
readFile();
# 写入文件
const fs = require('fs').promises;
async function writeFile() {
try {
await fs.writeFile('output.txt', 'Hello, Node.js!', 'utf8');
console.log('文件写入成功');
} catch (err) {
console.error('写入文件失败:', err);
}
}
writeFile();
# 追加内容
const fs = require('fs').promises;
async function appendFile() {
try {
await fs.appendFile('log.txt', 'New log entry\n', 'utf8');
console.log('内容追加成功');
} catch (err) {
console.error('追加失败:', err);
}
}
appendFile();
# 文件操作
const fs = require('fs').promises;
// 删除文件
await fs.unlink('file.txt');
// 重命名文件
await fs.rename('old.txt', 'new.txt');
// 复制文件
await fs.copyFile('source.txt', 'dest.txt');
// 检查文件是否存在
try {
await fs.access('file.txt');
console.log('文件存在');
} catch {
console.log('文件不存在');
}
// 获取文件信息
const stats = await fs.stat('file.txt');
console.log('文件大小:', stats.size);
console.log('是否是文件:', stats.isFile());
console.log('是否是目录:', stats.isDirectory());
# 目录操作
const fs = require('fs').promises;
// 创建目录
await fs.mkdir('mydir');
// 递归创建目录
await fs.mkdir('a/b/c', { recursive: true });
// 读取目录
const files = await fs.readdir('mydir');
console.log(files);
// 删除目录(必须为空)
await fs.rmdir('mydir');
// 递归删除目录
await fs.rm('mydir', { recursive: true, force: true });
# 流式读写(大文件)
const fs = require('fs');
// 读取流
const readStream = fs.createReadStream('large.txt', { encoding: 'utf8' });
readStream.on('data', (chunk) => {
console.log('读取数据块:', chunk.length);
});
readStream.on('end', () => {
console.log('读取完成');
});
readStream.on('error', (err) => {
console.error('读取错误:', err);
});
// 写入流
const writeStream = fs.createWriteStream('output.txt');
writeStream.write('Hello, ');
writeStream.write('Node.js!');
writeStream.end();
// 管道(复制文件)
const readStream = fs.createReadStream('source.txt');
const writeStream = fs.createWriteStream('dest.txt');
readStream.pipe(writeStream);
# 五、路径处理(path)
const path = require('path');
// 路径拼接(跨平台)
const filePath = path.join('/user', 'docs', 'file.txt');
console.log(filePath); // /user/docs/file.txt(Windows: \user\docs\file.txt)
// 绝对路径
const absPath = path.resolve('docs', 'file.txt');
console.log(absPath); // /current/working/directory/docs/file.txt
// 路径解析
const parsed = path.parse('/user/docs/file.txt');
console.log(parsed);
// {
// root: '/',
// dir: '/user/docs',
// base: 'file.txt',
// ext: '.txt',
// name: 'file'
// }
// 路径组合
const formatted = path.format({
dir: '/user/docs',
base: 'file.txt'
});
console.log(formatted); // /user/docs/file.txt
// 获取目录名
console.log(path.dirname('/user/docs/file.txt')); // /user/docs
// 获取文件名
console.log(path.basename('/user/docs/file.txt')); // file.txt
console.log(path.basename('/user/docs/file.txt', '.txt')); // file
// 获取扩展名
console.log(path.extname('/user/docs/file.txt')); // .txt
// 相对路径
const relative = path.relative('/user/docs', '/user/docs/files/file.txt');
console.log(relative); // files/file.txt
// 规范化路径
console.log(path.normalize('/user//docs/../file.txt')); // /user/file.txt
# 常用路径变量
console.log(__dirname); // 当前文件所在目录的绝对路径
console.log(__filename); // 当前文件的绝对路径
console.log(process.cwd()); // 当前工作目录
# 六、HTTP 服务器
# 创建简单 HTTP 服务器
const http = require('http');
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
res.end('Hello, Node.js!');
});
const PORT = 3000;
server.listen(PORT, () => {
console.log(`服务器运行在 http://localhost:${PORT}/`);
});
# 处理不同路由
const http = require('http');
const url = require('url');
const server = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url, true);
const pathname = parsedUrl.pathname;
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
if (pathname === '/') {
res.statusCode = 200;
res.end('首页');
} else if (pathname === '/about') {
res.statusCode = 200;
res.end('关于页面');
} else {
res.statusCode = 404;
res.end('页面未找到');
}
});
server.listen(3000, () => {
console.log('服务器运行在 http://localhost:3000/');
});
# 处理 POST 请求
const http = require('http');
const server = http.createServer((req, res) => {
if (req.method === 'POST') {
let body = '';
req.on('data', (chunk) => {
body += chunk.toString();
});
req.on('end', () => {
console.log('接收到的数据:', body);
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ message: '数据接收成功', data: body }));
});
} else {
res.statusCode = 405;
res.end('Method Not Allowed');
}
});
server.listen(3000);
# 返回 JSON
const http = require('http');
const server = http.createServer((req, res) => {
const data = {
name: 'Alice',
age: 30,
city: 'Beijing'
};
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(data));
});
server.listen(3000);
# 七、NPM 包管理
# 初始化项目
npm init # 交互式创建 package.json
npm init -y # 使用默认配置
# 安装依赖
# 安装生产依赖
npm install express
npm install lodash axios
# 安装开发依赖
npm install --save-dev nodemon eslint
# 全局安装
npm install -g nodemon
# 安装指定版本
npm install express@4.18.0
# 从 package.json 安装所有依赖
npm install
# package.json 结构
{
"name": "my-app",
"version": "1.0.0",
"description": "My Node.js application",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest"
},
"keywords": ["nodejs", "express"],
"author": "Your Name",
"license": "MIT",
"dependencies": {
"express": "^4.18.0"
},
"devDependencies": {
"nodemon": "^2.0.0"
}
}
# NPM 脚本
{
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js",
"test": "jest",
"lint": "eslint .",
"build": "webpack --mode production"
}
}
运行脚本:
npm start # 运行 start 脚本
npm run dev # 运行 dev 脚本
npm test # 运行 test 脚本
# 常用 NPM 命令
# 卸载包
npm uninstall express
# 更新包
npm update express
npm update # 更新所有包
# 查看已安装的包
npm list
npm list --depth=0 # 只显示顶层依赖
# 查看包信息
npm info express
# 搜索包
npm search mongodb
# 查看过时的包
npm outdated
# 清理缓存
npm cache clean --force
# 八、常用 Web 框架
# Express
const express = require('express');
const app = express();
// 中间件
app.use(express.json()); // 解析 JSON 请求体
app.use(express.urlencoded({ extended: true })); // 解析 URL 编码请求体
// 路由
app.get('/', (req, res) => {
res.send('Hello, Express!');
});
app.get('/api/users', (req, res) => {
res.json([
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
]);
});
app.post('/api/users', (req, res) => {
const user = req.body;
console.log('接收到用户:', user);
res.status(201).json({ message: '用户创建成功', user });
});
// 路由参数
app.get('/api/users/:id', (req, res) => {
const userId = req.params.id;
res.json({ id: userId, name: 'User ' + userId });
});
// 查询参数
app.get('/search', (req, res) => {
const query = req.query.q;
res.json({ search: query });
});
// 错误处理
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: '服务器错误' });
});
app.listen(3000, () => {
console.log('服务器运行在 http://localhost:3000');
});
# Koa
const Koa = require('koa');
const Router = require('@koa/router');
const bodyParser = require('koa-bodyparser');
const app = new Koa();
const router = new Router();
// 中间件
app.use(bodyParser());
// 路由
router.get('/', async (ctx) => {
ctx.body = 'Hello, Koa!';
});
router.get('/api/users', async (ctx) => {
ctx.body = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
});
router.post('/api/users', async (ctx) => {
const user = ctx.request.body;
ctx.status = 201;
ctx.body = { message: '用户创建成功', user };
});
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000, () => {
console.log('服务器运行在 http://localhost:3000');
});
# 九、环境变量
# 使用 process.env
const PORT = process.env.PORT || 3000;
const DB_HOST = process.env.DB_HOST || 'localhost';
console.log(`服务器端口: ${PORT}`);
console.log(`数据库地址: ${DB_HOST}`);
运行时指定环境变量:
PORT=8080 node app.js
# 使用 dotenv
安装:
npm install dotenv
创建 .env 文件:
PORT=3000
DB_HOST=localhost
DB_USER=admin
DB_PASSWORD=secret
NODE_ENV=development
使用:
require('dotenv').config();
console.log(process.env.PORT); // 3000
console.log(process.env.DB_HOST); // localhost
console.log(process.env.DB_USER); // admin
console.log(process.env.NODE_ENV); // development
# 十、错误处理
# try-catch
async function readFile() {
try {
const fs = require('fs').promises;
const data = await fs.readFile('file.txt', 'utf8');
console.log(data);
} catch (err) {
console.error('读取文件失败:', err.message);
}
}
readFile();
# 捕获未处理的异常
// 未捕获的异常
process.on('uncaughtException', (err) => {
console.error('未捕获的异常:', err);
process.exit(1); // 退出进程
});
// 未处理的 Promise 拒绝
process.on('unhandledRejection', (reason, promise) => {
console.error('未处理的 Promise 拒绝:', reason);
process.exit(1);
});
// 触发异常
setTimeout(() => {
throw new Error('测试异常');
}, 1000);
# 自定义错误类
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
this.statusCode = 400;
}
}
class NotFoundError extends Error {
constructor(message) {
super(message);
this.name = 'NotFoundError';
this.statusCode = 404;
}
}
// 使用
function validateUser(user) {
if (!user.name) {
throw new ValidationError('用户名不能为空');
}
}
try {
validateUser({});
} catch (err) {
if (err instanceof ValidationError) {
console.error('验证失败:', err.message);
}
}
# 十一、调试
# console 调试
console.log('普通日志');
console.error('错误日志');
console.warn('警告日志');
console.info('信息日志');
console.debug('调试日志');
// 格式化输出
console.log('用户:', { name: 'Alice', age: 30 });
console.table([
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 25 }
]);
// 计时
console.time('操作');
// 执行一些操作...
console.timeEnd('操作'); // 操作: 123.456ms
# Node.js Inspector
# 启动调试模式
node --inspect app.js
node --inspect-brk app.js # 启动时暂停
# 在 Chrome 浏览器中访问
chrome://inspect
# VS Code 调试
创建 .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "启动程序",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/app.js"
}
]
}
# 十二、实用工具
# nodemon(自动重启)
安装:
npm install -g nodemon
# 或作为开发依赖
npm install --save-dev nodemon
使用:
nodemon app.js
配置 nodemon.json:
{
"watch": ["src"],
"ext": "js,json",
"ignore": ["node_modules"],
"exec": "node app.js"
}
# pm2(进程管理)
安装:
npm install -g pm2
使用:
pm2 start app.js # 启动应用
pm2 start app.js --name myapp # 指定名称
pm2 list # 查看所有进程
pm2 logs # 查看日志
pm2 restart myapp # 重启应用
pm2 stop myapp # 停止应用
pm2 delete myapp # 删除应用
pm2 monit # 监控面板
# 十三、总结
Node.js 是一个强大的服务器端 JavaScript 运行时,掌握以下核心内容即可快速上手:
- 模块系统:CommonJS、ES Modules
- 文件系统:读写文件、目录操作、流式处理
- HTTP 服务器:创建服务器、路由处理、请求/响应
- NPM:包管理、依赖安装、脚本运行
- Web 框架:Express、Koa
- 环境变量:dotenv 配置管理
- 错误处理:try-catch、自定义错误
- 调试工具:console、Inspector、nodemon、pm2
Node.js 的强大之处在于其丰富的生态系统和高效的异步模型,适合构建现代化的 Web 应用和微服务。更多高级特性(如流、缓冲区、子进程、集群等),详见Node.js高级特性详解。
祝你变得更强!
编辑 (opens new window)
上次更新: 2025/11/07