React history 路由模式webpack配置不生效
摘要:在做一个react学习项目的时候,一开始使用的是hash路由模式进行开发,后来想要切换成history路由模式。遂修改路由模式为BrowserRouter,当然如果配置不做任何修改,直接进行访问肯定是不成功的。因为hash路由模式进行前端资源访问的时候,路由改变只是hash在变化,不会向后端发送请求,而history路由模式则是整个浏览器地址栏地址都变化了,会向服务端发送请求。此时我们又没有进行类似代理的配置,请求肯定是不成功的。
修改路由模式
把 HashRouter 替换为 BrowserRouter
// 注释掉 HashRouter 路由引入方式。替换为 BrowserRouter
// import { HashRouter } from "react-router-dom";
import { BrowserRouter } from "react-router-dom";
// 使用react-router-config来进行路由的配置
import { renderRoutes } from "react-router-config";
// 自定义的路由配置
import routes from "./router";
ReactDOM.render(
<BrowserRouter basename="/">{renderRoutes(routes)}</BrowserRouter>,
document.getElementById("app")
);
修改webpack配置
秉着快速了解配置并解决问题的思路(拿来主义🐶),直接百度了下相关的配置,拿到相关的搜索结果进行配置文件的修改。 此处只提供涉及到修改的配置信息。 可在devServer中配置historyApiFallback配置项,具体修改如下:
// webpack.dev.js
module.exports = merge(common, {
mode: "development",
devtool: "cheap-module-eval-source-map",
output: {
path: path.resolve(__dirname, '../release'),
publicPath: path.resolve(__dirname, '../release')
},
devServer: {
historyApiFallback: true, // 添加这一行代码,当使用 HTML5 History API 时,任意的 404 响应都可能需要被替代为 index.html
stats: "errors-only",
compress: true,
port: 8081,
hot: true,
open: true,
proxy: {
"/api": {
target: "http://proxy.test.cn",
changeOrigin: true,
},
},
}
});
涉及的修改:
module.exports = merge(common, {
// 新增
output: {
path: path.resolve(__dirname, '../release'),
publicPath: path.resolve(__dirname, '../release')
},
devServer: {
// 新增
historyApiFallback: true, // 添加这一行代码,当使用 HTML5 History API 时,任意的 404 响应都可能需要被替代为 index.html
}
});
运行调试
由于没有先去官网查看相关的配置(官网链接)。所以修改完就运行验证下配置是否正确。心想应该能成功的。可是当运行起来后发现,当访问 http://localhost:8081/ 或者其他路由 http://localhost:8081/login 的时候得到如下的结果。
不成功,得到的结果总是 Cannot GET /
。习惯性的思维是继续去进行搜索,不管是百度还是stackoverflow。其实忽略了最重要的资源官网。官网上有每一个配置字段的说明。我们只要细心一点,关注下每个字段配置的功能,一定能避免很多问题。
如果我们配置了publicPath, devServer会从publicPath下加载静态资源,并且这个路径除了配置一个完整URL之外,需要确保 devServer.publicPath
总是以斜杠(/)开头和结尾。我们做如下的调整:
publicPath: '/release/'
那此时我们的访问路径应该是 http://localhost:8081/release/
。我们发现资源找到了!说明html模板加载没有问题了。不过,像http://localhost:8081/login
这样的路径访问还是不行。因为我们的静态资源是在release路径下。所以http://localhost:8081/login
这样的访问方式,肯定获取不到模板html,那路由渲染也肯定是不成功的。
解决方案
我们有两种解决方式:
- 走默认配置
删掉 publicPath 配置,默认为
/
。此时访问http://localhost:8081/
或者http://localhost:8081/login
都能获取模板。然后路由跳转再由react-router来进行控制。
output: {
path: path.resolve(__dirname, '../release'),
},
historyApiFallback: true,
- 重写访问路由
output: {
path: path.resolve(__dirname, '../release'),
publicPath: '/release/'
},
historyApiFallback: {
rewrites: [
{
from: /.*/,
to: '/release/'
}
]
},
我们把 historyApiFallback:true
修改为一个对象,并且重写请求路径。任何请求过来的路径,默认都走/release/
,这样就能够跟我们设置的publicPath一致,就能获取到html模板文件了。