React history 路由模式webpack配置不生效

1,482 阅读3分钟

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。其实忽略了最重要的资源官网。官网上有每一个配置字段的说明。我们只要细心一点,关注下每个字段配置的功能,一定能避免很多问题。

image1.png

publicPath 说明

image2.png

如果我们配置了publicPath, devServer会从publicPath下加载静态资源,并且这个路径除了配置一个完整URL之外,需要确保 devServer.publicPath 总是以斜杠(/)开头和结尾。我们做如下的调整:

    publicPath: '/release/'

那此时我们的访问路径应该是 http://localhost:8081/release/。我们发现资源找到了!说明html模板加载没有问题了。不过,像http://localhost:8081/login这样的路径访问还是不行。因为我们的静态资源是在release路径下。所以http://localhost:8081/login这样的访问方式,肯定获取不到模板html,那路由渲染也肯定是不成功的。

解决方案

我们有两种解决方式:

  1. 走默认配置 删掉 publicPath 配置,默认为/。此时访问 http://localhost:8081/ 或者 http://localhost:8081/login 都能获取模板。然后路由跳转再由react-router来进行控制。
output: {
    path: path.resolve(__dirname, '../release'),
},
historyApiFallback: true,
  1. 重写访问路由
output: {
    path: path.resolve(__dirname, '../release'),
    publicPath: '/release/'
},
historyApiFallback: {
    rewrites: [
    {
        from: /.*/,
        to: '/release/'
    }
    ]
},

我们把 historyApiFallback:true 修改为一个对象,并且重写请求路径。任何请求过来的路径,默认都走/release/,这样就能够跟我们设置的publicPath一致,就能获取到html模板文件了。