Express.js 官方文档教程

概述

Express.js 是一个基于 Node.js 的快速、无约束的、极简的 Web 框架。它简化了 Node.js 的 HTTP 模块,提供了更简洁的 API 和丰富的中间件生态系统。本教程将引导你深入了解 Express.js 的官方文档,帮助你掌握如何有效地使用和扩展 Express.js。

1. Express.js 简介和特点

1.1 什么是 Express.js?

Express.js 是一个轻量级的 Web 应用框架,用于构建 Web 应用和 API。它基于 Node.js 的 HTTP 模块,提供了路由、中间件、模板引擎等功能。

1.2 Express.js 的特点

  • 快速:Express.js 设计简洁,性能优越。
  • 灵活:支持多种中间件和插件,易于扩展。
  • 极简:核心功能精简,专注于 Web 应用的基本需求。

2. 环境搭建

2.1 安装 Node.js 和 npm

首先,你需要安装 Node.js 和 npm(Node Package Manager)。你可以从 Node.js 官网 下载并安装。

# 检查 Node.js 和 npm 是否安装成功
node -v
npm -v

2.2 创建项目目录

mkdir my-express-app
cd my-express-app

2.3 初始化 npm 项目

npm init -y

2.4 安装 Express.js

npm install express

3. 创建第一个 Express.js 应用

3.1 创建 app.js 文件

// app.js
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(port, () => {
  console.log(`App listening at http://localhost:${port}`);
});

3.2 运行应用

node app.js

打开浏览器,访问 http://localhost:3000,你应该会看到 "Hello World!"。

4. 路由基础

4.1 什么是路由?

路由是指确定如何响应客户端对特定端点的请求。在 Express.js 中,路由由 HTTP 方法(如 GET、POST)和 URL 路径定义。

4.2 基本路由示例

app.get('/about', (req, res) => {
  res.send('About page');
});

app.post('/submit', (req, res) => {
  res.send('Form submitted');
});

5. 中间件概念

5.1 什么是中间件?

中间件是一个函数,它可以访问请求对象(req)、响应对象(res)以及应用程序的请求-响应周期中的下一个中间件函数(next)。

5.2 中间件示例

app.use((req, res, next) => {
  console.log('Time:', Date.now());
  next();
});

6. 请求和响应对象

6.1 请求对象(req)

请求对象包含客户端请求的信息,如 URL、HTTP 头、请求体等。

app.get('/user/:id', (req, res) => {
  res.send(`User ID: ${req.params.id}`);
});

6.2 响应对象(res)

响应对象用于向客户端发送响应。

app.get('/', (req, res) => {
  res.send('Hello World!');
});

7. 路由进阶

7.1 路由参数

路由参数用于捕获 URL 中的动态部分。

app.get('/user/:id', (req, res) => {
  res.send(`User ID: ${req.params.id}`);
});

7.2 查询字符串

查询字符串用于传递额外的参数。

app.get('/search', (req, res) => {
  res.send(`Search query: ${req.query.q}`);
});

8. 静态文件服务

8.1 提供静态文件

Express.js 提供了 express.static 中间件来提供静态文件服务。

app.use(express.static('public'));

9. 模板引擎

9.1 使用 EJS 模板引擎

EJS 是一个简单的模板引擎,允许你在 HTML 中嵌入 JavaScript。

npm install ejs
app.set('view engine', 'ejs');

app.get('/', (req, res) => {
  res.render('index', { title: 'My Express App' });
});

10. 错误处理

10.1 错误处理中间件

错误处理中间件用于捕获和处理错误。

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

11. 常用中间件介绍

11.1 body-parser

body-parser 用于解析请求体。

npm install body-parser
const bodyParser = require('body-parser');
app.use(bodyParser.json());

12. 自定义中间件开发

12.1 创建自定义中间件

const logger = (req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next();
};

app.use(logger);

13. 第三方中间件集成

13.1 集成 morgan 日志中间件

npm install morgan
const morgan = require('morgan');
app.use(morgan('dev'));

14. 身份认证中间件

14.1 使用 passport 进行身份认证

npm install passport
const passport = require('passport');
app.use(passport.initialize());
app.use(passport.session());

15. 文件上传处理

15.1 使用 multer 处理文件上传

npm install multer
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });

app.post('/upload', upload.single('file'), (req, res) => {
  res.send('File uploaded');
});

16. MongoDB 与 Mongoose

16.1 连接 MongoDB

npm install mongoose
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/mydatabase', { useNewUrlParser: true, useUnifiedTopology: true });

17. SQL 数据库 (MySQL, PostgreSQL)

17.1 使用 mysql 连接 MySQL

npm install mysql
const mysql = require('mysql');
const connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'mydatabase'
});

connection.connect();

