web-dev-qa-db-fra.com

Modules ES6 dans des fichiers locaux - Le serveur a répondu avec un type MIME non-JavaScript

Je reçois cette erreur:

Échec du chargement du script de module: le serveur a répondu avec un type MIME non-JavaScript de "". La vérification de type MIME stricte est appliquée pour les scripts de module selon les spécifications HTML.

Le projet est exécuté à partir de fichiers locaux, par exemple: file:///D:/path/project.html.

Fonctionne sans problème dans Firefox, mais pas dans Google Chrome. Je souhaite le tester de cette manière à des fins de développement: il est plus pratique que de créer un serveur et de se rappeler sur quel port il est.

16
Tomáš Zato

Si vous recevez ce message d'erreur, cela signifie qu'il ne s'agit pas d'un problème de même origine.

Comme indiqué dans le message d'erreur, le vrai problème est que les scripts de modules exigent que le MIME de votre fichier de script soit l'un des types MIME javascript.

Votre système de fichiers ne fournit aucun MIME, par conséquent le chargement échoue.

La meilleure solution consiste donc évidemment à exécuter votre code sur un serveur local et non sur le système de fichiers.

Mais puisque vous insistez;) Une solution de contournement consiste à extraire d'abord votre fichier script en tant que Blob à l'aide de XHR (fetch ne peut pas être utilisé sur le protocole file://), puis forcer sa propriété type à être l'un des MIME de js, puis définir votre <script> 's src à un blobURI pointant vers ce 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();

MAIS, vous ne pourrez pas import aucune dépendance à partir de votre module.

5
Kaiido

Une solution simple pour moi qui ne figurait pas ici était la suivante:

J'avais une déclaration d'importation rapportant un objet d'un fichier différent, ce que j'ai fait via cette ligne:

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

Ce qui a cassé le code et a causé l'erreur de type MIME, c'est que .js ne soit pas ajouté à la fin de ./modules/Cell

La ligne mise à jour a résolu mon problème:

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

11
Jay Gould

Les fichiers du module ES6 sont chargés à l'aide des restrictions règles standard de même origine que les navigateurs appliquent et appliquent de nombreuses autres restrictions de sécurité, tandis que les fichiers "script" JavaScript disposent d'une sécurité beaucoup plus laxiste pour ne pas endommager les sites Web existants des normes ont été ajoutées aux navigateurs au fil du temps. Vous en frappez un, c'est-à-dire que les fichiers doivent être envoyés avec le type MIME approprié.

file:// Les URL ne sont pas des requêtes HTTP normales et, en tant que telles, elles ont des règles différentes autour des requêtes. Il n’existe pas non plus de règle sur le type de MIME à envoyer. Si vous souhaitez utiliser les modules ES6, vous devez exécuter un véritable serveur HTTP localement pour servir vos fichiers.

3
loganfsmyth

Vous pouvez définir la ModuleSpecifier sur un data URI

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

pour définir ModuleSpecifier par programme, vous pouvez lancer Chromium/Chrome avec l'indicateur --allow-file-access-from-files et utiliser XMLHttpRequest() pour demander un fichier JavaScript à partir du protocole 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>
1
guest271314