浏览器接受“经典”js脚本标记,但不接受ES6模块 - 带有Node http服务器的MIME错误

问题描述 投票:0回答:2

我想使用ES6模块,所以我决定使用Node作为一个简单的Web服务器,以避免我在本地执行时遇到的所有与CORS相关的错误。现在我在浏览器中遇到了MIME类型相关的错误,我无法理解。

这是我的server.js文件:

const http = require('http'),
      url  = require('url'),
      fs   = require('fs');

http.createServer((req, res) => {

  const q = url.parse(req.url, true),
        filename = "." + q.pathname;

  fs.readFile(filename, (err, data) => {
    if (err) {
      res.writeHead(404, {'Content-Type': 'text/html'});
      return res.end("404 Not Found");
    }  
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write(data);
    return res.end();
  });

}).listen(8080);

如果我尝试在浏览器中访问我的index.html文件,其中包含以下代码:

<!DOCTYPE html>
<html>
<body> 

  <!-- Works -->
  <script src="index.js"></script>

  <!-- Doesn't work -->
  <script src="module.js" type="module"></script>

</body>
</html>

我收到以下错误:

无法加载模块脚本:服务器使用非JavaScript MIME类型“text / html”进行响应。

type="text/javascript"属性也不会影响模块标记。我已经读过默认情况下所有ES6模块都是“延迟”的,这意味着它们在完全解析HTML之前不会执行。我想这是问题,但我不知道如何相应地修改我的server.js文件来修复它。非常感谢帮助!如果不是太不切实际,我宁愿不拉入任何NPM包。

编辑:我认为,因为我访问http://localhost:8080/index.html发送类型为text/html的标头是正确的。但是,如果我console.log(url.parse(req.url, true));我现在看到延迟脚本标签触发createServer回调。显式记录的对象显示它是JS模块的文件名。

一旦我修复了错误的标题,我会回来一个有效的例子。

解决方案:我引入了两个额外的模块;路径和哑剧。我在mime.getType()返回的路径的扩展上使用了url.parse()

const http = require('http'),
      url  = require('url'),
      fs   = require('fs'),
      mime = require('mime'),
      path = require('path');

http.createServer((req, res) => {

  const q = url.parse(req.url, true),
        filename = "." + q.pathname;

  fs.readFile(filename, (err, data) => {
    if (err) {
      res.writeHead(404, {'Content-Type': 'text/html'});
      return res.end("404 Not Found");
    }  
    res.writeHead(200, {'Content-Type': mime.getType(path.extname(filename))});
    res.write(data);
    return res.end();
  });

}).listen(8080);
node.js http mime-types es6-modules
2个回答
1
投票
res.writeHead(200, {'Content-Type': 'text/html'});

这表明每个文件都使用text/html mimetype。


1
投票

当浏览器请求你的模块时,你发回一个Content-Type: text/html标题 - 这是无效的,as per the HTML spec

如果满足以下任何条件,则抛出“NetworkError”DOMException:

  • 响应的类型是“error
  • 响应的状态不是正常状态
  • 从响应的标头列表中提取MIME类型的结果不是JavaScript MIME类型

据我所知,'经典'脚本没有这个限制。

为了解决这个问题,您需要使用适当的MIME类型(例如text/javascript)从服务器发回JavaScript模块:

res.writeHead(200, {'Content-Type': 'text/javascript'});

我建议使用像Express这样的东西,而不是直接使用http模块,但是 - you can get a lot of this functionality out of the box,我相信它会为你设置标题。

© www.soinside.com 2019 - 2024. All rights reserved.