58

I deployed my angular application(Static webpage) on kubernetes and tried launching it from Google Chrome. I see app is loading, however there is nothing displayed on the browser. Upon checking on browser console , I could see this error

"Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec." for (main.js,poylfill.js,runtime.js) files . I research few forums and one possible rootcause could because of type attribute in <script> tag should be type=text/javascript instead of type=module in my index.html file that is produced under dist folder after executing ng build. I don't how to make that change as to these tags as generated during the build process, and my ng-build command is taken care by a docker command.

URL i'm trying to access will be something like : "http://xxxx:portnum/issuertcoetools

note: The host xxxx:portnum will be used by many other apps as well.

Are there any work-arounds or solutions to this issue?

index.html - produced after running ng-build in local, (which is the same i see in kubernetes POD too)

<!DOCTYPE html><html lang="en"><head>
    <meta charset="utf-8">
    <title>Data Generator</title>
    <base href="/">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" type="image/x-icon" href="favicon.ico">
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <style type="text/css">@font-face{font-family:'Roboto';font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOlCnqEu92Fr1MmSU5fCRc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;}@font-face{font-family:'Roboto';font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOlCnqEu92Fr1MmSU5fABc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;}@font-face{font-family:'Roboto';font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOlCnqEu92Fr1MmSU5fCBc4AMP6lbBP.woff2) format('woff2');unicode-range:U+1F00-1FFF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOlCnqEu92Fr1MmSU5fBxc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0370-03FF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOlCnqEu92Fr1MmSU5fCxc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;}@font-face{font-family:'Roboto';font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOlCnqEu92Fr1MmSU5fChc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOlCnqEu92Fr1MmSU5fBBc4AMP6lQ.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOmCnqEu92Fr1Mu72xKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOmCnqEu92Fr1Mu5mxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOmCnqEu92Fr1Mu7mxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+1F00-1FFF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOmCnqEu92Fr1Mu4WxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0370-03FF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOmCnqEu92Fr1Mu7WxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOmCnqEu92Fr1Mu7GxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOlCnqEu92Fr1MmEU9fCRc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOlCnqEu92Fr1MmEU9fABc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOlCnqEu92Fr1MmEU9fCBc4AMP6lbBP.woff2) format('woff2');unicode-range:U+1F00-1FFF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOlCnqEu92Fr1MmEU9fBxc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0370-03FF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOlCnqEu92Fr1MmEU9fCxc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOlCnqEu92Fr1MmEU9fChc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOlCnqEu92Fr1MmEU9fBBc4AMP6lQ.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}</style>
    <style type="text/css">@font-face{font-family:'Material Icons';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/materialicons/v128/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2) format('woff2');}.material-icons{font-family:'Material Icons';font-weight:normal;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:'liga';-webkit-font-smoothing:antialiased;}</style>
<style>.mat-typography{font:400 14px/20px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal}html,body{height:100%}body{margin:0;font-family:Roboto,Helvetica Neue,sans-serif}</style><link rel="stylesheet" href="styles.9c0548760c8b22be.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.9c0548760c8b22be.css"></noscript></head>

<body class="mat-typography">
    <app-root></app-root>
 
<script src="runtime.397c3874548e84cd.js" type="module">
</script><script src="polyfills.2145acc81d0726ab.js" type="module">
</script><script src="main.a655dca28148b7e2.js" type="module"></script>

</body></html>

nginx.conf file

worker_processes 4;

events { worker_connections 1024; }

http {
    server {
        listen 8080;
        include /etc/nginx/mime.types;

  location /issuertcoetools {
    root /usr/share/nginx/html;
    index index.html index.htm;
    try_files $uri $uri/ /index.html =404;
  }
}
}

0

16 Answers 16

35

This error usually happens because you deployment was into a subfolder, so it seems like Angular is fetching you app directly from your base URL, so your html is found when you go to your domain.com/mysubfolder/index.html, but as the Angular fetches your resources from domain.com/index.html instead of domain.com/mysubfolder/index.html; I’m pretty sure this is the cause of your issue. You can resolve it building your app with:

ng build --prod --base-href mysubfolder
Sign up to request clarification or add additional context in comments.

1 Comment

Late update, the solution given by you worked . However on the latest version of angular “—base-href” is deprecated. the given solution can only be implemented by declaring APP_BASE_HREF value in NgModule section on app.module.ts file .. dtls here angular.io/api/common/APP_BASE_HREF
31

