你现在的处境很典型:
- 用
encodeURIComponent→ Vercel ISR(Next.js)报 500 - 用
base64→ 浏览器/路由不识别,路径错乱
原因:Vercel/Next.js 的 ISR 对 % 编码路径有解析 bug/限制,尤其在 getStaticPaths 和动态路由里很容易炸。下面给你一套在 Vercel ISR 下稳定可用、中文安全、能正常解码的方案,直接替换就能解决。
✅ 最佳方案:用「安全 Base64」(URL-safe Base64)
把中文转成 URL 安全的 Base64,不是普通 Base64,也不是 encodeURIComponent。
1. 编码(客户端 / 生成路径时)
js// 中文 → URL-safe Base64function encodeSafe(str) {return Buffer.from(str, 'utf8').toString('base64').replace(/\+/g, '-') // + → -.replace(/\//g, '_') // / → _.replace(/=/g, ''); // 去掉末尾 =}// 广州 → 5bm_5bee5biCconsole.log(encodeSafe('广州'));
2. 解码(Next.js 页面 / getStaticProps 里)
js// URL-safe Base64 → 中文function decodeSafe(encoded) {let str = encoded.replace(/-/g, '+').replace(/_/g, '/');// 补回末尾 =while (str.length % 4) str += '=';return Buffer.from(str, 'base64').toString('utf8');}// 5bm_5bee5biC → 广州console.log(decodeSafe('5bm_5bee5biC'));
3. 为什么这个能解决 Vercel ISR 500
- 没有
%→ 不会触发 Vercel/Next.js 的编码解析 bug - 只有
a-z0-9-_→ 完全合法 URL 字符,ISR 静态路径生成稳定 - 可逆、无乱码、无长度爆炸
- 对比:
encodeURIComponent('广州')→%E5%B9%BF%E5%B7%9E(ISR 易炸)- 普通 Base64 →
5bm/5bee5biC(含/,路由被当成文件夹) - URL-safe Base64 →
5bm_5bee5biC(完美)
✅ Next.js ISR 完整示例(App Router / Pages Router 都可用)
生成路径(比如 getStaticPaths)
js// 假设 locations = [{ name: '广州' }, ...]const paths = locations.map(loc => ({params: { city: encodeSafe(loc.name) }}));
页面里解码
js// app/[city]/page.jsexport default function Page({ params }) {const cityName = decodeSafe(params.city);return <div>{cityName}</div>;}
✅ 备选方案(不想用 Base64 时)
如果不想用 Base64,可以用 encodeURI + 替换,但稳定性不如上面:
js// 编码const safe = encodeURI('广州').replace(/%/g, '_');// _E5_B9_BF_E5_B7_9E// 解码const orig = decodeURI(safe.replace(/_/g, '%'));
✅ 总结(直接照做)
- 扔掉
encodeURIComponent(ISR 易 500) - 扔掉普通
base64(含/,路由错误) - 用 URL-safe Base64:
+→-、/→_、去掉= - 解码时还原即可
要不要我帮你把现有代码(生成链接 + 页面解码)直接改成这套安全方案,你复制就能用?
