React Router+Express服务端重定向实现(SEO优化需求)
嘿,这个需求太常见了——尤其是要保护已收录页面的SEO权重,绝对不能让它们跳404。我来给你拆解一套React Router + Express的服务端重定向方案,分两种场景(SPA和SSR)来解释:
第一步:先在Express层搞定核心重定向逻辑
不管你的React应用是静态SPA还是服务端渲染,服务端的重定向优先级最高——因为爬虫访问时先打给Express,直接在这里返回301/302状态码,对SEO最友好(前端JS跳转爬虫可能不认)。
1. 定义重定向规则表
先把所有需要重定向的旧URL和目标URL整理成一个规则数组,支持精确匹配和正则匹配:
// 可以单独放在一个文件里,比如 redirect-rules.js,方便维护 const redirectRules = [ // 精确匹配旧页面 { from: '/old-product-page', to: '/products/new-item', status: 301 }, { from: '/about-us/team', to: '/company/team', status: 301 }, // 正则匹配整个目录的迁移(比如旧博客路径转新文章路径) { from: /^\/blog\/(\d{4})\/(.*)$/, to: '/articles/$1/$2', status: 301 }, // 临时重定向用302(比如页面正在维护) { from: '/under-maintenance', to: '/home', status: 302 } ]; module.exports = redirectRules;
2. 编写Express中间件处理重定向
在你的Express主文件里(比如server.js),把这个重定向中间件放在最前面,确保它先于静态资源或SSR逻辑执行:
const express = require('express'); const redirectRules = require('./redirect-rules'); const app = express(); // 重定向中间件 app.use((req, res, next) => { const matchedRule = redirectRules.find(rule => { if (typeof rule.from === 'string') { // 精确匹配路径 return req.path === rule.from; } else if (rule.from instanceof RegExp) { // 正则匹配路径 return rule.from.test(req.path); } return false; }); if (matchedRule) { // 处理正则替换的目标URL const targetUrl = typeof matchedRule.from === 'string' ? matchedRule.to : req.path.replace(matchedRule.from, matchedRule.to); // 返回重定向响应 return res.redirect(matchedRule.status, targetUrl); } // 没有匹配的规则,继续执行后续中间件 next(); });
第二步:结合React应用场景补充处理
场景A:静态SPA(比如create-react-app构建的项目)
如果你的React应用是静态打包的,接下来只需要处理静态资源和SPA的 fallback 逻辑:
const path = require('path'); // 托管React打包后的静态资源 app.use(express.static(path.join(__dirname, 'build'))); // 所有未匹配的请求返回React入口文件(让React Router处理前端路由) app.get('*', (req, res) => { res.sendFile(path.join(__dirname, 'build', 'index.html')); }); app.listen(3000, () => console.log('Server running on port 3000'));
场景B:服务端渲染(SSR)的React应用
如果你的项目是SSR架构,在处理完Express的重定向后,还要确保React Router在服务端渲染时不会重复处理旧URL(当然我们已经在Express层拦截了,但可以再加一层保险):
假设你用react-router-dom/server的matchRoutes来做服务端路由匹配:
import { matchRoutes, renderToString } from 'react-router-dom/server'; import { StaticRouter } from 'react-router-dom/server'; import App from './src/App'; import routes from './src/routes'; // 你的React路由配置数组 app.get('*', (req, res) => { // 先检查是否有React路由层面的重定向(比如组件内部的重定向逻辑) const matchedRoutes = matchRoutes(routes, req.path); let redirectUrl = null; matchedRoutes.forEach(({ route }) => { // 比如你在路由配置里加了redirectTo字段 if (route.redirectTo) { redirectUrl = route.redirectTo; } }); if (redirectUrl) { return res.redirect(301, redirectUrl); } // 继续SSR渲染流程... const html = renderToString( <StaticRouter location={req.path}> <App /> </StaticRouter> ); res.send(` <!DOCTYPE html> <html> <head>...</head> <body>${html}</body> </html> `); });
关键注意事项
- 优先用301重定向:永久重定向会告诉Google更新收录的URL到新地址,最大限度保留SEO权重;临时重定向(302)只用于页面暂时迁移的场景。
- 测试重定向状态码:用
curl -I https://your-domain/old-page或者Postman检查响应头,确保返回的是301 Moved Permanently,而不是200(前端JS跳转的话会返回200,对SEO不友好)。 - 批量维护规则:如果重定向规则很多,可以把它们放在JSON文件里,然后在Express里读取并转换正则(注意JSON里不能直接存正则对象,需要把正则字符串转成RegExp实例)。
内容的提问来源于stack exchange,提问作者MoPkoBot
相关产品推荐
相关产品推荐

