问题
先上 react App 代码
class App extends React.Component {
render() {
return (
<BrowserRouter>
<div>
<Link to=”/lottery”>to lottery</Link>
<Route path=”/lottery” component={Lottery} exact />
<Route path=”/a” render={() => <div>in a</div>} exact />
</div>
</BrowserRouter>
)
}
}
点击后可以正常跳转至 lottery 路由,忽略丑陋的界面 …
这时刷新就 404 找不到页面了
原因
react 的 BrowserRouter 用的是 Html5 提供的 HistoryApi 方法,Link 组件实际上是调用了 History.pushState(),然后通过监听 history 状态去展示或者隐藏组件。所以当刷新时,也就是向服务器发送了这个路径的请求,而服务器上实际是没有对这个路径的请求做任何处理的,故返回的是 404。
解决方法 — 用的是 koa 搭建服务器
app.use(views(path.resolve(__dirname, ‘../www/dist’), {extension: ‘html’}))
app.use(async (ctx, next) => {
console.log(ctx.path)
await next()
})
app.use(router.routes())
router.all(/\.js/i, static(path.resolve(__dirname, ‘../www/dist’)))
router.all(‘*’, async ctx => {
await ctx.render(‘index’)
})
这里需要注意的是 koa-views 提供的 render 方法是异步的,所以要用 await,否则也是返回 404,相当于对路由没有进行任何处理。
只要不是以.js 结束的路由请求都返回 index.html,js 类型的就从项目打包出来的静态资源里找,相当于把路由的控制权交给了前端。前端 react App 只需要对匹配不到的路由做下处理就 ok 了。
<BrowserRouter>
<div>
<Switch>
<Route path=”/lottery” component={Lottery} exact />
<Route path=”/a” render={() => <div>in a</div>} exact />
<Route render={() => <div>404 页面 </div>}></Route>
</Switch>
</div>
</BrowserRouter>