You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js 14中如何组合Supabase与next-intl中间件?

在Next.js中整合Supabase与next-intl中间件的问题

我在NextJS应用里集成Supabase(参考文档第4点)和next-intl时碰到了麻烦——这两个库的中间件都会直接返回NextResponse,我尝试同时使用它们,但始终没法合并返回同一个NextResponse。

我试过用stackMiddlewares自定义中间件,但这两个中间件都不返回NextResponse,只返回NextMiddleware。

我已经写了两个中间件:

export const withI18n: MiddlewareFactory = (next) => {
  return async (request: NextRequest, _next: NextFetchEvent) => {
    
    // 该如何处理这个?
    const response = createMiddleware({
      defaultLocale: 'en',
      locales: SUPPORTED_LOCALES,
      pathnames,
      localePrefix,
    });

    return next(request, _next);
  };
};

以及参考Supabase客户端文档实现的updateSession方法对应的中间件:

export const withSupabaseSessionUpdate: MiddlewareFactory = (next) => {
  return async (request: NextRequest, _next: NextFetchEvent) => {

    // 该如何处理这个?
    const response = await updateSession(request);

    return next(request, _next);
  };
};

解决方案

核心思路是让两个中间件链式处理请求和响应——先让一个中间件生成响应,再把这个响应传给下一个中间件处理,最终返回经过两次处理的响应。

步骤1:修正中间件写法,支持响应传递

修正withI18n中间件

createMiddleware返回的是Middleware函数,需要用它处理当前请求拿到响应,再传给后续中间件:

export const withI18n: MiddlewareFactory = (next) => {
  return async (request: NextRequest, event: NextFetchEvent) => {
    // 调用next-intl中间件处理请求,得到初始响应
    const i18nMiddleware = createMiddleware({
      defaultLocale: 'en',
      locales: SUPPORTED_LOCALES,
      pathnames,
      localePrefix,
    });
    
    const response = await i18nMiddleware(request, event);
    // 将响应传给下一个中间件
    return next(request, event, response);
  };
};

修正withSupabaseSessionUpdate中间件

updateSession需要接收请求和已有响应,更新后再传递或返回:

export const withSupabaseSessionUpdate: MiddlewareFactory = (next) => {
  return async (request: NextRequest, event: NextFetchEvent, prevResponse?: NextResponse) => {
    // 若无前置响应,创建默认响应
    const baseResponse = prevResponse || NextResponse.next();
    // 基于现有响应更新Supabase会话
    const updatedResponse = await updateSession(request, baseResponse);
    
    // 有后续中间件则传递响应,否则直接返回
    return next ? next(request, event, updatedResponse) : updatedResponse;
  };
};

步骤2:扩展MiddlewareFactory类型

让类型支持传递前置响应:

type MiddlewareFactory = (
  next: (request: NextRequest, event: NextFetchEvent, response?: NextResponse) => Promise<NextResponse>
) => (request: NextRequest, event: NextFetchEvent, response?: NextResponse) => Promise<NextResponse>;

步骤3:实现中间件堆叠函数

用reduceRight实现中间件链式调用:

export const stackMiddlewares = (middlewares: MiddlewareFactory[]) => {
  return middlewares.reduceRight(
    (next, middleware) => middleware(next),
    async (req, evt, res) => res || NextResponse.next()
  );
};

步骤4:整合中间件

在middleware.ts中挂载堆叠后的中间件:

export default stackMiddlewares([withSupabaseSessionUpdate, withI18n]);

// 配置中间件匹配路径(按需调整)
export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};

关键注意点

  • 执行顺序:若需先处理国际化路由再更新会话,调整数组顺序为[withI18n, withSupabaseSessionUpdate]即可
  • 每个中间件必须接收前置响应并返回处理后的新响应,确保两个库的逻辑作用于同一个NextResponse

内容的提问来源于stack exchange,提问作者Rafał Prokopiak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 17:32:43