Fixed the issue in my case by disabling the browser cache:

enter image description here

5 Comments

You save my day!. i was loogin this answer for 2 hours
the question is how to make it without disable cache and other thing which casual user of web app won't do.
@Jemy depending on the headers it might be that a new version won't be downloaded for many years if people never delete their cookies. Furthermore there might be a proxy-cache for some sites, so there is no general solution, especially not with "disable cache". People who are not experienced with all the browser options pose a special challenge for webmasters which might be unsolvable ¯_(ツ)_/¯
@Jemy, there is a reason why first thing a L1 support operator will ask will be to clear the cache ;) these things aren't easily avoidable. But to us, it should be muscle memory to just try it in an incognito tab when things don't look right for apparently no reason. Also, this is the reason why I don't use Chrome nor Firefox as my main browsers. I frequently clean everything in them because of testing my software
This worked for me also. I believe that this may happen when I launched one version, then deployed, then tried to launch again and something is still kept in browser cached. Just a guess.
13

I was trying to add an Angular app in a subdirectory.

@Leo's answer is correct. I made it manually by changing the base reference in index.html.

From <base href=""> to <base href="http://subdomain.domain.com/subdirectory/"> and it worked!

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>Website</title>
    <!-- <base href=""> -->
    <base href="http://subdomain.domain.com/subdirectory/">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" type="image/x-icon" href="favicon.ico">

<body>...</body>

</html>

2 Comments

I tried your solution and it seems to work fine (no more problem when I copy/paste the url in the browser). This "trick" works in conjunction with url rewriting set either in the web.config file on IIS or in the .htaccess file on Apache. Url rewriting avoid to use hash symbol in url. Url rewriting avoid us to use the disgraceful hash symbol in url.
This worked for me! However, I have local, dev, and prod deployments so hard coding the entire URL wasn't an option for me. So, I just did: <base href="/en/" />
6

Solution:

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

Explanation:

The problem is that when you run the command ng build --configuration production then the solution is outputted into dist/YourAppName and then paths get's broken because Angular think your app is in your root folder, but it is in root/YourAppName. Doing the above puts your app in root folder.

1 Comment

This one worked for me, changing output path to just "dist". Thank you very much!
6

We had few sites live ~1 month and one day we started facing Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html" problem. We did not change nginx config before this issue, but we thought that the problem was related to nginx.

Everything was ok with Nginx, the problem was with Cloudflare caching, so do the next:

  • enable Development mode in Cloudflare (here we disable Cloudflare caching)
  • open site (we should see our site without any problems)
  • disable Development mode in Cloudflare (here we enable Cloudflare caching)

One more way how to fix it...

In Cloudflare:

  • Log in
  • Select Project
  • Select Domain
  • In the right block "Quick Actions" there is a link "Configure caching" (click it)
  • In the "Purge Cache" block click "Purge Everything" button

2 Comments

This fixed it for me. I started visiting the JS files directly in the browser (e.g. example.com/chunk-ASI62OLC.js) and they would show an HTML page with "Welcome to nginx! If you see this page, the nginx web server is successfully installed and working. Further configuration is required.". If I force refresh the page 2 times it would show the JS contents, but the index.html page in chrome was still getting the cached page even if I disabled cache in chrome. Finally switching CloufFlare to development mode (under Caching) fixed it.
this is true in my case
4

Check include /etc/nginx/mime.types; In the NGINX conf, that path may have an error, lean on the logs (nginx).

4 Comments

This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
This got it for me. Def check this out if you're using NGNIX from an angular app. Even if it "worked" previously
This is valid answer.
This was also my problem. This fixed it.
2

I encountered the same issue recently in Angular 18 hosted on Cloudflare. The fix was to create a headers file with the following:

