33 lines
1.3 KiB
TypeScript
33 lines
1.3 KiB
TypeScript
import type { NextRequest } from "next/server";
|
||
import createNextIntl from "next-intl/middleware";
|
||
import { routing } from "./i18n/routing";
|
||
|
||
/**
|
||
* 语言路由中间件。
|
||
*
|
||
* Next.js 16 起 `middleware.ts` 约定更名为 `proxy.ts`
|
||
* (nextjs.org/docs/messages/middleware-to-proxy)。
|
||
*
|
||
* ## 为什么不在这里拦截不存在的文章
|
||
*
|
||
* 一开始的思路是在中间件里提前查库、对草稿和不存在的 slug 直接返回 404。
|
||
* 最终**放弃了这个方案**,原因:
|
||
* 1. 中间件在每个匹配请求上都会执行,等于给所有页面加了一次额外开销;
|
||
* 2. 中间件运行在受限运行时,引入数据库驱动会显著增大中间件包体积;
|
||
* 3. 即便返回 404,也需要与页面渲染逻辑保持一致,容易产生两套判定标准。
|
||
*
|
||
* 实际采用的做法见 `app/[locale]/posts/[slug]/page.tsx`:
|
||
* 在**渲染之前**用 `notFound()` 终止,并配合 `dynamic = "force-dynamic"`
|
||
* 避免流式响应已经提交状态码。具体说明见该文件注释。
|
||
*/
|
||
const handleI18nRouting = createNextIntl(routing);
|
||
|
||
export default function proxy(request: NextRequest) {
|
||
return handleI18nRouting(request);
|
||
}
|
||
|
||
export const config = {
|
||
// 跳过 API、Next 内部资源与静态文件(含点号的路径)
|
||
matcher: ["/((?!api|_next|_vercel|.*\\..*).*)"],
|
||
};
|