【问题标题】:ES6 modules in local files - The server responded with a non-JavaScript MIME type本地文件中的 ES6 模块 - 服务器以非 JavaScript MIME 类型响应
【发布时间】:2018-05-04 08:22:26
【问题描述】:

我收到此错误:

加载模块脚本失败:服务器以非 JavaScript MIME 类型“”响应。根据 HTML 规范对模块脚本强制执行严格的 MIME 类型检查。

项目从本地文件运行,例如:file:///D:/path/project.html

在 Firefox 中运行没有问题,但在 Google Chrome 中无法运行。我想以这种方式测试它以用于开发目的 - 它比创建服务器并记住它在哪个端口上更舒服。

【问题讨论】:

  • 您需要设置一个本地HTTP服务器。使用 file: URL 从来都不是一个好主意,因为它无法像真实页面那样运行。
  • 最终用户会收到使用 webpack 打包的页面。但对我来说,用文件进行测试是最舒服的。我可以启动 python 或 node.js 服务器,我只是不想。
  • 其实,我刚刚试过,而且..你没有面临这个同源限制。就像错误消息指出的那样:他们对 js MIME 类型进行了严格检查,您的文件系统没有提供任何内容。
  • 那么问题是如何禁用对本地文件的检查,对吧?
  • 我认为您对此没有一个可行的答案?我很想有一个解决方法。

标签: javascript google-chrome ecmascript-6


【解决方案1】:

将这一行添加到 apache mime types 文件配置中,我解决了同样的问题:

AddType aplication/javascript .js

我希望这会有所帮助。

【讨论】:

    【解决方案2】:

    如果文件结尾不是“.js”而是“.mjs”,请尝试将它们更改为“.js”

    如果您没有指定文件类型,请指定它:./modules/Cell./modules/Cell.js

    【讨论】:

      【解决方案3】:

      在 Windows 上,我无法正确加载 ES 2016 模块。即使您禁用了安全性,您也会遇到下一个问题,即 .js 文件没有设置 MIME 类型,因此您会收到一条消息,例如 Failed to load module script: The server respond with a non-JavaScript MIME类型 ””。根据 HTML 规范对模块脚本强制执行严格的 MIME 类型检查。

      答案是在 macintosh 上使用 Safari,它允许本地文件使用 ES 2016 模块没有问题。有趣的是,Chrome 和 Firefox 也无法正常工作。坦率地说,这是一个错误,因为当您加载本地文件时,从同一个文件夹访问文件绝对没有什么不安全的。但祝你好运让谷歌或火狐来解决这个问题。 Apple 甚至在他们的下拉菜单中有一个关于跨脚本权限的标志,所以他们知道禁用无意义的安全内容是多么重要。

      【讨论】:

        【解决方案4】:

        这里没有列出的一个简单的解决方法是:

        我有一个 import 语句从另一个文件中引入一个对象,我通过这一行做到了:

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

        破坏代码并导致 MIME 类型错误的原因是没有将 .js 附加到 ./modules/Cell 的末尾。

        更新后的行解决了我的问题:

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

        【讨论】:

        • 哇。对。就在这儿。也有道理,因为这明确告诉它导入模块是什么类型
        • @Jona 是的,事后看来这是有道理的,但我想弄清楚。
        • 哈哈,很高兴你在我偶然发现同样的问题之前找到了它:p
        • JayGould 太棒了!我什么都没有发疯,这样说是可以理解的。 @Jona 这对我来说很有意义,天才!,
        • 谢天谢地,浏览器控制台给了我一个有用的错误消息,所以我不需要花一个小时来寻找这个解决方案。不是!顺便说一句,我使用的是 HTTP 服务器(Python2)。
        【解决方案5】:

        您可以将ModuleSpecifier 设置为data URI

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

        要以编程方式设置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>
        

        【讨论】:

          【解决方案6】:

          ES6 模块文件是使用浏览器强制执行的standard Same-Origin policy 限制加载的,并且存在许多其他安全限制,而 JavaScript“脚本”文件具有更宽松的安全性,以避免破坏现有网站,因为已经添加了更好的安全标准浏览器随着时间的推移。您遇到了其中之一,即必须使用正确的 MIME 类型发送文件。

          file:// URL 不是普通的 HTTP 请求,因此它们对请求有不同的规则。对于应该发送什么 MIME 类型也几乎没有规则。如果你想使用 ES6 模块,那么你需要在本地运行一个真正的 HTTP 服务器来提供你的文件。

          【讨论】:

          • 我在询问可能的开发标志/选项,以使我能够在没有服务器的情况下测试文件。
          • 我不相信你除了运行服务器之外别无选择。
          • 我正在运行 python 的 SimpleHTTPServer。为什么这还不够?
          【解决方案7】:

          如果您收到此错误消息,则表示这不是同源问题。

          正如错误消息中所说,真正的问题是模块脚本要求脚本文件的 MIME 是 javascript MIME 类型之一。

          您的文件系统没有提供任何 MIME,因此加载失败。

          所以最好的解决方案显然是在本地服务器上运行您的代码,而不是在文件系统上。

          但既然你坚持;) 一种解决方法是首先使用 XHR 将脚本文件作为 Blob 获取(fetch 不能用于 file:// 协议),然后强制其 @ 987654324@ 属性为 js MIME 之一,并将您的 &lt;script&gt; 的 src 设置为指向此 Blob 的 blobURI。

          // 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();
          

          但是,您将无法 import 模块内的任何依赖项。

          【讨论】:

          • 这并没有真正帮助,但对解决方法表示赞赏。可以在其他情况下派上用场...
          • @TomášZato 请注意,在这种情况下,可以通过 chrome 脚本(扩展)强制 MIME 使用 webRequest API,但我不知道足以说明如何进行……
          • 如果您在本地服务器上运行此程序,但仍遇到此问题怎么办?
          • 我有一个模块中的导入为零,所以这应该可以工作。但由于 CORS 策略,它仍然无法加载脚本:Access to XMLHttpRequest at 'file:///Users/test.js' from origin 'null' has been blocked by CORS policy
          猜你喜欢
          • 2019-11-08
          • 2020-05-11
          • 2021-06-05
          • 2021-04-11
          • 2023-04-01
          • 2021-03-07
          • 2021-01-26
          • 2019-11-18
          相关资源
          最近更新 更多