React应用部署后路由失效求助:点击按钮出现Cannot GET /services
React应用部署后路由无法访问的问题排查与解决
问题描述
本地开发时,通过window.location.href跳转到http://localhost:3000/services正常;部署到服务器后,主页http://www.assertivesolutions.ca可正常加载,但点击按钮跳转/services时出现Cannot GET /services错误,直接在地址栏输入该路径也会触发同样问题。
核心原因
- 客户端路由与服务器静态服务的冲突:使用
BrowserRouter时,React路由是纯客户端路由,仅通过浏览器JS解析URL渲染对应组件。当直接访问/services或通过window.location.href跳转时,浏览器会向服务器发起新请求,而当前Express仅配置了静态文件服务,找不到/services对应的物理文件,因此返回404。 - 错误的跳转方式:
window.location.href会触发浏览器页面刷新和服务器请求,没有利用React Router的客户端路由能力。
解决方案
前端调整:改用React Router客户端跳转方式
替换原有的window.location.href跳转,使用React Router提供的方式实现客户端路由切换,避免触发服务器请求:
方式1:使用<Link>组件
// 在对应组件中导入Link import { Link } from 'react-router-dom'; // 替换原button为Link组件 <Link to="/services" className="welcome-buttons"> Read More <i className="fas fa-arrow-alt-circle-right"></i> </Link>
方式2:使用history.push(适用于类组件)
// 在组件中导入withRouter import { withRouter } from 'react-router-dom'; class Welcome extends Component { handleNavigate = () => { this.props.history.push('/services'); }; render() { return ( <button className="welcome-buttons" onClick={this.handleNavigate}> Read More <i className="fas fa-arrow-alt-circle-right"></i> </button> ); } } // 用withRouter包裹组件以获取history对象 export default withRouter(Welcome);
后端调整:配置Express路由 fallback
即使前端用了客户端跳转,用户直接在地址栏输入路由或刷新页面时,仍会向服务器发起请求。需要让Express将所有非静态文件的请求都返回React应用的index.html,交由React Router处理:
修改服务器中assertSolApp的配置:
const assertSolApp = express(); const staticPath = path.join(__dirname, 'assertivesolutions.ca'); // 优先处理静态资源(如js、css、图片等) assertSolApp.use(express.static(staticPath)); // 所有其他请求返回index.html,让React Router接管路由 assertSolApp.get('*', (req, res) => { res.sendFile(path.join(staticPath, 'index.html')); }); assertSolApp.listen(8001);
验证步骤
- 重新构建React应用并上传到服务器
- 重启后端服务器
- 测试:点击按钮跳转
/services、直接在地址栏输入/services、刷新该页面,确认均可正常访问对应组件
内容的提问来源于stack exchange,提问作者gib65
相关产品推荐
相关产品推荐

