Node.js后端开发入门

Node.js后端开发

Node.js让JavaScript从浏览器走向了服务器,使得前端开发者能够使用同一门语言完成全栈开发。这一变革性的技术不仅打破了前后端的边界,还催生了无数的Web应用和服务。在这篇文章中,我将带你从零开始学习Node.js后端开发,掌握构建现代Web服务的核心技能。

理解Node.js

Node.js是基于Chrome V8引擎的JavaScript运行时,它让JavaScript可以在服务端运行。与浏览器环境不同,Node.js提供了文件系统、网络、进程等底层API,让JavaScript具备了完整的服务端能力。

Node.js的特点

  • 事件驱动:基于事件循环模型,高效处理并发
  • 非阻塞I/O:I/O操作不会阻塞主线程
  • 单线程:主线程单线程,通过事件循环处理并发
  • 跨平台:支持Windows、macOS、Linux
  • 丰富的包管理:npm拥有世界上最大的开源库生态系统

适用场景

Node.js特别适合I/O密集型应用:Web服务器、API服务、实时通信、数据流处理等。但对于CPU密集型任务(如视频编码、科学计算),Node.js不是最佳选择,因为计算会阻塞事件循环。

快速开始

安装Node.js

推荐使用nvm(Node Version Manager)安装和管理Node.js版本:

# 安装nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash

# 安装Node.js
nvm install --lts
nvm use --lts

# 验证安装
node -v
npm -v

第一个Node.js程序

// app.js
console.log('Hello, Node.js!');

// 运行
// node app.js

创建HTTP服务器

const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World\n');
});

server.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});

包管理器npm

package.json

{
  "name": "my-app",
  "version": "1.0.0",
  "description": "A Node.js application",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js",
    "test": "jest"
  },
  "dependencies": {
    "express": "^4.18.0"
  },
  "devDependencies": {
    "nodemon": "^3.0.0"
  }
}

常用命令

# 初始化项目
npm init -y

# 安装依赖
npm install express
npm install -D nodemon

# 全局安装
npm install -g pm2

# 运行脚本
npm run dev

Express框架

Express框架

Express是Node.js最流行的Web框架,简洁灵活,适合构建各种Web应用。

基础使用

const express = require('express');
const app = express();

// 中间件:解析JSON请求体
app.use(express.json());

// 路由
app.get('/', (req, res) => {
  res.json({ message: 'Hello API' });
});

app.post('/users', (req, res) => {
  const { name, email } = req.body;
  // 创建用户逻辑
  res.status(201).json({ id: 1, name, email });
});

app.put('/users/:id', (req, res) => {
  const { id } = req.params;
  const { name } = req.body;
  // 更新用户逻辑
  res.json({ id, name });
});

app.delete('/users/:id', (req, res) => {
  // 删除用户逻辑
  res.status(204).end();
});

// 错误处理
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Something went wrong!' });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

中间件

中间件是Express的核心概念,它是在请求和响应之间执行的函数:

// 日志中间件
app.use((req, res, next) => {
  console.log(`${req.method} ${req.path} - ${new Date().toISOString()}`);
  next();
});

// 身份验证中间件
function authMiddleware(req, res, next) {
  const token = req.headers.authorization;
  if (!token) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  // 验证token
  req.user = verifyToken(token);
  next();
}

// 在特定路由使用
app.get('/profile', authMiddleware, (req, res) => {
  res.json({ user: req.user });
});

数据库操作

MongoDB

const mongoose = require('mongoose');

// 连接数据库
mongoose.connect('mongodb://localhost/myapp');

// 定义模型
const UserSchema = new mongoose.Schema({
  name: { type: String, required: true },
  email: { type: String, required: true, unique: true },
  createdAt: { type: Date, default: Date.now }
});

const User = mongoose.model('User', UserSchema);

// CRUD操作
async function createUser(data) {
  return await User.create(data);
}

async function findUser(id) {
  return await User.findById(id);
}

async function updateUser(id, data) {
  return await User.findByIdAndUpdate(id, data, { new: true });
}

async function deleteUser(id) {
  return await User.findByIdAndDelete(id);
}

SQL数据库(PostgreSQL)

const { Pool } = require('pg');

const pool = new Pool({
  host: 'localhost',
  database: 'myapp',
  user: 'postgres',
  password: 'password'
});

// 查询
async function getUsers() {
  const { rows } = await pool.query('SELECT * FROM users');
  return rows;
}

async function createUser(name, email) {
  const { rows } = await pool.query(
    'INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *',
    [name, email]
  );
  return rows[0];
}

安全性

安全中间件

const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const cors = require('cors');

// 安全HTTP头
app.use(helmet());

// CORS
app.use(cors({
  origin: 'https://myapp.com',
  credentials: true
}));

// 速率限制
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15分钟
  max: 100 // 每IP最多100个请求
});
app.use('/api/', limiter);

输入验证

const { body, validationResult } = require('express-validator');

app.post('/users',
  body('email').isEmail().normalizeEmail(),
  body('name').trim().notEmpty().escape(),
  (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
    // 处理请求
  }
);

部署

PM2进程管理

# 安装PM2
npm install -g pm2

# 启动应用
pm2 start app.js --name "myapp"

# 查看状态
pm2 status

# 日志
pm2 logs myapp

# 开机自启
pm2 startup
pm2 save

Docker部署

# Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]

最佳实践

  1. 使用异步/await:避免回调地狱,代码更清晰
  2. 环境变量管理:使用dotenv管理配置
  3. 统一错误处理:集中处理异常,避免崩溃
  4. 日志记录:使用winston或pino记录日志
  5. API文档:使用Swagger自动生成文档
  6. 单元测试:使用Jest编写测试
  7. 安全检查:使用npm audit检查依赖漏洞

总结

Node.js为前端开发者打开了后端的大门,让你可以用同一门语言完成全栈开发。从理解事件循环开始,掌握Express框架、数据库操作、安全防护,你就能构建出生产级别的Web服务。

继续学习:深入学习TypeScript与Node.js结合、微服务架构、消息队列等高级主题,你的Node.js技能会更上一层楼。