如何使用Hapi部署带React-Router的React-JS应用?重定向疑问
解决React Router + Hapi部署的SPA路由问题
没错,你确实需要配置Hapi将所有客户端路由(比如/user/:id)转发到build/index.html —— 这是因为你用Create React App打包后的项目是单页应用(SPA),所有路由逻辑都是在浏览器端由React Router处理的,服务器本身并不知道这些自定义路由。
为什么要这么做?
当你直接在浏览器访问/user/123时,Hapi服务器会默认去寻找对应的物理文件(比如build/user/123.html),但显然这个文件不存在,就会返回404错误。而把这些请求转发到index.html后,React Router就能接管请求,在客户端解析路由并渲染对应的组件,同时保留组件状态。
具体实现步骤
首先确保你已经安装了@hapi/inert插件(用来处理静态文件),然后按以下方式配置Hapi:
- 注册inert插件
const Hapi = require('@hapi/hapi'); const Inert = require('@hapi/inert'); const path = require('path'); const init = async () => { const server = Hapi.server({ port: process.env.PORT || 3000, host: '0.0.0.0' // 允许EC2外部访问 }); // 注册inert插件 await server.register(Inert);
- 配置静态资源路由
先让Hapi正确处理build/目录下的静态文件(比如CSS、JS、图片等):
// 服务build目录下的静态资源 server.route({ method: 'GET', path: '/{param*}', handler: { directory: { path: path.join(__dirname, 'build'), redirectToSlash: true, index: true } } });
- 添加Catch-All路由处理客户端路由
注意:这个路由要放在静态资源路由之后!它会捕获所有未被静态资源或API路由匹配的请求,返回index.html:
// 捕获所有客户端路由,返回index.html server.route({ method: 'GET', path: '/{any*}', handler: (request, h) => { return h.file(path.join(__dirname, 'build', 'index.html')); } }); await server.start(); console.log('Server running on %s', server.info.uri); }; process.on('unhandledRejection', (err) => { console.log(err); process.exit(1); }); init();
重要提醒
如果你有后端API路由(比如/api/users),一定要把这些API路由放在Catch-All路由之前,这样Hapi会优先处理API请求,不会把API请求也转发到index.html。
这样配置后,无论是访问/home还是/user/123,服务器都会返回index.html,React Router就能正常解析路由并渲染对应的组件,同时不会丢失组件状态啦。
内容的提问来源于stack exchange,提问作者Mars
相关产品推荐
相关产品推荐

