Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS Cloudfront distribute multilingual angular apps

I have an Angular app which is store in a AWS S3 bucket and distributed by Cloudfront.

Now I want to distribute my app in multiple languages. I've already translated my angular app and for each language I have on build.

So my S3 bucket looks like this:

de
   /index.html
   /script.js
en
   /index.html
   /script.js

For each language I want to serve another app.

In Cloudfront I created two Origins which points to Origin Path /de and /en

So my URL schema is like this:

<appname>.<mydomain>.com/:lang

But my problem is, I dont get the Error Pages to work with these specific language folders. I need these Error Response Handlers to deliver the angular app(s) when a 404 occurred (due to a reload)

Does anyone know how I can solve this? Or should i create one more subdomain for each language? So it looks like this:

<lang>.<appname>.<mydomain>.com
like image 221
Roman Avatar asked Mar 02 '18 09:03

Roman


1 Answers

I've recently bumped into the same problem. My situation:

  • I have an Angular 5 app
  • I'm using i18n for 2 languages (en & fr)
  • S3 for website hosting and Cloudfront for CDN & custom domain name/ssl certificate
  • My default language is EN, so https://example.com redirects to https://example.com/en/
  • When a user navigates directly to a route (eg https://example.com/en/product/1234), it should also work, irrespectively of the number of subfolders

Solution:

  • Create 2 separate deployments, 1 for each language (en, fr). Git bash tends to replace the /en/ with a local folder, so make sure your index.html file contains the right base url

ng build -prod -aot --base-href /en/ --i18nFile=src/locale/messages.en.xlf --i1nFormat=xlf --locale=en

  • Deploy these into an /en/ and /fr/ folder at the root of your S3 bucket
  • Create a new CloudFront distribution. Make sure to leave the Default Root Object empty!
  • Add your bucket as an S3 origin (as you otherwise would).
  • Now, create a new Lambda function, use Node 6.10. Important: select US-EAST-1, as this is the only region supported by Lambda@Edge. Code:

const path = require('path')

exports.handler = (evt, ctx, cb) => {
  const { request } = evt.Records[0].cf

  if (!path.extname(request.uri)) {
      if (request.uri.startsWith('/fr'))
        request.uri = '/fr/index.html'
      else
        request.uri = '/en/index.html'
  }
  cb(null, request)
}
  • Next: publish this version (in the Action dropdown)
  • Copy the ARN of this version, and go back to CloudFront -> Behaviors -> Default Behavior
  • Select Origin Request as Event Type in the Lambda Function Associations, and paste the ARN of the Lambda function.

Building Angular with the base path parameter will establish the right subdirectory for your Angular app. The rewrite will make sure that resource files will not be rewritten, but all your routes will be redirected to index.html

like image 80
Dries Van Hansewijck Avatar answered Oct 02 '22 16:10

Dries Van Hansewijck