前置知识

什么是中间件?入门指南

从零理解中间件、为什么对 SaaS 有用,以及我们在 Next.js 中的中间件如何处理 i18n 和请求 ID,并介绍如何自定义。

基础概念(面向初学者)

中间件运行在“请求 → 最终处理器”之间。它像一个检查点:读取请求头、决定重定向、设置响应头,然后再进入页面或 API 处理逻辑。

常见用途:

  • 认证拦截(未登录重定向)
  • 多语言 i18n(保持 /:locale/... 或自动检测)
  • 日志与追踪(添加 x-request-id
  • 特性开关/实验
  • 安全和限流

在 Next.js 中,middleware.ts 在 Edge 侧非常早地执行。


为什么有用

把“跨领域”的逻辑集中管理,避免在各路由重复:

  • 统一的全局规则入口
  • 一致的可观测性(统一的 request_id
  • 早决策、少开销(更少后端工作)
  • 处理器更专注于业务逻辑

SaaS 典型需求:多语言、日志关联、后台区、实验、请求头规范化等。


我们的中间件在做什么

组合 next-intl 的 i18n 路由与轻量的请求 ID 传播。

要点:

  • 语言路由:src/i18n/routing.ts
  • x-request-id:复用已有或生成 UUID
  • 保守的匹配器:排除 api_next、静态资源、admin
// src/middleware.ts(节选)
import createMiddleware from 'next-intl/middleware';
import { NextRequest } from 'next/server';
import { routing } from '@/i18n/routing';

const intlMiddleware = createMiddleware(routing);

export default function middleware(request: NextRequest) {
  const existing = request.headers.get('x-request-id');
  const requestId = existing || crypto.randomUUID();
  const res = intlMiddleware(request);
  res.headers.set('x-request-id', requestId);
  return res;
}

如何安全地自定义

添加响应头:

export default function middleware(request: NextRequest) {
  const res = intlMiddleware(request);
  res.headers.set('x-feature-flag', 'on');
  return res;
}

重定向:

import { NextResponse } from 'next/server';
export default function middleware(request: NextRequest) {
  if (request.nextUrl.pathname === '/old') {
    return NextResponse.redirect(new URL('/new', request.url));
  }
  return intlMiddleware(request);
}

调整 matcher,并在线上日志中使用 x-request-id。避免在中间件里修改认证 Cookie。


什么时候不要用中间件

  • 仅针对某单一路由的逻辑
  • 重型异步任务(如数据库访问)
  • 读取/转换请求体

TL;DR

  • 适合 i18n、响应头、重定向、轻量级守卫
  • 默认实现:i18n + x-request-id
  • 通过响应头、重定向和 matcher 来扩展;不要改动认证 Cookie