Vie*_*iet 24 javascript amazon-s3 amazon-web-services reactjs
我将React网站build/文件夹部署到AWS S3存储桶中.
如果我去www.mywebsite.com,它可以工作,如果我点击a标签去项目和关于页面,它会引导我到正确的页面.但是,如果我复制并发送页面网址或直接转到类似的链接:www.mywebsite.com/projects,则返回404.
这是我的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>
);
Run Code Online (Sandbox Code Playgroud)
A.R*_*eef 43
我不确定你是否已经解决了它.我遇到过同样的问题.
这是因为AWS S3正在寻找您没有的文件夹(项目).
只需将错误文档指向即可index.html.
这对我有用.您可以在react-router中处理错误页面.
Mei*_*bay 29
如果此 S3 存储桶由CloudFront 分配提供:
在 CloudFront 分配中创建自定义错误页面 (AWS Docs),将 404 错误路由到 index.html 并返回 200 响应代码。这样您的应用程序将处理路由。
Kon*_*los 18
此线程中有一些很好的答案,主要是关于使用重定向规则配置 S3 存储桶。虽然这也适用于我的用例,通常是通过 CloudFront 使用 React Router 托管 React 单页面应用程序,并将 S3 配置为源,但考虑到最近发布的一种新功能,我决定尝试一种不同的方法,云前功能。主要思想是在 URL 到达 CloudFront 缓存之前重写 URL,以便将客户端上的 React Router 创建的 URL 重写为指向应用程序域根。
您可以在此处阅读有关 CloudFront Functions 的更多信息: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-functions.html
主要思想是使用 CloudFront 函数重写任何不针对静态文件(即 .js、.CSS、.html 等)的请求的请求 Uri,并使其指向 /index.html 文件。此函数将作为查看器请求触发器的一部分运行,并在 CloudFront 检查请求的对象是否在 CloudFront 缓存中之前运行。这将导致客户端发送的由 React Router 生成的任何 Uri 在从源服务器请求内容之前被重写,因此不需要在 S3 上进行任何进一步的重定向。同时,被请求但在源上不再存在的文件将按预期返回 404,而所有其他静态内容将按请求提供。
我的 CloudFront 函数如下所示:
function handler(event) {
var request = event.request;
if (!request.uri.includes('.')) {
request.uri = "/index.html";
request.querystring = {}
}
return request;
}
Run Code Online (Sandbox Code Playgroud)
您可以将 URL 重写规则设置得尽可能复杂,但令人惊讶的是,这一小段代码非常适合我的用例。此外,与 Lambda@Edge 函数不同,CloudFront Functions 更加轻量级,允许您通过 AWS 控制台几乎实时进行实验,方法是更改函数代码,在几秒钟内测试并部署它。但是,它们具有某些语言限制,因此不要期望支持所有 JavaScript 语言功能。此页面记录了可供您使用的内容:
Vie*_*iet 12
回答以结束问题。多亏了艾伦·弗里德曼(Alan Friedman)的上述评论,我已经解决了这个问题:
您需要将错误(在本例中为404)重定向到根index.html – 7月7日,0:34
小智 9
案例使用 Cloudfront 到 S3:
https://hackernoon.com/hosting-static-react-websites-on-aws-s3-cloudfront-with-ssl-924e5c134455
3b) AWS CloudFront?—?Error Pages 创建 CloudFront 分配后,当其状态为进行中时,进入错误页面选项卡。使用自定义错误响应处理响应代码 404 和 403。
Google 建议缓存 1 周或 604800 秒。我们在这里所做的是设置 CloudFront 来处理丢失的 html 页面,这通常发生在用户输入无效路径时,特别是当他们刷新根路径以外的路径时。
当发生这种情况时:
CloudFront 将查找 S3 存储桶中不存在的文件;存储桶中只有 1 个 html 文件,对于像这个项目示例这样的单页应用程序,它是 index.html 将返回 404 响应,我们的自定义错误响应设置将劫持它。我们将返回 200 响应代码和 index.html 页面。React 路由器将与 index.html 文件一起加载,它将查看 url 并呈现正确的页面而不是根路径。对于对查询路径的所有请求,此页面将在 TTL 期间被缓存。为什么我们还需要处理 403?这是因为 Amazon S3 为不存在的资产返回此响应代码,而不是 404。例如,https ://yourdomain.com/somewhere 的网址 将寻找一个不存在的名为某处(没有扩展名)的文件。
附注。以前是返回404,现在好像是返回403;无论哪种方式,最好都处理两个响应代码)。
这里有很多答案,所以我想我应该对迄今为止现有的答案进行调查,并比较各种方法的优缺点。
| 方法 | 描述 | 优点 | 缺点 | 答案 |
|---|---|---|---|---|
| 云前功能 | 使用 AWS CloudFront 函数将请求写入 SPA 的根文档,例如index.html |
没有抛出错误,没有重定向,显然有利于 SEO。AWS 在他们的一份文档中建议了这种方法。 | 额外费用(尽管在撰写本文时,免费套餐允许每月免费 200 万次调用,之后每百万次调用仅收取 10c)。需要部署/管理的额外基础设施。 | 公斤 |
| 作为网站托管 | 配置 S3 存储桶来托管网站,而不是 REST API。 | 当以这种方式配置时,路由由 S3 自动处理。 | 无法使用 Orign Access Identity。相反,S3 端点通过 HTTP 公开,您需要使用自定义标头来限制访问,这更加复杂。 | 前值 |
| 错误重定向(404 和 403) | 绝大多数答案似乎都提供了一些这种味道。这个想法是允许 404 或 403 错误发生,但随后返回index.html(或任何 SPA 根文档)作为错误页面。 |
易于实施。 | 每次客户端尝试访问非根 URL 时都会导致客户端重定向。显然这对 SEO 不利。 | AR , V , MG , PB , K , KS |
| URL 哈希/Hashbang | 一些解决方案涉及使用 URL 中的哈希值来路由子页面。 | 无需重定向,也无需支付额外的 AWS 资源费用。 | 这些方法似乎存在问题 - 请参阅此处。有些人认为 URL 中的哈希值很丑陋;似乎确实有办法减轻这种情况,但这涉及一些额外的复杂性。 | AA , B |
注意:我的这个答案是基于我在其他答案中读到的内容。除了“CloudFront Function”方法之外,我还没有完全测试任何方法,我可以确认该方法有效。
小智 8
这个问题已经有几个很好的答案。虽然这个问题现在已经很老了,但我今天遇到了这个问题,所以我觉得这个答案可能会有所帮助。
S3 有两种端点,如果您遇到此错误,您可能已直接选择 S3 存储桶作为 CloudFront 分配的源域名字段中的端点。
这看起来像:bucket-name.s3.amazonaws.com并且是一个完全有效的端点。事实上,AWS 似乎确实希望这是默认行为;此条目将在您创建 CloudFront 分配时的下拉列表中。
但是,执行此操作然后设置错误页面可能会也可能不会解决您的问题。
但是,S3 有一个专用的网站端点。这可以从您的 S3 存储桶 > 属性 > 静态网站托管访问。(您将在顶部看到链接)。
您应该使用此链接而不是 CloudFront 中出现的原始自动填充链接。您可以在创建发行版时将其放入,或者在创建后,您可以从“起源”和“起源组”选项卡进行编辑,然后使缓存无效。
这个链接看起来像:bucket-name.s3-website.region-name.amazonaws.com。
一旦这种传播和变化,这应该可以解决您的问题。
tl;dr:不要在 CloudFront 中使用默认的 S3 端点。请改用 S3 网站端点。您的原始域应如下所示:my-application.s3-website.us-east-1.amazonaws.com而不是my-application.s3.amazonaws.com.
此处的 AWS 文档中提供了有关网站终端节点的更多信息。
这个线程对我来说真的很有帮助。我知道这已经很旧了,但是,我想添加一个aws-cdk最终对我有用的代码片段。我的用例需要我利用aws-cdk,因此,如果您期待aws-cdk基于解决方案,我将在此处添加它。
该代码片段index.html在 s3 和 cloudfront 中添加为错误页面。特别是对于 cloudfront,我添加了错误页面,并且/index.html响应为404403200
// imports...
// import * as cdk from '@aws-cdk/core';
// import * as s3 from '@aws-cdk/aws-s3';
// import * as cloudfront from '@aws-cdk/aws-cloudfront';
// following code snippet has to be added in a
// class which extends to a Construct or a Stack
const bucket = new s3.Bucket(this, '<Specify a name>', {
bucketName: '<add your bucket name>',
websiteIndexDocument: 'index.html',
websiteErrorDocument: 'index.html',
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
removalPolicy: cdk.RemovalPolicy.DESTROY, // edit it according to your use case, I'll change it though
autoDeleteObjects: true,
});
const cloudFrontOAI = new cloudfront.OriginAccessIdentity(this, 'OAI');
const distribution = new cloudfront.CloudFrontWebDistribution(this, props?.stackName + 'AbcWebsiteDistribution', {
defaultRootObject: "index.html",
errorConfigurations: [{
errorCode: 404,
responsePagePath: "/index.html",
responseCode: 200
}, {
errorCode: 403,
responsePagePath: "/index.html",
responseCode: 200
}],
originConfigs: [
{
s3OriginSource: {
s3BucketSource: bucket,
originAccessIdentity: cloudFrontOAI,
originPath: "/artifacts" // change this based on your use case
},
behaviors: [{ isDefaultBehavior: true }]
}
]
})
bucket.grantRead(cloudFrontOAI.grantPrincipal);
Run Code Online (Sandbox Code Playgroud)
从这个帖子中真正帮助我的答案是:
| 归档时间: |
|
| 查看次数: |
9149 次 |
| 最近记录: |