javascript 反应路由器在 aws s3 存储桶中不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/51218979/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
react router doesn't work in aws s3 bucket
提问by Viet
I deployed my React website build/folder into an AWS S3 bucket.
我将我的 React 网站build/文件夹部署到 AWS S3 存储桶中。
If I go to www.mywebsite.com, it works and if I click on atag to go to Project and About pages, it leads me to the right page.
However, if I copy and send the page url or go straight to the link like: www.mywebsite.com/projects, it returns 404.
如果我转到www.mywebsite.com,它会起作用,如果我单击a标记转到“项目”和“关于”页面,它会将我带到正确的页面。但是,如果我复制并发送页面 url 或直接转到以下链接:www.mywebsite.com/projects,它会返回 404。
Here's my App.jscode:
这是我的App.js代码:
const App = () => (
<Router>
<div>
<NavBar/>
<Switch>
<Route exact path="/" component={Home}/>
<Route exact path="/projects" component={Projects}/>
<Route exact path="/about" component={About}/>
<Route component={NoMatch}/>
</Switch>
</div>
</Router>
);
采纳答案by Viet
Update 1 May 2020:
2020 年 5 月 1 日更新:
Since this post is quite active, I need to update the answer:
由于这个帖子很活跃,我需要更新答案:
So you have a few options to solve the issue:
所以你有几个选项来解决这个问题:
- You can put index.htmlin the Error documentbox (like Alan Friedman suggested).
- Go to your bucket (the one that actually has the code - not the one you use to redirect) -> Properties-> Static website hosting:
- This is not "hacky" but it works because of the way
react-routerworks: It handles the requests from the front-end and routes users to other routes but overall, the React app is a single-page application. - If you want server-side React, consider using Next.js.
- 您可以将index.html放在错误文档框中(就像 Alan Friedman 建议的那样)。
- 转到您的存储桶(实际拥有代码的存储桶 - 不是您用来重定向的存储桶)->属性->静态网站托管:
- 这不是“hacky”,但它的工作方式是
react-router有效的:它处理来自前端的请求并将用户路由到其他路由,但总的来说,React 应用程序是一个单页面应用程序。 - 如果您想要服务器端 React,请考虑使用Next.js。
You can put a designated error file error.htmlin the publicfolder of your React app and in the Static website hosting: Error documentbox, put in: error.html. This also works. I've tested it.
Use AWS CloudFront> CloudFront Distributions> The distribution of your bucket > Error Pagesand add the error code you want. If you don't use
react-router(like the example below), the bucket will respond with Error 403so you can respond with your error.html.
您可以将指定的错误文件error.html放入您的 React 应用程序的公共文件夹和静态网站托管:错误文档框中,放入:error.html。这也有效。我已经测试过了。
使用AWS CloudFront> CloudFront Distributions> The distribution of your bucket > Error Pages并添加您想要的错误代码。如果您不使用
react-router(如下例所示),存储桶将响应错误 403,因此您可以使用您的error.html进行响应。
- For
TypeScript, currentlyreact-routerdoesn't support it so you should consider option 2 and 3. They're going to update the library in future version6.*according to this thread.
- 对于
TypeScript,目前react-router不支持它,因此您应该考虑选项 2 和 3。他们将6.*根据此线程在未来版本中更新库。
回答by A.R Naseef
I'm not sure if you have already solved it. I had the same issue.
我不确定你是否已经解决了它。我遇到过同样的问题。
It's because AWS S3 is looking for that folder (projects) to serve from, which you don't have.
这是因为 AWS S3 正在寻找要从中提供服务的文件夹(项目),而您没有。
Simply point Error document to index.html.
只需将错误文档指向index.html.
This worked for me. You can handle error pages in react-router.
这对我有用。您可以在 react-router 中处理错误页面。
回答by Flávio Vieira
Case use Cloudfront to S3:
案例使用 Cloudfront 到 S3:
https://hackernoon.com/hosting-static-react-websites-on-aws-s3-cloudfront-with-ssl-924e5c134455
https://hackernoon.com/hosting-static-react-websites-on-aws-s3-cloudfront-with-ssl-924e5c134455
3b) AWS CloudFront?—?Error Pages After creating the CloudFront distribution, while its status is In Progress, proceed to the Error Pages tab. Handle response codes 404 and 403 with Customize Error Response.
3b) AWS CloudFront?—?Error Pages 创建 CloudFront 分配后,当其状态为进行中时,进入错误页面选项卡。使用自定义错误响应处理响应代码 404 和 403。
Google recommends 1 week or 604800 seconds of caching. What we are doing here is to set up CloudFront to handle missing html pages, which typically occurs when a user enters an invalid path or, in particular, when they refresh a path other than the root path.
Google 建议缓存 1 周或 604800 秒。我们在这里所做的是设置 CloudFront 来处理丢失的 html 页面,这通常发生在用户输入无效路径时,特别是当他们刷新根路径以外的路径时。
When that happens:
当发生这种情况时:
CloudFront will be looking for a file that does not exist in the S3 bucket; there is only 1 html file in the bucket and that is the index.html for the case of a Single Page Application like this project example A 404 response will be returned and our custom error response setup will hiHyman it. We will return a 200 response code and the index.html page instead. React router, which will be loaded along with the index.html file, will look at the url and render the correct page instead of the root path. This page will be cache for the duration of the TTL for all requests to the queried path. Why do we need to handle 403 as well? It is because this response code, instead of 404, is returned by Amazon S3 for assets that are not present. For instance, a url of https://yourdomain.com/somewherewill be looking for a file called somewhere (without extension) that does not exist.
CloudFront 将查找 S3 存储桶中不存在的文件;存储桶中只有 1 个 html 文件,对于像这个项目示例这样的单页应用程序,它是 index.html 将返回 404 响应,我们的自定义错误响应设置将劫持它。我们将返回 200 响应代码和 index.html 页面。React 路由器将与 index.html 文件一起加载,它将查看 url 并呈现正确的页面而不是根路径。对于对查询路径的所有请求,此页面将在 TTL 期间被缓存。为什么我们还需要处理 403?这是因为 Amazon S3 为不存在的资产返回此响应代码,而不是 404。例如,https://yourdomain.com/somewhere 的网址将寻找一个不存在的名为某处(没有扩展名)的文件。
PS. It used to be returning 404, but it seems to be returning 403 now; either way it is best to handle both response codes).
附注。以前是返回404,现在好像是返回403;无论哪种方式,最好都处理两个响应代码)。
回答by Meir Gabay
In case this S3 bucket is served from a CloudFront distribution:
如果此 S3 存储桶由CloudFront 分配提供:
Create a custom error page (AWS Docs)in CloudFront distribution that routes 404 errors to index.html and returns 200 response code. This way your application will handle the routing.
在 CloudFront 分配中创建一个自定义错误页面 (AWS Docs),将 404 错误路由到 index.html 并返回 200 响应代码。这样您的应用程序将处理路由。
Custom Error Pages
自定义错误页面
回答by Gegenwind
Why it happens
为什么会发生
Your issue is that you want to pass responsibility to routing to your react app/javascript. The link will work because react can listen to the link click and simply update the route in the browser URL bar. However, if you go a location where your script (index.html and the bundle.js or wherever your app code is located) is not loaded, then the JavaScript is never loaded and has no chance to handle the request. Instead, whatever runs your server will take care of the request, look if there is a resource at this place, and return a 404 error or whatever else it found.
您的问题是您想将责任传递给您的反应应用程序/javascript。该链接将起作用,因为 React 可以监听链接点击并简单地更新浏览器 URL 栏中的路由。但是,如果您前往脚本(index.html 和 bundle.js 或您的应用程序代码所在的任何位置)未加载的位置,则 JavaScript 永远不会加载并且没有机会处理请求。相反,无论您的服务器运行什么,都会处理请求,查看此位置是否有资源,并返回 404 错误或发现的其他任何内容。
The solution
解决方案
As mentioned in the comments, this is the reason why you need to redirect 404-errors to the exact location where your app is placed. This is nothing specific to Amazon, it is a general requirement to set up your react app.
正如评论中所提到的,这就是您需要将 404 错误重定向到放置应用程序的确切位置的原因。这不是亚马逊特有的,它是设置 React 应用程序的一般要求。
To solve the issue you need to find out what handles routing on your server and how to configure it. For example if you have an Apache server, an .htaccess file could take care of the matter like this:
要解决此问题,您需要了解服务器上处理路由的内容以及如何配置它。例如,如果你有一个 Apache 服务器,一个 .htaccess 文件可以处理这样的事情:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
This file lets the server redirect not found errors to the index.html. Keep in mind that it might affect other routing rules that are on your server, so this configuration is easiest, if your react app has a place on its own, not interfering with other stuff.
该文件允许服务器将未找到的错误重定向到 index.html。请记住,它可能会影响您服务器上的其他路由规则,因此如果您的 React 应用程序有自己的位置,而不干扰其他内容,则此配置是最简单的。
回答by jethroFloyd
This question already has several great answers. Although the question is now old, I faced this problem today, so I feel that perhaps this answer can help.
这个问题已经有几个很好的答案。虽然这个问题现在已经很老了,但我今天遇到了这个问题,所以我觉得这个答案可能会有所帮助。
S3 has two kinds of end points, and if you are facing this error, you have probably selected the S3 bucket directly as the endpoint in the Origin Domain Name field for your CloudFront Distribution.
S3 有两种端点,如果您遇到此错误,您可能已直接选择 S3 存储桶作为 CloudFront 分配的源域名字段中的端点。
This would look something like: bucket-name.s3.amazonaws.comand is a perfectly valid endpoint. In fact, it would seem that AWS does expect this as default behaviour; this entry will be in the drop-down list you have when you are creating your CloudFront distribution.
这看起来像:bucket-name.s3.amazonaws.com并且是一个完全有效的端点。事实上,AWS 似乎确实希望这是默认行为;此条目将在您创建 CloudFront 分配时的下拉列表中。
However, doing this and then setting error pages may or may not solve your problem.
但是,执行此操作然后设置错误页面可能会也可能不会解决您的问题。
S3 has, however, a dedicated Website Endpoint. This is accessible from your S3 Bucket > Properties > Static Website Hosting. (You will see the link on the top).
但是,S3 有一个专用的网站端点。这可以从您的 S3 存储桶 > 属性 > 静态网站托管访问。(您将在顶部看到链接)。
You should use this link instead of the original auto-populated link that comes up in CloudFront. You can put this in while creating your distribution, or after creation, you can edit from the tab Origins and Origins Groups, and then invalidating caches.
您应该使用此链接而不是 CloudFront 中出现的原始自动填充链接。您可以在创建发行版时将其放入,或者在创建后,您可以从“起源”和“起源组”选项卡进行编辑,然后使缓存无效。
This link will look like: bucket-name.s3-website.region-name.amazonaws.com.
这个链接看起来像:bucket-name.s3-website.region-name.amazonaws.com。
Once this propagates and changes, this should then fix your problem.
一旦这种传播和变化,这应该可以解决您的问题。
tl;dr: Don't use the default S3 endpoint in CloudFront. Use the S3 website endpoint instead. Your origin domain should look like this: my-application.s3-website.us-east-1.amazonaws.comand not like my-application.s3.amazonaws.com.
tl;dr:不要在 CloudFront 中使用默认的 S3 端点。请改用 S3 网站端点。您的原始域应如下所示:my-application.s3-website.us-east-1.amazonaws.com而不是my-application.s3.amazonaws.com.
More Information about website endpoints is available in the AWS Documentation here.
此处的 AWS 文档中提供了有关网站终端节点的更多信息。
回答by Amr Abu Greedah
Redirecting 4xx to index.html would work, but that solution would make you fall into many other problems like google won't be able to crawl these pages. Please check this link, it solved this issue by using redirection rules for the S3 bucket.
将 4xx 重定向到 index.html 是可行的,但该解决方案会使您陷入许多其他问题,例如 google 将无法抓取这些页面。请检查此链接,它通过使用 S3 存储桶的重定向规则解决了此问题。
回答by Dank
I ran into this issue despite using the configuration as described in the accepted answer, but if you still get 403 errors, AND you're using AWS Cloudflare Manager, you can create an error page in the "Error Pages" tab of the distribution settings, with the following configuration:
尽管使用了已接受答案中描述的配置,但我还是遇到了这个问题,但是如果您仍然收到 403 错误,并且您使用的是 AWS Cloudflare Manager,您可以在分配设置的“错误页面”选项卡中创建一个错误页面,具有以下配置:
Error Code: 404,
Customize Error Response: Yes,
Response Page Path: /index.html,
HTTP Response Code: 200
Pic of Error Page Config to pass route handling to browser router
This worked for me although I'm by no means knowledgeable about proper server admin, hopefully someone will tell me if this is a major issue, if serendipitous.
这对我有用,尽管我对适当的服务器管理员一无所知,但希望有人会告诉我这是否是一个主要问题,如果是偶然的。
回答by Valerii
As per previous answers, the best way to solve the problem: redefine the fallback strategy. If you'd like to learn more about client-side routing vs server-side, and particularly about different routing approaches in the React JS, check out this article.
根据之前的答案,解决问题的最佳方法是:重新定义回退策略。如果您想更多地了解客户端路由与服务器端,尤其是 React JS 中的不同路由方法,请查看这篇文章。


