52

I get this error:

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

The project is run from local files, eg.: file:///D:/path/project.html.

Works without problems in Firefox, but doesn't work in Google Chrome. I want to test it this way for development purposes - it's more comfortable than creating a server and remembering what port is it on.

sideshowbarker
  • 72,859
  • 23
  • 167
  • 174

7 Answers7

45

A simple fix for me that wasn't listed here was this:

I had an import statement bringing an object from a different file, which I did via this line:

import { Cell } from './modules/Cell';

What broke the code and caused the MIME type error was not having .js appended to the end of ./modules/Cell.

The updated line fixed my problem:

import { Cell } from './modules/Cell.js';

James Gould
  • 4,111
  • 2
  • 24
  • 45
  • Wow. Yup. Right here. Makes sense, too, because this explicitly tells it what type the import module is – Jona Jun 30 '18 at 22:03
  • 1
    @Jona yeah it made sense in hindsight but I was going out of my mind trying to figure it out. – James Gould Jul 01 '18 at 09:56
  • 1
    Haha I'm glad you found it before I stumbled upon the same issue :p – Jona Jul 01 '18 at 11:05
  • JayGould great!, I was going crazy about nothing, saying this way it's understandable. @Jona that makes sense to me, Genius!, – Karla Danitza Duran Memijes Sep 20 '18 at 05:24
  • Thankfully the browser console gave me a helpful error message so I didn't need to spend an hour finding this solution. Not! BTW, I'm using an HTTP server (Python2). – Tom Russell Jan 11 '19 at 07:49
  • @TomRussell yup, did exactly the same when I posted this answer. Worst part is that it was for a timed take-home test for an interview! – James Gould Jan 14 '19 at 07:47
  • I am really new to this however I think you should be using this solution with care in case of npm modules since you essentially create a coupling from the importing module not to the module but also the name and path of the js file instead of just the module name. I suppose that webpack etc as bundlers take care of resolving this amongst other things, but as said am new and may be wrong. – TomFree Jun 03 '19 at 15:03
  • What worked for me was similar, but instead changing the `.mjs` extension I had to `.js`. I was following tutorials or writeups about modules and they use `.mjs` so not sure what that's about there. – Daniel Jackson Jul 01 '19 at 14:32
  • @Tom this occurs with unbundled code, if you're running babel/webpack omitting the .js will give the same functionality as including it. – James Gould Jul 02 '19 at 17:00
21

If you got onto this error message, it means that it's not a Same-origin issue.

As said in the error message, the real problem is that modules scripts require the MIME of your script file to be one of the javascript MIME types.

Your filesystem doesn't provide any MIME, hence the loading fails.

So the best solution is obviously to run your code on a local server, and not on the filesystem.

But since you do insist ;) One workaround is to first fetch your script file as Blob using XHR (fetch can't be used on file:// protocol), then force its type property to be one of js MIMEs, and set your <script>'s src to a blobURI poiting to this Blob.

// requires to start chrome with the --allow-file-access-from-file flag
var xhr = new XMLHttpRequest();
xhr.onload = e => {
    let blob = xhr.response;
    blob.type = 'application/javascript'; // force the MIME
    moduleScript.src = URL.createObjectURL(blob);
};
xhr.open('get', "yourmodule.js");
xhr.responseType = 'blob';
xhr.send();

BUT, you won't be able to import any dependencies from within your module.

Kaiido
  • 103,356
  • 8
  • 183
  • 231
  • 4
    This doesn't really help but kudos for the workaround. Can come in handy in other situations... – Tomáš Zato - Reinstate Monica Nov 21 '17 at 01:32
  • 1
    @TomášZato note that it might be possible through *chrome* scripts (extension) to force the MIME in such cases, using the [webRequest API](https://developer.chrome.com/extensions/webRequest), but I don't know it enough to show exactly how to procede... – Kaiido Nov 21 '17 at 01:47
  • 3
    What if you are running this on a local server, and still getting this issue? – SeanMC Jan 27 '19 at 16:57
  • 1
    I have a module with zero imports in it, so this should work. But it still fails to load the script because of CORS policy: `Access to XMLHttpRequest at 'file:///Users/test.js' from origin 'null' has been blocked by CORS policy` – Jespertheend Feb 04 '20 at 19:44
5

ES6 module files are loaded using the standard Same-Origin policy restrictions that browsers enforce and have many other security restrictions in place, while JavaScript "script" files have much more lax security to avoid breaking existing websites as better security standards have been added to browsers over time. You are hitting one of them, which is that files must be sent with the correct MIME type.

file:// URLs are not normal HTTP requests, and as such they have different rules around requests. There's also pretty much no rules for what MIME type should be sent. If you want to use ES6 modules then you need to be running a real HTTP server locally to serve your files.

loganfsmyth
  • 146,797
  • 27
  • 317
  • 241
5

On Windows, i cannot get ES 2016 modules to load correctly. Even if you disable security, then you get hit by the next prolem which is the .js files don't have a MIME type set, so you get a message like Failed to load module script: The server responded with a non-JavaScript MIME type of "". Strict MIME type checking is enforced for module scripts per HTML spec.

The answer is to use Safari on the macintosh, which allows local files no problem with ES 2016 modules. Interestingly both Chrome and Firefox also fail to work properly. Frankly this is a bug, because when you are loading a local file, there is absolutely nothing insecure about accessing files from the same folder. But good luck getting Google or Firefox to fix this. Apple even has a flag about cross-scripting permissions in their pulldown menu, so they know how important it is to disable nonsense security stuff.

Edward De Jong
  • 121
  • 1
  • 8
3

You can set the ModuleSpecifier to a data URI

<script type="module">
  import {Test} from "data:application/javascript,const%20Mod={this.abc=123};export%20{Mod};";
  console.log(Test);
</script>

to set the ModuleSpecifier programmatically you can launch Chromium/Chrome with --allow-file-access-from-files flag and utilize XMLHttpRequest() to request a JavaScript file from file: protocol

<script>
(async() => {

  const requestModule = ({url, dataURL = true}) => 
    new Promise((resolve, reject) => {
      const request = new XMLHttpRequest();
      const reader = new FileReader();
      reader.onload = () => { resolve(reader.result) };
      request.open("GET", url);
      request.responseType = "blob";
      request.onload = () => { reader[dataURL ? "readAsDataURL" : "readAsText"](request.response) };
      request.send();
   })

  let moduleName = `Mod`;
  // get `Mod` module
  let moduleRequest = await requestModule({url:"exports.js"});
  // do stuff with `Mod`; e.g., `console.log(Mod)`
  let moduleBody = await requestModule({url:"ModBody.js", dataURL: false}); 
  let scriptModule = `import {${moduleName}} from "${moduleRequest}"; ${moduleBody}`;
  let script = document.createElement("script");
  script.type = "module";
  script.textContent = scriptModule;
  document.body.appendChild(script);

})();
</script>
guest271314
  • 1
  • 12
  • 91
  • 170
2

I solved the same problem adding this line to apache mime types file configuration:

AddType aplication/javascript .js

I hope this helps.

tHeSiD
  • 3,616
  • 3
  • 25
  • 42
0

If the files don't end up with ".js" but ".mjs" try changing them to ".js"

And also if you didn't specify the file type, specify it: ./modules/Cell to ./modules/Cell.js

E_net4 - Krabbe mit Hüten
  • 24,143
  • 12
  • 85
  • 121
Poussy
  • 65
  • 4