首页 / NestJS 入门教程 / 压缩与版本控制

NestJS 入门教程

压缩与版本控制

本教程共 47 篇 · 第 35 篇 · 更新于 2026-08-09 · 约 9 分钟阅读

NestJS压缩版本控制API版本gzipFastify

本节目标:学会给 API 响应开启压缩以减小传输体积,以及用版本控制让新旧接口和平共存。

响应压缩

你的接口返回一个 JSON,可能也就几 KB。但如果返回的是列表数据、HTML 页面或者大段文本,体积就上去了。

压缩就是在服务端把响应体压一下,客户端收到后自动解压。对用户来说完全透明,但传输体积能缩小 60%-80%。

Express 项目

compression 这个中间件:

npm install compression
npm install -D @types/compression

main.ts 里启用:

import * as compression from 'compression';

// 在 app 创建之后、listen 之前
app.use(compression());

就这么简单。所有经过 Express 的响应都会自动 gzip 压缩。

Fastify 项目

Fastify 用的是 @fastify/compress

npm install @fastify/compress
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import compression from '@fastify/compress';

const app = await NestFactory.create<NestFastifyApplication>(
  AppModule,
  new FastifyAdapter(),
);
await app.register(compression);
Note

Fastify 的压缩插件默认会用 Brotli 算法(Node >= 11.7),压缩率比 gzip 高,但速度更慢。如果你更在意响应速度,可以指定只用 gzip:

await app.register(compression, { encodings: ['gzip', 'deflate'] });

什么时候不该用应用层压缩

如果你的应用前面有 Nginx 反向代理,压缩应该交给 Nginx 做,不要在应用层做。Nginx 是 C 写的,压缩效率比 Node.js 高很多。

应用层压缩适合这些场景:

  • 没有反向代理,直接暴露 Node.js 服务
  • 开发调试阶段
  • 某些特殊路由需要定制化压缩策略
Tip

生产环境最佳实践:Nginx 负责压缩,Node.js 应用不装 compression 中间件。这样应用进程可以把 CPU 留给业务逻辑。


API 版本控制

接口上线后,你不能随便改。前端可能还在用旧版接口,移动端 app 用户不会立刻更新。直接改接口等于砸别人的饭碗。

版本控制就是给接口加上版本号,新旧版本同时存在,给调用方足够的迁移时间。

启用版本控制

main.ts 里开启:

import { VersioningType } from '@nestjs/common';

const app = await NestFactory.create(AppModule);
app.enableVersioning({
  type: VersioningType.URI,
});

VersioningType.URI 是最常用的方式——版本号直接出现在 URL 里:

GET /v1/cats
GET /v2/cats

四种版本控制方式

类型说明示例
URI版本号在 URL 路径里/v1/cats
Header自定义请求头指定版本Custom-Version: 1
Media TypeAccept 头里指定版本Accept: application/json;v=2
Custom你自己写提取函数任意逻辑

Header 版本控制:

app.enableVersioning({
  type: VersioningType.HEADER,
  header: 'X-Api-Version',
});

客户端请求时带上 X-Api-Version: 1 就行。

Media Type 版本控制:

app.enableVersioning({
  type: VersioningType.MEDIA_TYPE,
  key: 'v=',
});

客户端请求头:Accept: application/json;v=2

Custom 版本控制:

const extractor = (req: Request): string | string[] => {
  // 你想从哪取就从哪取
  return req.headers['x-api-version'] as string;
};

app.enableVersioning({
  type: VersioningType.CUSTOM,
  extractor,
});
Tip

URI 版本控制最直观,前端调试也方便。大部分公开 API(微信、支付宝、Stripe)都用这种方式。没特殊需求就选它。

在控制器上使用版本

启用了版本控制后,控制器需要声明自己属于哪个版本:

@Controller({
  version: '1',
})
export class CatsControllerV1 {
  @Get('cats')
  findAll(): string {
    return '这是 v1 的猫咪接口';
  }
}

请求 /v1/cats 会命中这个控制器。请求 /v2/cats 会返回 404,因为没有 v2 的控制器。

在路由上使用版本

如果同一个控制器里不同路由版本不同,可以在方法级别声明:

import { Controller, Get, Version } from '@nestjs/common';

@Controller()
export class CatsController {
  @Version('1')
  @Get('cats')
  findAllV1(): string {
    return 'v1 版本';
  }

  @Version('2')
  @Get('cats')
  findAllV2(): string {
    return 'v2 版本,返回了更多数据';
  }
}

路由级别的版本会覆盖控制器级别的。

一个控制器支持多个版本

如果 v1 和 v2 的逻辑完全一样,不用写两份:

@Controller({
  version: ['1', '2'],
})
export class CatsController {
  @Get('cats')
  findAll(): string {
    return 'v1 和 v2 共用这个逻辑';
  }
}

版本中立

有些接口不需要版本控制——不管客户端请求哪个版本,都返回同样的内容。用 VERSION_NEUTRAL

import { Controller, Get, VERSION_NEUTRAL } from '@nestjs/common';

@Controller({
  version: VERSION_NEUTRAL,
})
export class HealthController {
  @Get('health')
  check(): string {
    return 'ok';
  }
}
Note

URI 版本控制下,VERSION_NEUTRAL 的接口 URL 里不会出现版本号。比如 /health 而不是 /v1/health

全局默认版本

不想每个控制器都写版本号?设一个全局默认版本:

app.enableVersioning({
  type: VersioningType.URI,
  defaultVersion: '1',
});

这样没声明版本的控制器自动归到 v1。

中间件也支持版本

中间件可以指定只对某个版本生效:

@Module({})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes({
        path: 'cats',
        method: RequestMethod.GET,
        version: '2',
      });
  }
}

这个 LoggerMiddleware 只在请求 v2 的 /cats 时才会执行。

小结

压缩:

  • Express 用 compression 中间件,Fastify 用 @fastify/compress
  • 有 Nginx 反代的话,压缩交给 Nginx 做
  • Fastify 默认 Brotli,可以指定只用 gzip 提速

版本控制:

  • app.enableVersioning() 开启,默认 URI 方式
  • 控制器用 version: '1',路由用 @Version('1')
  • VERSION_NEUTRAL 让接口忽略版本
  • defaultVersion 设全局默认版本,省得每个控制器都写