如何使反应路由器与静态资产、html5 模式、历史 API 和嵌套路由一起工作?

Posted

技术标签:

【中文标题】如何使反应路由器与静态资产、html5 模式、历史 API 和嵌套路由一起工作?【英文标题】:How to make react router work with static assets, html5 mode, history API and nested routes? 【发布时间】:2016-08-23 17:21:00 【问题描述】:

我以为我开始了解 React Router,但是在添加一个为其组件加载 css 的库时,我遇到了新问题。从我家导航到包含该组件的页面时一切正常,但是当我刷新它时,字体的 url 被破坏了......

我找到了一些指针 here 和 here 但到目前为止还没有运气。这是一个常见问题吗?如何解决它?

我使用 webpack 开发服务器,默认配置由 yeoman scaffolder 构建。

我使用的库是React Fa来显示图标。

当我在http://localhost:8000/ 上加载我的应用程序时,一切正常,然后我导航到http://localhost:8000/customer/ABCD1234/chat,我的图标就正常了。字体已正确加载。

然后我刷新页面,我在控制台看到:

DOMLazyTree.js?019b:56 GET http://localhost:8000/customer/ABCD1234/assets/926c93d201fe51c8f351e858468980c3.woff2

这显然是坏的,因为客户部分不应该在这里......

到目前为止,这是我的路由器:

ReactDOM.render(
  <Router history=browserHistory>
    <Route path='/' component=App>
      <IndexRoute component=Index/>
      <Route path='customer/:id'        component=Customer    />
      <Route path='customer/:id/chat'   component=CustomerChat/>
      <Route path="*"                   component= NotFound   />
    </Route>
  </Router>
, document.getElementById('support-app'));

我还尝试在我的 index.html 中添加 &lt;base href="/"/&gt;,但我在控制台中收到了一个很好的红色警告,所以这可能不是最好的主意:

警告:使用 is 自动设置 basename 已弃用并将在下一个主要版本中删除。这 的语义与 basename 略有不同。请 在 createHistory 的选项中显式传递基本名称

【问题讨论】:

【参考方案1】:

听起来您已经在 CSS 中定义了资产和图标的相对路径。

background-image: url('assets/image/myicon.png')

尝试使用绝对路径:

background-image: url('/assets/image/myicon.png')

由于 React 应用程序是单页面应用程序,并且您在 / 上输入您的应用程序,因此无论您导航到哪个页面,所有 url 都可以正常工作,因为它们与您开始的根目录相关。

但是,一旦您在不同的路径(例如 /customer/ABCD)上重新加载页面,您的所有资产都将与该路径相关,因此您在控制台中看到的 URL 是错误的。

另外,如果使用 webpack,您可以尝试在配置文件中设置 publicPath,如下所示:

...
output: 
    path: 'assets',
    publicPath: '/'
,
...

【讨论】:

理论上,我认为这可行,但有问题的资产是一种字体,正如我提到的那样,由 font awesome 加载。而且我不能改变路径,除非我自己从 SCSS 构建了很棒的字体,但是我失去了 CDN 的优势......这是 CSS:maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/… 您将如何处理多种不同来源的静态资产。因为我认为我的问题可能来自类似的东西。由于 fontawsome 加载了相对路径,但我的图片来自绝对资产路径,就像你提到的那样...... 您在项目中使用的是纯 CSS 还是 SASS?如果是后者,我宁愿在我的项目中包含 font-awesome 并重新定义基本路径,而不是必须管理多个资产路径:fontawesome.io/get-started【参考方案2】:

我也有同样的问题。

    使用默认 browserHistory 将 &lt;base href="http://whatever"&gt; 标签添加到包含 react-router 的 HTML 的页面的头部

    加载页面 - history.js 将输出 2 个错误,警告:使用 &lt;base href&gt; 自动设置基本名称已被弃用,并将在下一个主要版本中删除。的语义与 basename 略有不同。请在创建历史的选项中明确传递基本名称

    将 react-router 历史记录更改为使用历史记录为 const history = useRouterHistory(createHistory)( basename: 'http://whatever' ) 的历史记录,这应该可以解决问题(因为 basename 现在已显式传递)

    重新加载页面

https://github.com/reactjs/react-router/issues/3387

5/9 更新

就我而言。

index.html

<head>
  <base href="/" />
  <script src="app.js"></script>
</head>
<body>
  <div id="app">
  </div>
</body>

app.js

import  Router , useRouterHistory  from 'react-router'
import  createHistory  from 'history'

const browserHistory = useRouterHistory(createHistory)( basename: '/' )

render(
  <Router routes=routes history=browserHistory/>,
  document.getElementById("app")
);

然后重新加载警告就消失了。 希望这是有用的。

【讨论】:

正如我在问题中提到的,我已经尝试过了,我确实找到了这个 github 问题。为了确定起见,我通过复制粘贴您的代码再次尝试,即使我做了您解释的第 3 步,我也会收到警告...【参考方案3】:

感谢 react-script:2+,我解决了这个问题

您只需要创建一个名为 setupProxy.js 的 js 文件,它将由开发服务器加载。现在您可以完全控制您的代理:

const proxy = require('http-proxy-middleware');

module.exports = function(app) 
    console.log("configuring development proxies to point to localhost:4000")
    app.use(proxy('/api',  target: 'http://localhost:4000/' ));
    app.use(proxy('/graphql',  target: 'http://localhost:4000/' ));
;

https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#configuring-the-proxy-manually

编辑: 旧链接坏了,这是更新的: https://create-react-app.dev/docs/proxying-api-requests-in-development/#configuring-the-proxy-manually

【讨论】:

链接失效了。 没错:create-react-app.dev/docs/proxying-api-requests-in-development/… 嗨@BBaysinger,对不起,我没有注意到你的评论。感谢 skini827 更新链接【参考方案4】:

我通过在应用索引页面上加载 font awesome cdn 解决了这个问题。然后它在所有情况下的所有路线上都可用。

【讨论】:

以上是关于如何使反应路由器与静态资产、html5 模式、历史 API 和嵌套路由一起工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何创建一个在反应时切换打开模式的按钮

如何对过滤器方法的结果进行条件渲染?反应

后退按钮后反应路由器“历史”和“位置”不匹配

反应构建资产表达静态文件夹不服务错误es6

用 Nginx 反应路由器 html5 pushstae

反应路由器:类型中缺少“历史”