2

I would like to serve an Angular 8 app with a simple Nginx server. Unfortunately, when I try to serve the app I receive the following error in Chrome:

Failed to load module script: The server responded with a non-JavaScript MIME type of "text/plain". Strict MIME type checking is enforced for module scripts per HTML spec.

I found several solutions (this and that for instance) suggesting I should manually configure all script tags and add type="javascript". However, in my case I cannot do this because my app contains Web Components that can only be loaded when the script type attribute is type="module".

My Nginx configuration looks like this:

events { worker_connections 1024; }

http
{
    sendfile on;

    server {
        root /usr/share/nginx/html/app;
        listen 9020;
        server_name  localhost;

        location / {
            index  index.html index.htm;
        }

        location ~ \.css {
            add_header  Content-Type    text/css;
        }

        location ~ \.js {
            add_header  Content-Type    application/javascript;
        }
    }
}

Do you know how I can configure either Angular or Nginx to serve javascript files (included by script tags in the index.html) which are of type "module"?

Thank you in advance.

SparkFountain
  • 2,110
  • 15
  • 35

2 Answers2

7

You should serve javascript which has a type="module" with mime type text/javascript as stated here:

.js files need to be loaded with a MIME-type of text/javascript (or another JavaScript-compatible MIME-type, but text/javascript is recommended), otherwise you'll get a strict MIME type checking error like "The server responded with a non-JavaScript MIME type".

That aside, your SPA config for nginx is not correct as it never reaches the .js location statement. You should add a try_files statement:

server {
    root /usr/share/nginx/html/app;
    listen 9020;
    server_name  localhost;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location ~* ^.+\.css$ {
        default_type text/css;
    }

    location ~* ^.+\.js$ {
        default_type text/javascript;
    }
}
Poul Kruijt
  • 69,713
  • 12
  • 145
  • 149
  • 1
    Thank you for the `try_files` hint! However, the JS files still cannot be recognized and the browser error **The server responded with a non-JavaScript MIME type of "text/plain"** remains... – SparkFountain Feb 12 '20 at 10:15
  • 1
    @SparkFountain I've updated my answer using `default_type` – Poul Kruijt Feb 12 '20 at 10:42
4

Contrary to my assumption, I found that it doesn't make a difference whether I write <script type="module"> or script type="text/javascript" in my index.html.

However, I simply forgot the part text/ in the MIME type declaration, thus the files could not be resolved correctly. My bad. Now the correct solution to this problem is to replace all MIME types module by text/javascript.

The actual problem only seems to occur with Angular 8 and has been discussed since June 2019 in this GitHub bug report. Another solution based on my tech stack (Angular 8 + Nginx) would be to explictly declare a MIME type association in Nginx for module scripts like this:

http {
    types {
      module js;
    }
    include       /etc/nginx/mime.types;
    # rest of your config...
}

(see https://github.com/angular/angular/issues/30835#issuecomment-583943657)

SparkFountain
  • 2,110
  • 15
  • 35