/*.js
   Content-Type: application/javascript

The _headers file should be part of the Angular build files.

Comments

1

you can run ng build --base-href=/subdomain/ or you can also add to angular.json

"architect": {
    "build": {
      "builder": "@angular-devkit/build-angular:browser",
      "options": {
        "outputPath": "dist/",
        "index": "src/index.html",
        "baseHref": "/subdomain/",
        ......
      } }

Comments

0

when you host angular projects on virtual directory, you need to add:

 APP_BASE_HREF, useValue: '/YOUR VIRTUAL DIRECTORY NAME'

to "app.module.ts" in "NgModule" section. like this:

import { APP_BASE_HREF } from '@angular/common';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    NgbModule
  ],
  providers: [{provide: APP_BASE_HREF, useValue: '/YOUR_VIRTUALDIRECTORY_NAME'}],
  bootstrap: [AppComponent]
})

and rebuild your project.

don't forget to use:

import { APP_BASE_HREF } from '@angular/common';

you can see about this, on https://angular.io/api/common/APP_BASE_HREF

and finally run:

ng build --base-href  YOUR_VIRTUAL_DIRECTORY_NAME

have a good time!

Comments

0

I commented out <base href="/"> from index.html and my app displays on the server.

And I changed the outputPath in angular.json to not include the subdomain: "outputPath": "dist",.

I also changed the public setting in firebase.json to include the subdomain: "public": "dist/en-US",.

Why the different settings in angular.json and firebase.json? Before these changes, I had angular.json set to "outputPath": "dist/language-two13",. The result was that ng build transpiled my Angular project into dist/language-two13/en-US. By changing this setting I got rid of one subdomain.

In the browser neither subdomain appeared in the URL.

Where the en-US subdomain is coming from I have no idea. I'm using Transloco for i18n but searching through transloco-root.module.ts I see en and es as the languages of my project, not en-US. I searched my entire app and found only a few instances of en-US, only in code that corrects this to en, and never in settings that would affect the transpiler.

I tried switching the default language of Transloco from en to es. Nada cambios...no changes.

I tried commenting out Transloco in app.module.ts but Angular won't compile.

I tried moving my files from dist/en-US/ to dist, removing the en-US folder, changing firebase.json to "public": "dist", and commenting <base href="/"> back into index.html, and deploying to Firebase Hosting. This works fine.

In conclusion, angular.json is set to transpile without a subdomain, but the en-US subdomain is magically getting inserted, so I set firebase.json to correct for this weird behavior.

My hat is off to dev-ops professionals who deal with this stuff all day!

Comments

0

In my case it was actually my mistake. I looked for the file runtime.[random-numbers].js which was highlighted in the error

Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.

I could not find it. I realised I had not updated the list of files in FileZilla after I built my Angular app (the file names had changed since Angular randomises the file names)

I hope this saves someone some time :)

Comments

0

If using AWS amplify make sure you add the extension to the rewrite list

</^[^.]+$|.(?!(css|gif|ico|jpg|js|png|txt|svg|woff|woff2|ttf|map|json|html|xlsx|mjs|webmanifest|properties)$)([^.]+$)/>

enter image description here

Comments

0

I am also face this issue sometime in my vite project. Disabling browser cache solves the issue

Comments

0

I faced this error in a static site deployment to Cloudflare Pages (aka Workers and Pages).

What ultimately worked was to simply add a 404.html file in the site's root. From the Pages docs:

If your project does not include a top-level 404.html file, Pages assumes that you are deploying a single-page application. This includes frameworks like React, Vue, and Angular. Pages' default single-page application behavior matches all incoming paths to the root (/), allowing you to capture URLs like /about or /help and respond to them from within your SPA.

Comments

0

I also run into this issue, and the root cause for my issue was the automatically generated early hints by Cloudflare Pages.

Some of the chunk files were loaded in the index.html. Cloudflare checks the scripts in the .html and generates early hints for browsers so these files can be preloaded to the link header. Like this:

link <https://fonts.gstatic.com>; rel="preconnect", <chunk-5SZKM2SH.js>; rel="modulepreload", <chunk-HMTLAR2O.js>; ....

It works well as long as you open the site on the root path (/), but if you open the website on a non-root path (e.g. /auth/login), the browser will try to preload the chunk files relative to this path (/auth/login/chunk.js instead of /chunk.js). Angular responds with a 404 page with text/html response for these requests. It results in the Expected a JavaScript module script but the server responded with a MIME type of "text/html" error.

By the way, my site worked correctly as Angular downloaded the chunk files later from the correct location too, but I had some ugly error messages in the console and in our error feed because of these preloads.

My solution was to disable early hint generation in the _headers file: https://developers.cloudflare.com/pages/configuration/early-hints/#disable-automatic-link-header-generation-automatic-link-header

/*
  ! Link

Side note: my index.html starts with this: <base href="/">. I haven’t tried it, but maybe changing this to the actually deployed site’s domain could work as well.

I wrote about this on CF community too: https://community.cloudflare.com/t/angular-chunk-load-error-wrong-mime-type/837476

Comments

-1

In index.html write: script type="javascript" src="../src/index.jsx"(you're local path) This will help solve this problem in my case

1 Comment

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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.