Angular: After upgrading to Angular 8, production builds can't load: 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.

Created on 4 Jun 2019  ·  123Comments  ·  Source: angular/angular

🐞 bug report

Affected Package Angular 8

Is this a regression? YES

Description

My production distribution is being served from Azure Blob Storage static site. Is it possible that serving from the static site is causing this error?

This issue happens in Chrome but not Edge.

After upgrading to Angular 8, production builds can't load. Browser console error: 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.

🔬 Minimal Reproduction

Upgrade an Angular 7 app to Angular 8. Do production build, deploy the production build to Azure Blob storage static web site and attempt to open it.

🔥 Exception or Error


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.


🌍 Your Environment

Angular Version:




Angular CLI: 8.0.1
Node: 11.6.0
OS: win32 x64
Angular: 8.0.0
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.800.1
@angular-devkit/build-angular     0.800.1
@angular-devkit/build-optimizer   0.800.1
@angular-devkit/build-webpack     0.800.1
@angular-devkit/core              8.0.1
@angular-devkit/schematics        8.0.1
@angular/cdk                      7.3.7
@angular/cli                      8.0.1
@angular/material                 7.3.7
@ngtools/webpack                  8.0.1
@schematics/angular               8.0.1
@schematics/update                0.800.1
rxjs                              6.5.2
typescript                        3.4.5
webpack                           4.30.0
core docs devrel confusing

Most helpful comment

You must change the property "target" in the file "tsconfig.json" to "es5". Read this blog entry, "Differential Loading by Default":

https://blog.angular.io/version-8-of-angular-smaller-bundles-cli-apis-and-alignment-with-the-ecosystem-af0261112a27

This property chooses between modern or legacy JavaScript based on the browser capabilities:

<script type="module" src="…"> // Modern JS

<script nomodule src="…"> // Legacy JS

All 123 comments

@kdawg1406 sounds like a server issue to me. What happens if you serve a production build yourself locally? I bet that works.

@spock123 thank you for your remarks. I'll try this in the morning.

Check that you are trying to load correct filenames. You are simply getting a 404 from backend and the browser cant load the 404 page as JS as a

I am not so sure this should be closed or sent off to Stack Overflow just yet.
You can reproduce this problem with a brand new version 8.02 "hello world" app generated from the CLI.
The exact same version 7 app has always worked just fine and still does up on Azure storage.
So, since there is not really anything we can do to reconfigure Azure Storege, what can we do to get Version 8 apps running up there? Something has changed that broke this capability and free hosting is a pretty good reason to use Angular. :)

Version 8 apps Do work fine on a "real" web server though.

Thanks!

@Aurora7Sys

I found the source of the problem. Angular 8 removed -- type="text/javascript" from the script tags in index.html. Angular 7 had them which is why it worked with Azure Storage.

We also discovered that the Azure portal manual upload did not add the MIME metadata to .js files that were uploaded. So... when I manually uploaded my Angular 8 site, it produced the above errors.

I started using Visual Studio Code to publish my Angular 8 apps to Azure Storage and it's working because the publish extension adds the correct MIME metadata to the files.

Microsoft will look into correcting the Azure portal manual upload to add the MIME metadata so this can't happen on their server.

Thanks for the update @kdawg1406.
I was going to start digging from index.html out, but this saves a lot of time!!

Same problem here, and no obvious fix still? Prod build uploaded to Github Pages does not work too.

@lion9 does my above solution not work for you? How are you publishing your app to the server? I used VS Code and it solved my problem.

@lion9 does my above solution not work for you? How are you publishing your app to the server? I used VS Code and it solved my problem.

I tried to upload it to Github Pages, no luck. It seems that it does not matter, which tool I am using - Webstorm or VS Code - it won't work :-( See here - https://lion9.github.io/test/

@lion9 understand. Full disclosure, my solution worked for me because the VS Code Extension that performs the upload to the Azure Blob Storage applied the correct metadata to the .js files.

Angular 8 does publish the .js files differently. If you compare an Angular 7 index.html with the Angular 8 index.html the scripts at the bottom of the file are different. Angular 7 .js files have the type="text/javascript" where the Angular 8 index.html script files do not add this.

Angular 7
<script type="text/javascript" src="runtime.26209474bfa8dc87a77c.js"></script>

I believe this is the root of the problem, Recommend contacting GitHub and ask them how you can apply the required metadata to the files.

Maybe you can try and add the type="text/javascript" to the script tags that don't have a type attribute? If I remember correctly half of the files have the attribute, the others don't.

Best regards, Karl

This issue is posted on Stack Overflow , but no resolution yet, thanks!