18. ORM 工具 (Sequelize)

18.1 使用 Sequelize 连接数据库

npm install sequelize
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql'
});

19. 数据验证和安全性

19.1 使用 joi 进行数据验证

npm install joi
const Joi = require('joi');

const schema = Joi.object({
  username: Joi.string().alphanum().min(3).max(30).required(),
  password: Joi.string().pattern(new RegExp('^[a-zA-Z0-9]{3,30}$')).required(),
});

app.post('/register', (req, res) => {
  const { error } = schema.validate(req.body);
  if (error) return res.status(400).send(error.details[0].message);
  res.send('Validation passed');
});

20. RESTful 设计原则

20.1 RESTful API 设计

RESTful API 遵循一组设计原则,如使用 HTTP 方法(GET、POST、PUT、DELETE)来操作资源。

app.get('/api/users', (req, res) => {
  res.json(users);
});

app.post('/api/users', (req, res) => {
  const user = req.body;
  users.push(user);
  res.status(201).json(user);
});

21. API 版本控制

21.1 版本控制策略

API 版本控制可以通过 URL 或 HTTP 头实现。

app.get('/api/v1/users', (req, res) => {
  res.json(users);
});

app.get('/api/v2/users', (req, res) => {
  res.json(usersV2);
});

22. 数据序列化和反序列化

22.1 使用 JSON 进行序列化和反序列化

app.get('/api/users', (req, res) => {
  res.json(users);
});

app.post('/api/users', (req, res) => {
  const user = req.body;
  users.push(user);
  res.status(201).json(user);
});

23. API 文档生成 (Swagger)

23.1 使用 swagger-jsdoc 和 swagger-ui-express

npm install swagger-jsdoc swagger-ui-express
const swaggerJsDoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');

const swaggerOptions = {
  swaggerDefinition: {
    info: {
      title: 'My API',
      version: '1.0.0',
    },
  },
  apis: ['app.js'],
};

const swaggerDocs = swaggerJsDoc(swaggerOptions);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs));

24. 缓存策略

24.1 使用 express-cache-controller

npm install express-cache-controller
const cacheControl = require('express-cache-controller');

app.use(cacheControl({ maxAge: 3600 }));

25. 压缩和 GZIP

25.1 使用 compression 中间件

npm install compression
const compression = require('compression');
app.use(compression());

26. 安全最佳实践

26.1 使用 helmet 增强安全性

npm install helmet
const helmet = require('helmet');
app.use(helmet());

27. 跨域资源共享 (CORS)

27.1 使用 cors 中间件

npm install cors
const cors = require('cors');
app.use(cors());

28. 负载均衡

28.1 使用 nginx 进行负载均衡

http {
  upstream myapp {
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
  }

  server {
    listen 80;

    location / {
      proxy_pass http://myapp;
    }
  }
}

29. 单元测试 (Mocha, Chai)

29.1 使用 mocha 和 chai 进行单元测试

npm install mocha chai
const chai = require('chai');
const expect = chai.expect;

describe('Array', () => {
  it('should return -1 when the value is not present', () => {
    expect([1, 2, 3].indexOf(4)).to.equal(-1);
  });
});

30. 集成测试

30.1 使用 supertest 进行集成测试

npm install supertest
const request = require('supertest');
const app = require('../app');

describe('GET /api/users', () => {
  it('should return a list of users', (done) => {
    request(app)
      .get('/api/users')
      .expect(200)
      .end((err, res) => {
        if (err) return done(err);
        expect(res.body).to.be.an('array');
        done();
      });
  });
});

31. 性能测试

31.1 使用 loadtest 进行性能测试

npm install -g loadtest
loadtest -n 1000 -c 100 http://localhost:3000/

32. 调试技巧

32.1 使用 node-inspector 进行调试

npm install -g node-inspector
node-debug app.js

33. 日志管理

33.1 使用 winston 进行日志管理

npm install winston
const winston = require('winston');
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' }),
  ],
});

34. 部署到云平台 (Heroku, AWS)

34.1 部署到 Heroku

heroku create
git push heroku master

34.2 部署到 AWS

eb init
eb create

35. 容器化 (Docker)

35.1 创建 Dockerfile

FROM node:14
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]

35.2 构建和运行 Docker 容器

docker build -t my-express-app .
docker run -p 3000:3000 my-express-app

36. 进程管理 (PM2)

36.1 使用 pm2 管理 Node.js 进程

npm install -g pm2
pm2 start app.js

37. 监控和日志

37.1 使用 pm2 进行监控和日志管理

pm2 monit
pm2 logs

38. CI/CD 流程

38.1 使用 GitHub Actions 进行 CI/CD

name: CI/CD
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Set up Node.js
      uses: actions/setup-node@v2
      with