ES6 modules in local files - The server responded with a non-JavaScript MIME type
Asked Answered
S

12

61

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.

Sarasvati answered 21/11, 2017 at 0:44 Comment(6)
You need to set up a local HTTP server. Using file: URLs is never a good idea because it fails to behave like a real page would.Unlicensed
The end users receive the page packed with webpack. But for me, it's most comfortable to test with files. I can start python or node.js server, I just don't wanna.Mod
Actually, I just tried and.. you are not facing this same-origin restriction. It's just like the error message states: they do a strict check against js MIME type, your filesystem doesn't provide any.Spieler
Well then the question is how to disable that check for local files, right?Mod
I don't suppose you ever got a workable answer for this? I'd love to have a workaround.Kampong
bugs.chromium.org/p/chromium/issues/detail?id=824651 - a corresponding issue on the issue trackerBeagle
S
23

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.

Spieler answered 21/11, 2017 at 1:29 Comment(4)
This doesn't really help but kudos for the workaround. Can come in handy in other situations...Mod
@TomášZato note that it might be possible through chrome scripts (extension) to force the MIME in such cases, using the webRequest API, but I don't know it enough to show exactly how to procede...Spieler
What if you are running this on a local server, and still getting this issue?Fransis
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 policyStrohben
C
55

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';

Castillo answered 21/2, 2018 at 20:54 Comment(9)
Wow. Yup. Right here. Makes sense, too, because this explicitly tells it what type the import module isSuperincumbent
@Superincumbent yeah it made sense in hindsight but I was going out of my mind trying to figure it out.Castillo
Haha I'm glad you found it before I stumbled upon the same issue :pSuperincumbent
JayGould great!, I was going crazy about nothing, saying this way it's understandable. @Superincumbent that makes sense to me, Genius!,Canaan
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).Daylong
@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!Castillo
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.Woolfell
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.Step
@Tom this occurs with unbundled code, if you're running babel/webpack omitting the .js will give the same functionality as including it.Castillo
S
23

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.

Spieler answered 21/11, 2017 at 1:29 Comment(4)
This doesn't really help but kudos for the workaround. Can come in handy in other situations...Mod
@TomášZato note that it might be possible through chrome scripts (extension) to force the MIME in such cases, using the webRequest API, but I don't know it enough to show exactly how to procede...Spieler
What if you are running this on a local server, and still getting this issue?Fransis
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 policyStrohben
U
7

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.

Unlicensed answered 21/11, 2017 at 0:51 Comment(3)
I was asking about possible development flags/options to enable me test the files without a server.Mod
I don't believe you have any option other than to run a server.Unlicensed
I'm running python's SimpleHTTPServer. Why isn't this sufficient?Earthwork
F
6

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.

Foggy answered 5/9, 2019 at 4:6 Comment(0)
H
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>
Haematic answered 11/1, 2018 at 22:55 Comment(0)
U
3

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

Uird answered 19/1, 2020 at 12:53 Comment(0)
B
2

The issue I had that caused this for me was I am using embedding React into an existing site and was calling my main.jsx. When you call a script with .jsx and embedding React, you need to set your type to "text/babel".

eg - <script type="text/babel" src="./src/main.jsx"></script>

This link is useful if you are embedding react - https://reactjs.org/docs/add-react-to-a-website.html#optional-try-react-with-jsx

Bragg answered 15/12, 2022 at 6:6 Comment(0)
M
2

Depending upon your server environment (for me, this worked on Ubuntu 18.04 using Apache - don't know about other systems), another solution is to update your /etc/mime.types file, replacing the following line:

application/javascript       js

with

application/javascript       js mjs

Be sure to restart your web server after updating the file.

Mcdougald answered 13/8, 2023 at 21:6 Comment(0)
J
0

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

AddType aplication/javascript .js

I hope this helps.

Jaban answered 28/6, 2020 at 18:58 Comment(0)
E
0

If you're using React, it probably means you haven't built your project yet. React sites aren't native JS and need to be built and deployed.

you probably have a script command called "deploy" in your package.json. If you don't, watch this tutorial: https://youtu.be/Q9n2mLqXFpU

then in command prompt or a terminal, run

npm run deploy

it'll build your project and then deploy it to the gh-pages branch of your github repository. Note: if there's any compile errors, it won't work, and you'll have to fix the compile errors and then build it again.

after you build and deploy, you might run into an error involving 404 errors. if you do, this answer on this github issue might help you: https://github.com/tschaub/gh-pages/issues/285#issuecomment-1556076504

Eubank answered 21/5, 2023 at 11:22 Comment(0)
C
0

This occurred in my case in ngx-extended-pdf-viewer library for which I added the setting on my server which is nginx.

Here is the Link to the solution.

Note: This is not a Backend server or not a frontend appissue. This is related to the server on which the App is deployed.

Cicely answered 6/5 at 11:12 Comment(1)
Please add an excerpt of the linked content to your answer. Links tend to die eventually and your answer would then become worthless.Mod
P
0

Firstly don't used files, use a server or just a docker container for development and test. I had this happen on shared hosting and I just added:

AddType application/javascript .mjs

To the .htaccess and bingo it works. Just an unrecognised MIME type, nothing complicated (unless you're loading files.....).

Pulse answered 15/5 at 0:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.