Модули ES6 в локальных файлах. Сервер ответил несимметричным MIME-типом

Я получаю эту ошибку:

Не удалось загрузить модуль script: сервер ответил несимметричным MIME-типом "". Строгая проверка типа MIME применяется для скриптов модуля для спецификации HTML.

Проект запускается из локальных файлов, например.: file:///D:/path/project.html.

Работает без проблем в Firefox, но не работает в Google Chrome. Я хочу протестировать его таким образом для целей разработки - он более удобен, чем создание сервера и запоминание того, какой порт он включен.

Ответ 1

Если вы попали в это сообщение об ошибке, это означает, что это не проблема с тем же выпуском.

Как сказано в сообщении об ошибке, реальная проблема заключается в том, что для сценариев модулей требуется, чтобы MIME вашего файла script был одним из типов MIME javascript.

Ваша файловая система не предоставляет MIME, поэтому загрузка не выполняется.

Таким образом, лучшим решением является, очевидно, запуск вашего кода на локальном сервере, а не в файловой системе.

Но так как вы настаиваете;) Один способ обхода - сначала извлечь ваш файл script, так как Blob с использованием XHR (fetch не может использоваться в протоколе file://), а затем заставить его свойство type один из jM 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();

НО, вы не сможете import от любых зависимостей внутри вашего модуля.

Ответ 2

Простое исправление для меня, которое не было перечислено здесь, было следующим:

У меня был оператор импорта, в котором был добавлен объект из другого файла, который я сделал по этой строке:

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

Что нарушило код и вызвало ошибку типа MIME, не было добавлено .js к концу ./modules/Cell.

Обновленная строка исправила мою проблему:

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

Ответ 3

Вы можете установить 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 вы можете запустить Chromium/Chrome с флагом --allow-file-access-from-files и использовать XMLHttpRequest() для запроса файла JavaScript из протокола file:

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

Ответ 4

Файлы модуля ES6 загружаются с помощью стандартной политики Same-Origin, которую браузеры применяют и имеют множество других ограничений безопасности, в то время как JavaScript Файлы "script" имеют гораздо более слабую защиту, чтобы не нарушать существующие веб-сайты, поскольку с течением времени браузеры были добавлены в браузеры. Вы ударяете один из них, то есть файлы должны быть отправлены с правильным типом MIME.

file:// URL-адреса не являются нормальными HTTP-запросами, и поэтому они имеют разные правила вокруг запросов. Там также практически нет правил для того, какой тип MIME должен быть отправлен. Если вы хотите использовать модули ES6, вам необходимо запустить настоящий HTTP-сервер локально, чтобы обслуживать ваши файлы.

Ответ 5

В Windows я не могу заставить модули ES 2016 загружаться правильно. Даже если вы отключите безопасность, вы столкнетесь со следующей проблемой: для файлов .js не задан тип MIME, поэтому вы получите сообщение типа Не удалось загрузить скрипт модуля: сервер ответил не MIME без JavaScript тип "". Строгая проверка типов MIME применяется для скриптов модулей в соответствии со спецификацией HTML.

Ответ заключается в использовании Safari на компьютере Macintosh, что позволяет локальным файлам без проблем работать с модулями ES 2016. Интересно, что и Chrome, и Firefox также не работают должным образом. Честно говоря, это ошибка, потому что при загрузке локального файла нет абсолютно ничего небезопасного при доступе к файлам из той же папки. Но удачи в Google или Firefox, чтобы это исправить. У Apple даже есть флаг о разрешениях кросс-скриптинга в их выпадающем меню, поэтому они знают, как важно отключить бессмысленные функции безопасности.