Reputation: 4024
I have the following situation:
/v1.0.0
index.html
main.js
/v1.1.0
index.html
main.js
I am using S3 with Cloudfront and have everything mostly working, however the client-side routing is broken. This is to say I am able to visit the root of each application, ie. https://<app>.cloudfront.net/<version>
, but cannot reach any client-side routes.
I'm aware that an error document can be set to redirect to an index.html
, but I believe this solution only works when there is one index.html
per bucket (ie. I cannot set an error document per route-based path).
What's the best way to get around this issue?
Upvotes: 5
Views: 2793
Reputation: 1568
One simple way to deal with SPA through Cloudfront is by using Lambda@Edge - Origin request (or Cloudfront functions). The objective is to change the Origin URI.
A simple js code that I use very often for SPAs (for the 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;
};
I check if there is an extension (.png, .js, .css, ...) in the URL. If it is an asset, I simply forward to the S3 object otherwise I send the index.html.
In that case, index.html is sent for the path /v1.0.0/my-react-router.
Updated
For dynamic handling, you can do like this (for the idea):
request.uri = '/' + request.uri.split('/')[1] + '/index.html';
Or even better, use regexp to parse the request.uri
in order to extract the version, the asset's extension or the spa route.
Upvotes: 7