I have a Python app that I do something similar with and use API Gateway with Custom Domains to achieve the desired result. In our case the display/design CSS and JS assets are rather complex and located in various domain and folder paths. Also the html is rendered server side. I might need a little more detail on your use case to perhaps provide a more tailored solution.
Since Angular is all client side I'm thinking you could point Route53 to the same S3/Cloudfront endpoint for all your subdomains and have the Angular app detect the subdomain into a variable or return the subdomain value from a function. Then use that value in the folder paths for your "theme" assets. You could store all theme assets to a separate S3 bucket used just for this purpose.
So something like this to get the subdomain value:
getSubdomain() {
const domain = window.location.hostname;
if (domain.indexOf('.') < 0 ||
domain.split('.')[0] === 'example' || domain.split('.')[0] === 'lvh' || domain.split('.')[0] === 'www') {
this.subdomain = '';
} else {
this.subdomain = domain.split('.')[0];
}
console.log('subdomain', this.subdomain);
return this.subdomain;
}
Taken and modified from How to handle tenant subdomains in Angular 2 (router 3)
Use the subdomain value with something like this:
loadScripts() {
const dynamicScripts = [
'https://my-s3-asset-bucket-url/'+getSubdomain()+'/js/test1.js',
'https://my-s3-asset-bucket-url/'+getSubdomain()+'/js/test1-more-stuff.js'
];
for (let i = 0; i < dynamicScripts.length; i++) {
const node = document.createElement('script');
node.src = dynamicScripts[i];
node.type = 'text/javascript';
node.async = false;
node.charset = 'utf-8';
document.getElementsByTagName('head')[0].appendChild(node);
}
}
loadCSS() {
const dynamicLinks = [
'https://my-s3-asset-bucket-url/'+getSubdomain()+'/css/test1.css',
'https://my-s3-asset-bucket-url/'+getSubdomain()+'/css/test1-more-stuff.css'
];
for (let i = 0; i < dynamicLinks.length; i++) {
const node = document.createElement('link');
node.href = dynamicLinks[i];
node.type = 'text/css';
node.rel ='stylesheet';
document.getElementsByTagName('head')[0].appendChild(node);
}
}
Then in your constructor:
constructor() {
this.loadScripts();
this.loadCSS();
}
Taken and modified from How to load external scripts dynamically in Angular?
You could also change the my-s3-asset-bucket-url above to a Cloudfront distribution url.