本地文件中的 ES6 模块 - 服务器以非 JavaScript MIME 类型响应
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47403478/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ES6 modules in local files - The server responded with a non-JavaScript MIME type
提问by Tomá? Zato - Reinstate Monica
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.
加载模块脚本失败:服务器响应非 JavaScript MIME 类型“”。每个 HTML 规范对模块脚本执行严格的 MIME 类型检查。
The project is run from local files, eg.: file:///D:/path/project.html.
该项目从本地文件运行,例如: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.
在 Firefox 中没有问题,但在 Google Chrome 中不起作用。我想以这种方式进行测试以用于开发目的 - 它比创建服务器并记住它在哪个端口上更舒适。
采纳答案by Kaiido
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.
正如错误消息中所说,真正的问题是模块脚本要求脚本文件的 MIME 是 javascript MIME 类型之一。
Your filesystem doesn't provide any MIME, hence the loading fails.
您的文件系统不提供任何 MIME,因此加载失败。
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 (fetchcan't be used on file://protocol), then force its typeproperty to be one of js MIMEs, and set your <script>'s src to a blobURI poiting to this Blob.
但既然你坚持;)一种解决方法是首先使用 XHR 将你的脚本文件作为 Blob 获取(fetch不能用于file://协议),然后强制其type属性成为 js MIME 之一,并将你<script>的 src 设置为 blobURI指向这个 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 importany dependencies from within your module.
但是,您将无法import从您的模块中获得任何依赖项。
回答by Jay Gould
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';
import { Cell } from './modules/Cell';
What broke the code and caused the MIME type error was not having .jsappended to the end of ./modules/Cell.
破坏代码并导致 MIME 类型错误的原因不是没有.js附加到./modules/Cell.
The updated line fixed my problem:
更新后的行解决了我的问题:
import { Cell } from './modules/Cell.js';
import { Cell } from './modules/Cell.js';
回答by loganfsmyth
ES6 module files are loaded using the standard Same-Origin policyrestrictions 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.
ES6 模块文件使用浏览器强制执行的标准同源策略限制加载,并具有许多其他安全限制,而 JavaScript“脚本”文件具有更宽松的安全性,以避免破坏现有网站,因为浏览器已添加更好的安全标准随着时间的推移。您正在点击其中之一,即必须使用正确的 MIME 类型发送文件。
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.
file://URL 不是普通的 HTTP 请求,因此它们对请求有不同的规则。对于应该发送什么 MIME 类型也几乎没有规则。如果你想使用 ES6 模块,那么你需要在本地运行一个真正的 HTTP 服务器来为你的文件提供服务。
回答by guest271314
You can set the ModuleSpecifierto a data URI
您可以设置ModuleSpecifier为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 ModuleSpecifierprogrammatically you can launch Chromium/Chrome with --allow-file-access-from-filesflag and utilize XMLHttpRequest()to request a JavaScript file from file:protocol
要以ModuleSpecifier编程方式设置,您可以使用--allow-file-access-from-files标志启动 Chromium/Chrome并利用XMLHttpRequest()从file:协议请求 JavaScript 文件
<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>
回答by Edward De Jong
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.
在 Windows 上,我无法正确加载 ES 2016 模块。即使您禁用了安全性,您也会遇到下一个问题,即 .js 文件没有设置 MIME 类型,因此您会收到类似 Failed to load module script: The server responded with a non-JavaScript MIME 这样的消息类型 ””。每个 HTML 规范对模块脚本执行严格的 MIME 类型检查。
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.
答案是在macintosh上使用Safari,它允许本地文件与ES 2016模块没有问题。有趣的是,Chrome 和 Firefox 也无法正常工作。坦率地说,这是一个错误,因为当您加载本地文件时,从同一文件夹访问文件绝对没有任何不安全的地方。但祝 Google 或 Firefox 能够解决这个问题。Apple 甚至在他们的下拉菜单中有一个关于跨脚本权限的标志,所以他们知道禁用无意义的安全内容是多么重要。
回答by Poussy
If the files don't end up with ".js" but ".mjs" try changing them to ".js"
如果文件结尾不是“.js”而是“.mjs”,请尝试将它们更改为“.js”
And also if you didn't specify the file type, specify it: ./modules/Cellto ./modules/Cell.js
而如果你还没有指定的文件类型,指定它:./modules/Cell以./modules/Cell.js