I got the same problem when I host the files on AWS S3. The problem is from the "type='module'", I had to manually change it into "type='text/javascript'" to make it work again.

Why "type='module'" in Angular 8, I'm wondering? What is the benefit of it over "type='text/javascript'" ?

@Erayus I think it has something to do with getting a modern browser to load the file instead of the other version of the file.

I would reach out to the Angular team, you may be causing a problem.

The server metadata needs to be applied to the files, and they will load correctly.

I do think Angular needs much better docs and testing to explain to developers how to deploy Angular 8 apps.

@kdawg1406 Thank you very much!

try browerslist

Same issue when packaging with Electron, seems to be resolved by setting type="text/javascript" instead of type="module".

You must change the property "target" in the file "tsconfig.json" to "es5". Read this blog entry, "Differential Loading by Default":

https://blog.angular.io/version-8-of-angular-smaller-bundles-cli-apis-and-alignment-with-the-ecosystem-af0261112a27

This property chooses between modern or legacy JavaScript based on the browser capabilities:

<script type="module" src="…"> // Modern JS

<script nomodule src="…"> // Legacy JS

@btey I don't see anything in the link you provided that suggested target should be es5. Instead the example there shows es2015 (which is es6).

I solved it by creating a task in gulp, I share the steps:

1) npm install --save-dev gulp
2) npm install --save-dev gulp-replace
3) create in the root of the project a file with the name:
gulpfile.js
4) copy the code in the _gulpfile.js_:

const { src, dest } = require('gulp');
var replace = require('gulp-replace')

exports.default = function (cb) {    
    src(['dist/ng-project/index.html'])
        .pipe(replace('type="module"', 'type="text/javascript"'))
        .pipe(dest('dist/ng-project/'));
    cb();
};

5) In the packaje.json file, modify the _"electron"_ script as follows:
"electron": "ng build --base-href ./ && tsc --p electron && gulp && electron ."
6) run your project: npm run electron

note: In the main electron file, make sure you go to the dist folder of your index.html file
_Ejemplo:_

win.loadURL(url.format({
        pathname: path.join(__dirname, `/../../dist/ng-project/index.html`),
        protocol: "file:",
        slashes: true
        })
    );

That is a webserver related problem. Angular 7 did include a MIME type in the tags in index.html:
<script type="text/javascript" src="runtime.26209474bfa8dc87a77c.js">

Angular 8 does not include a MIME type in

Same issue, It's seems like ng8 issue and not something that can be fixed on the node side

While this only treats the symptom, you can opt out of differential loading to buy you some time to deal with the problem.

We use ADO build pipelines to drop files into blob storage running static website and fronted with a CDN, so I may be looking at just running a custom post-copy PS script again like in the earlier days to apply correct mime types.

+1

Still no solution to this problem??

Still no solution to this problem??

the easy solution
just replace target with es5 in tsconfig,json

"target": "es5",

This issue affects anyone using Cordova, as Cordova ultimately serves up files via the file:// protocol. I can't change my "server" to serve up the js files as text/javascript afaik as there _is_ no server. There's an issue on Cordova's github, but I don't know that it's anything the Cordova team can resolve.

Does anyone know if there's any support for the file:// with javascript modules?

I use a c++ webserver derived from https://github.com/eidheim/Simple-Web-Server . You can easily create a fast c++ REST server with this, which will serve your angular client. When you request a file it just sends the file. No processing. So if there is no MIME metadata in the file, it will not add it. I don't understand why this issue is closed. Adding the MIME metadata seems simple enough. And if it is inconvenient there should be an option.

NGINX configuration was failing even with mime types loaded from /etc/nginx/mime.types.

Eventually after some digging, removing one option at a time, I managed to trace the option that was causing the MIME types errors I was getting in the console. Commented it out and viola content was displayed fine.

`
# This option cause issues with Angular served applications
#          add_header X-Content-Type-Options nosniff;
`

Hope it helps someone

I have same problem, does anyone help me, please, thank you very much

btey had the fix for building with electron. Change the target in tsconfig.json to es5. Thanks btey

Thanks Kdawg! type='module' is really bizarre, AWS S3 hosting won't work with Opera and Chrome (V8 indigestion haha). Thanks, Easy fix to get All fixed up!!

Change type in index.html

i solved this in tsconfig.json
change target to es5 and module to commonjs

Ex:
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"module": "commonjs",
"moduleResolution": "node",
"importHelpers": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
]
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
}
}

Changing the target to ES5 is not a solution, it is a workaround. It means the typescript compiler can't use modern javascript features and will have to emulate them. I fix it by changing the generated index.html and add the mime type. Not a lot of work but a nuisance.

The clever gulp solution to fix the index.html