Angular 9 Failed to load module script using AWS S3 and Cloudfront
Asked Answered
O

4

6

I am hosting my Angular 9 application in AWS using S3 and CloudFront Service. After accessing the application I am getting following error in the browser:

  • Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec. /polyfills-es2015.5af60e74e954ace452ee.js:1
  • Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec. /main-es2015.9d477ae8338087e639b5.js:1
  • Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.

My index.html:

<!doctype html>
<html>
<head>    
  <meta charset="utf-8">
  <title>ReachApp Success</title>
  <base href="/reach">
    <!-- TODo: check for common configuration for material icon -->
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> 
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <script src='https://www.google.com/recaptcha/api.js' async defer></script> 
<link rel="stylesheet" href="styles.7f06624db32e037ad1c6.css"></head>
<body>
  <reach-root></reach-root>
  <div id="displayError"></div> <!-- Display message if IE broswer-->
<script src="runtime-es2015.0dae8cbc97194c7caed4.js" type="module"></script><script src="runtime-es5.0dae8cbc97194c7caed4.js" nomodule defer></script><script src="polyfills-es5.352c85d9e468300d10fb.js" nomodule defer></script><script src="polyfills-es2015.27bdbf82a4d61d823e83.js" type="module"></script><script src="main-es2015.89b57a9808d25011d96d.js" type="module"></script><script src="main-es5.89b57a9808d25011d96d.js" nomodule defer></script></body>
</html>

I already tried different suggestions provided by others by replacing the type="module" to type="text/javascript" but still no luck. Could anyone suggest any possible fix for this issue?

Octennial answered 25/9, 2020 at 22:11 Comment(11)
What response you get if you open /main-es2015.9d477ae8338087e639b5.js in the browser? Is it a HTML page (such as an error page) or the Javascript you expect?Boat
Do you have these two files in your project: web.config, .htaccess?Anodize
@TamásSallai it opens the index.html page and not the actual javascript.Octennial
@Anodize no I don't have either of those files in my project. Why do I need it and what should be content of those files?Octennial
How did you configure CloudFront? What I suspect is that you have an error page set up and that returns the index.html for all 404'sBoat
@TamásSallai I have setup 403 error code to return index.html. This setting is there when my application was running on Angular 7 and never caused any problem. What do you suggest I should have if you think that is the cause of the problem?Octennial
Then the error is that CloudFront does not find the js file, then it returns the index.html, which the browser tries to interpret as javascript and fails. Is the /main-es2015.9d477ae8338087e639b5.js file present in the S3 bucket and can be read by the CloudFront distibution?Boat
@TamásSallai yes, all these files are in S3 bucket and at the same level as index.html. How do I ensure that Cloudfront can read this file? Any suggestions on how should be the setup?Octennial
Could you post some images of the S3 bucket and the CloudFront configuration (origin and cache behavior config)? It should work, as the index.html is readable, so should be the other files, but there is a glitch somewhereBoat
@TamásSallai I found a setting in CloudFront which was causing this issue. - I enabled Restrict Viewer Access (Use Signed URLs or Signed Cookies) property to Yes and because of that I was not able to access the application - After disabling this property the application loads correctly - But because of my company policy I cannot keep this flag disabled so I am looking into ways how to generate the signed cookie and host the application.Octennial
Yep, that explains the error.Boat
T
4

AWS S3 determines the default "content-type" metadata for the js files to be "text/plain" during upload. A workaround to fix such types of issues is to upload files to s3 and specify the content-type in metadata for js files explicitly. Eg.

aws s3 sync $DIST_PATH/ s3://$BUCKET_NAME/ --exclude "*.js"
aws s3 sync $DIST_PATH/ s3://$BUCKET_NAME/ --include "*.js" --content-type "application/javascript"
aws cloudfront create-invalidation \
    --distribution-id $DISTRIBUTION_ID\
    --paths "/
Trojan answered 18/5, 2022 at 12:11 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Sikes
G
1

After going through all the comments the most probable cause for this issue is below

Check

  1. If you are deploying in subfolder then build with base_href tag in ng build --prod command
  2. make sure to invalidate cloud front with /*
  3. In AWS cloudfront open redirect tab. Make sure you redirect the error pages(403) to index.html with 200 response

More info about BASE_HREF

--base-href If you deploy your Angular app to a subfolder, the ‘--base-href’ is important to generate the correct routes. This parameter will update the tag inside the index.html.

For example, if the index.html is on the server at /angularapp/index.html, the base href should be set to .

More information: https://angular.io/guide/deployment

ng build --prod --base-href /angularapp/
Grays answered 3/12, 2020 at 9:40 Comment(0)
O
1

I was facing the same issue. Turns out we had an Lambda@Edge integration. After disabling it, everything started working fine again.

Onomatology answered 14/10, 2021 at 6:6 Comment(0)
V
0

I found an easier solution:

Go to angular.json and update the outputPath parameter to just dist instead of dist/YourAppName. Now use ng build --configuration production to publish your app

Visualize answered 25/1, 2023 at 11:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.