在 Astro 中实现基于浏览器首选语言的自动重定向,主要有以下 4 种主流方案。根据部署架构(SSG 纯静态 vs SSR/Edge 边缘计算)的不同,它们的性能、SEO 影响及维护成本有显著差异。
| 维度 | 方案一:Astro SSR 中间件 (Middleware) | 方案二:边缘计算重定向 (Cloudflare Workers / Vercel Edge) | 方案三:客户端 JS 拦截 (Root index.astro) | 方案四:HTML <meta> 标签静态重定向 |
| 执行位置 | Node/Edge 运行时(SotA) | Edge 节点(CDN 网络最外层) | 浏览器端(Client Side) | 浏览器端(Client Side) |
| 适配模式 | SSR / Hybrid | SSG(纯静态构建) | SSG(纯静态构建) | SSG(纯静态构建) |
| 用户体验 | 极佳(无白屏/无闪烁) | 极佳(延迟极低,无白屏) | 一般(存在毫秒级白屏或闪烁) | 较差(响应极慢,存在延迟) |
| SEO 友好度 | 高(支持 302/307 语义与 Vary: Accept-Language) | 高(支持 302/307 语义) | 中(搜索引擎可能会忽略 JS 跳转) | 低(搜索引擎不推荐 meta refresh) |
| 部署成本 | 需启用 Astro SSR 适配器 | 需配置 CDN / Vercel 重定向规则 | 零配置(纯 HTML/JS 输出) | 零配置(纯 HTML/JS 输出) |
核心选型逻辑
- 如果你的站点采用 SSG 纯静态导出(部署在 Vercel / Netlify / Cloudflare Pages):
- 最佳实践:采用 方案二(边缘/平台重定向规则),既保住了纯静态 HTML 的部署成本和极速响应,又能实现 0 闪烁的服务端级重定向。
- 次优备选:采用 方案三(客户端 JS 降级),实现最简单,适合纯前端轻量处理。
- 如果你的 Astro 开启了 SSR 模式(Node.js / Cloudflare SSR):
- 最佳实践:首选 方案一(Astro 原生 Middleware)。
落地实现细节
落地方案一:Astro Middleware 方式(SSR 架构)
在 src/middleware.ts 中拦截根路径访问:
import { defineMiddleware } from "astro:middleware";
const DEFAULT_LANG = "en";
const SUPPORTED_LANGS = ["zh", "en"];
export const onRequest = defineMiddleware(async ({ request, redirect, url }, next) => {
// 仅针对根路径 "/" 进行重定向处理
if (url.pathname === "/" || url.pathname === "") {
const acceptLanguage = request.headers.get("accept-language") || "";
// 解析 Accept-Language Header(例如: "zh-CN,zh;q=0.9,en;q=0.8")
let targetLang = DEFAULT_LANG;
if (acceptLanguage.includes("zh")) {
targetLang = "zh";
} else if (acceptLanguage.includes("en")) {
targetLang = "en";
}
// 302/307 重定向至对应语言根路径
return redirect(`/${targetLang}/`, 307);
}
return next();
});
落地方案二:Vercel / Cloudflare Edge 托管层配置(SSG 纯静态架构)
如果你将 Astro 以纯静态方式部署在 Vercel,直接在项目根目录的 vercel.json 中配置原生重定向逻辑,完全不需要改动任何代码:
{
"redirects": [
{
"source": "/",
"has": [
{
"type": "header",
"key": "accept-language",
"value": "(?i).*zh.*"
}
],
"destination": "/zh/",
"permanent": false
},
{
"source": "/",
"destination": "/en/",
"permanent": false
}
]
}
落地方案三:客户端 JS 降级重定向(SSG 纯静态架构)
在 src/pages/index.astro 页面中注入内联 Script,在 DOM 渲染前立即完成跳转:
---
// src/pages/index.astro (作为重定向中转页)
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Redirecting...</title>
<script is:inline>
(function () {
// 优先读取用户之前手动选择过的语言 Cookie/LocalStorage,没有则读取浏览器首选语言
const savedLang = localStorage.getItem("preferred_lang");
const browserLang = navigator.language || navigator.userLanguage || "";
let targetLang = "en";
if (savedLang && ["zh", "en"].includes(savedLang)) {
targetLang = savedLang;
} else if (browserLang.toLowerCase().startsWith("zh")) {
targetLang = "zh";
}
window.location.replace("/" + targetLang + "/");
})();
</script>
</head>
<body class="bg-tihubb-900 text-white flex items-center justify-center min-h-screen font-mono text-xs">
<p>Redirecting to your preferred language...</p>
</body>
</html>