今天就要准备测试发布新官网项目了,和产品校对后主要发现这个 next-international
多语言库预设的 Middleware 有问题,导致 301 跳转多次。以及因为这个问题,我也没法做好产品另外的一个需求。
需求 1:访问
/
跳转到/home
,如果携带多语言则依旧(例如/ja
跳转到/ja/home
)- 无默认首页,只能用
NextResponse.redirect
- 无默认首页,只能用
需求 2:如果系统语言为英语,访问
/
跳转到/home
而不是/en/home
- 需要
NextResponse.rewrite
改写/
变成/en
的效果,但前提是系统语言是英语
- 需要
起初我的实现方案是直接使用该库提供的 urlMappingStrategy
属性,将它设置成 rewriteDefault
可以帮我完成第二个需求,但结果就是发现第一个需求除了我自己跳转了一次,还额外多次跳转了,而且跳转的地址也是极其诡异:
// 启用了 rewriteDefault
/ (307) -> /home (307) -> /ja/home (307) -> /home (307) -> /ja/home (200)
// 未启用
/ (307) -> /home (307) -> /ja/home (200)
通过分析它的 Middleware 源码 可以发现,它其实是获取地址栏语言(假如请求路径是 /ja
)之后将路径 307 到 /
,再根据 Cookies 从 /
307 跳转到 /ja
从而完成跳转流程的。由于爬虫不一定会有 Cookies 的概念,于是它这种跳转逻辑,会导致第一次跳转完成后直接 Fallback 成默认语言(可能是英语),最终得到一个 /ja
出现英语页面内容的错误情况。
目前只能去掉这个改写规则暂时发布先,后续看起来只能我自己思考一下怎么自己写一个中间件完成跳转和 Rewrite 了,但我认为这或许是一个 Bug,给作者提一条 Issues 说不定也是可以的?并且我认为我手写的 /
跳转到 /home
而不是检测语言后直接跳转 /ja/home
也不太合理,但这种业务需求肯定不能求着作者帮忙改了...
昨天给 NextJS 提交的那条 Issues 我发现了问题,其实是我阅读有误(当然它文档或许存在一定的易混淆性),next.config.js
它只有 redirects
优先级最高,中间件的 rewrites
就是比 next.config.js
的高,也就是说正确方案或许是直接在中间件里编写对应的 redirects
规则就能够做到反向代理的效果了。
export function middleware(request: NextRequest) {
if (request.nextUrl.pathname.startsWith("/paul")) {
const response = NextResponse.rewrite(`https://paul.ren/${request.nextUrl.pathname.replace("/paul", "")}`);
return response;
}
...
}
新官网上线后,产品还需要增加 Google 统计的代码,看了下 NextJS 官方文档 的做法,它对此做了一个封装,于是我顺藤摸瓜直接模仿它 源码 写了一份(其实又是一个产品的奇葩需求,要求某一个页面添加 2 份统计代码)