我所在的公司希望使用单个S3存储桶和Cloudfront分发为多个react网站提供服务,因为AWS允许的存储桶数量有限制。我们想要的基本文件结构在bucket的根目录下有三个文件夹(即dev、prod和sandbox(,每个文件夹都有相应的react项目。
在Cloudfront分发版中,我发送Host头以了解应该为哪个环境和bucket提供服务。我在一个Lambda@Edge函数并路由到相应的bucket,该bucket一直工作到该点。这个Lambda@Edge函数可以正确地获取index.html文件,但不能为文件夹中的所有其他文件提供服务。这导致控制台中只有一个空白的白色屏幕,其中包含几个错误:The stylesheet was not loaded because its MIME type, "text/html" is not "text/css
和Loaded file has not a valid JavaScript MIME type
。
Lambda@Edge我使用的功能如下:
'use strict';
exports.handler = (event, context, callback) => {
// Extract the request from the CloudFront event that is sent to Lambda@Edge
var cf = event.Records[0].cf;
var request = event.Records[0].cf.request;
const origin = request.origin;
const domain = request.headers.host[0].value;
if (domain.includes("dev")) {
request.uri = "/dev-test/index.html"
} else if (domain.includes("sandbox") {
request.uri = "/sandbox-test/index.html";
} else {
request.uri = "/prod-test/index.html";
}
request.headers.host[0].value = origin.s3.domainName
// Return to CloudFront
return callback(null, request);
}
该函数从Host标头中提取域,相应地设置URI,并将Host标头更改为S3域名,以避免出现权限错误。我还尝试过更改S3路径和URI,只更改路径而不更改URI,但似乎什么都不起作用。我不知道我是应该在请求中设置/更改其他内容,还是应该更改S3存储桶和/或Cloudfront分发中的设置/权限。
顺便说一句,我正在用一个基本的React JS应用程序测试这一点,我只运行了npx create-react-app my-app
,然后构建了它,并将构建文件夹中的所有内容上传到S3 bucket文件夹中。
事先非常感谢你在这件事上的帮助。
您的所有请求都返回了200 OK状态和正确的内容吗?您只看到一个带有控制台错误的空白屏幕?如果是这样的话,那么问题是你需要在CSS文件上设置mime类型,以便浏览器显示它。一些浏览器,如Chrome,如果没有text/CSS Content-type标头,就无法提供CSS文件。
你有三种设置方法:
- 将其作为元数据添加到S3存储桶中的每个CSS文件中
- 使用Lambda@Edgeorigin响应函数,用于根据文件扩展名动态设置Content-Type标头
- 创建一个路径模式为
*.css
的新缓存行为,并附加一个响应标头策略,该策略将text/css的内容类型设置为选中"原始覆盖"的自定义标头(这是免费使用的,执行速度将快于Lambda@Edge因为它是本机功能(
如果将选项1作为上传工作流的一部分添加,则选项1是最简单的。否则,建议选择3。