具有多个基于路径的单页应用程序的 S3 / Cloudfront 的客户端路由
Client-side routing for S3 / Cloudfront with multiple path-based Single Page Apps
我有以下情况:
- 具有多个基于路径的应用程序的 S3 存储桶,按版本号分组。
简化示例:
/v1.0.0
index.html
main.js
/v1.1.0
index.html
main.js
- 每个应用程序都是一个 (React) SPA 并且需要客户端路由(通过 React 路由器)
我正在将 S3 与 Cloudfront 一起使用并且一切正常,但客户端路由已损坏。这就是说我能够访问每个应用程序的根目录,即。 https://<app>.cloudfront.net/<version>
,但无法到达任何客户端路由。
我知道 重定向到 index.html
,但我相信此解决方案仅在每个存储桶有一个 index.html
时才有效(即我无法设置每个基于路由的路径的错误文档)。
解决此问题的最佳方法是什么?
通过 Cloudfront 处理 SPA 的一种简单方法是使用 Lambda@Edge - Origin 请求(或 Cloudfront functions)。
objective 是为了改变 Origin URI。
我经常用于 SPA 的简单 js 代码(对于 v1.0.0 webapp):
exports.handler = async (event) => {
const request = event.Records[0].cf.request;
const hasType = request.uri.split(/\#|\?/)[0].split('.').length >= 2;
if (hasType) return request; // simply forward to the S3 object as it is an asset
request.uri = '/v1.0.0/index.html'; // handle all react routes
return request;
};
我检查 URL 中是否有扩展名(.png、.js、.css、...)。如果它是资产,我只是转发到 S3 对象,否则我发送 index.html.
在这种情况下,index.html 被发送到路径 /v1.0.0/my-react-router.
已更新
对于动态处理,你可以这样做(为了这个想法):
request.uri = '/' + request.uri.split('/')[1] + '/index.html';
或者更好的是,使用正则表达式解析 request.uri
以提取版本、资产的扩展名或 spa 路由。
我有以下情况:
- 具有多个基于路径的应用程序的 S3 存储桶,按版本号分组。 简化示例:
/v1.0.0
index.html
main.js
/v1.1.0
index.html
main.js
- 每个应用程序都是一个 (React) SPA 并且需要客户端路由(通过 React 路由器)
我正在将 S3 与 Cloudfront 一起使用并且一切正常,但客户端路由已损坏。这就是说我能够访问每个应用程序的根目录,即。 https://<app>.cloudfront.net/<version>
,但无法到达任何客户端路由。
我知道 index.html
,但我相信此解决方案仅在每个存储桶有一个 index.html
时才有效(即我无法设置每个基于路由的路径的错误文档)。
解决此问题的最佳方法是什么?
通过 Cloudfront 处理 SPA 的一种简单方法是使用 Lambda@Edge - Origin 请求(或 Cloudfront functions)。 objective 是为了改变 Origin URI。
我经常用于 SPA 的简单 js 代码(对于 v1.0.0 webapp):
exports.handler = async (event) => {
const request = event.Records[0].cf.request;
const hasType = request.uri.split(/\#|\?/)[0].split('.').length >= 2;
if (hasType) return request; // simply forward to the S3 object as it is an asset
request.uri = '/v1.0.0/index.html'; // handle all react routes
return request;
};
我检查 URL 中是否有扩展名(.png、.js、.css、...)。如果它是资产,我只是转发到 S3 对象,否则我发送 index.html.
在这种情况下,index.html 被发送到路径 /v1.0.0/my-react-router.
已更新
对于动态处理,你可以这样做(为了这个想法):
request.uri = '/' + request.uri.split('/')[1] + '/index.html';
或者更好的是,使用正则表达式解析 request.uri
以提取版本、资产的扩展名或 spa 路由。