首先,让我们确保我们谈论的是同一件事:
function App() {
return (
<BrowserRouter>
<Redirect from="/old-route" to="/new-route" />
{/* ... more routes etc... */}
</BrowserRouter>
)
}
(或者你在自己的框架中如何完成同样的事情)。
我不是在谈论这种用法(从文档中借用的例子):
<Route exact path="/">
{loggedIn ? <Redirect to="/dashboard" /> : <PublicHomePage />}
</Route>
这在技术上是没有问题的,尽管在你的应用程序中可能有更好的方法来处理这个问题。请阅读我的文章《React应用程序中的认证》以了解更多相关信息。
好了,现在我们已经清楚了,让我解释一下为什么,然后你应该做什么来代替。
首先,使用客户端重定向(如Redirect的fromprop或类似的)的目的是确保用户不会登陆到一个你期望他们能登陆的URL,而是将他们重定向到一个不同的URL。这方面的一个很好的例子是,当你改变你的应用程序的URL方案。或者是你给你的用户发送了一封带有错误URL的电子邮件,现在你被困在了用户的重定向上,直到永远。
不管是什么情况...如果你知道你想重定向用户的URL,那么你最好在服务器上重定向他们。让我们来谈谈为什么客户端的重定向会有这样的问题。
149.3 千字节的重定向 😱
假设一个用户来到你的应用程序,并点击了/old-route 。在浏览器知道它在一条错误的路线上之前,他们必须下载你的应用程序。不管你的代码分割能力有多强,他们至少需要react,react-dom, 和react-router-dom 。那是一些字节!
- react@16.13.1 - 6.3kB
- react-dom@16.13.1 - 114.6kB
- react-router-dom@5.1.2 - 28.4kB
这些大小都是经过压缩的,但未经压缩,因为压缩取决于太多的变量,无法进行准确的比较。另外,我意识到React Router v6很快就会到来,并会大大减少捆绑的大小,但请听我说!这还不包括你的应用程序。
而且这还不包括你自己的代码!
现在,让我们不要虚情假意!<Redirect /> ,只支持在同一个应用程序内重定向,所以用户无论如何都需要下载所有这些东西。但这个概念仍然适用。不要做客户端重定向,从一个已知路由到另一个已知路由。如果是从一个应用程序到另一个,那么用户只是下载并运行了一堆他们不需要的代码。另外,即使是在应用内,那么根据你对代码分割的配置情况,这绝对有可能导致用户下载过多或引发瀑布效应(导致次优性能)。
至于在你自己的应用程序中使用<Redirect /> ,用户将不得不等待,直到应用程序完成加载并实际运行后,他们地址栏中的URL才会更新为正确的URL。<Redirect /> 也许这本身并不足以成为避免使用from 的理由,但请继续阅读。
HTTP状态代码
这绝对是一个足以避免客户端重定向的理由(比如<Redirect /> 和from )。当用户通过JavaScript重定向时,没有办法通知浏览器(或搜索引擎)他们之前所在的URL不再正确,而新的才是正确的。这对搜索引擎和浏览器的缓存有影响(对错误状态代码的缓存处理也很有意思)。
服务器端重定向
我将向你展示我为bookshelf.lol实现的三个服务器端重定向。在bookhelf应用中,我在/ 的主页路线上没有任何东西(注意,bookhelf应用纯粹是为了教育目的,所以像这样半刻意的决定是不容质疑的。请注意,谢谢你)。
因此,每个对/ 的请求都应该被重定向到/list 。我想用302 来重定向,因为很可能在未来的某个时间点,我会改变主意,我不想处理破坏浏览器或搜索引擎对这个特定重定向的缓存。
Netlify (生产)
使用Netlify,你可以在 netlify.toml 文件中配置重定向,但我选择了_redirects 文件的选项。下面是该文件需要的内容,以使该重定向到位:
/ /list 302!
你可以在这里查看这个文件现在的样子。
如果我想使用netlify.toml 文件,那么它将更像这样:
[[redirects]]
from = "/"
to = "/list"
status = 302
force = true
本地建立的文件
一旦我建立了书架应用程序,如果我想在本地运行它,我就用serve来实现。这个CLI使用serve-handler它可以像这样用serve.json 来配置。
{
"redirects": [
{
"source": "/",
"destination": "/list",
"type": 302
}
]
}
你可以在这里查看这个文件的现状。
本地开发中的文件
书架应用程序是用Create React App构建的(它使用react-scripts )。这意味着开发服务器完全由我在幕后处理。幸运的是,react-scripts 确实允许为代理目的定制服务器,我可以通过在src/setupProxy.js 创建一个文件来使用它进行重定向。这只是导出了一个接受Express应用程序的函数,然后我就可以在要求使用res.redirect当请求/路线时,我可以使用
function proxy(app) {
app.get(/^\/$/, (req, res) => res.redirect('/list'))
}
module.exports = proxy
你可以在这里查看这个文件,就像现在这样。
结论
无论你最终将你的应用程序发布到什么主机上,可能都有一些配置重定向的方法(如果没有,那就太奇怪了)。为了避免简单的重定向,可能会感觉到很多工作:
<Redirect from="/" to="/list" />
但实际上,成本是相当小的(设置一次就忘了),而且在语义上正确的好处超过了这些成本。
一般来说,遵循网络的语义对现有的工具更好(就像使用语义标记对无障碍性更好一样)。如果网络标准满足用例,那么就使用网络标准。
感谢Ryan Florence(React Router的创造者),他让我相信了这个想法。