代码之家  ›  专栏  ›  技术社区  ›  Audun Olsen

浏览器接受“classic”JS脚本标记,但不接受ES6模块的mime错误w/node http server

  •  0
  • Audun Olsen  · 技术社区  · 7 年前

    我想使用ES6模块,所以我决定使用节点作为简单的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>
    

    我得到以下错误:

    加载模块脚本失败:服务器用 “text/html”的非javascript mime类型。

    这个 type="text/javascript" 属性对module标记也没有影响。我已经了解到,所有ES6模块在默认情况下都是“延迟的”,这意味着它们不会在HTML完全解析之前执行。我想这是问题所在,但我不知道如何修改我的 服务器,JS 相应地归档以修复它。非常感谢您的帮助!如果不是太不实际,我宁愿不拉任何新产品经理包。

    编辑: 我想自从我进入 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);
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Evert    7 年前
    res.writeHead(200, {'Content-Type': 'text/html'});
    

    这意味着每个文件都有一个 text/html MIMETYPE,

        2
  •  1
  •   Joe Clay    7 年前

    你要寄回 Content-Type: text/html 头当浏览器请求您的模块时-这是无效的, as per the HTML spec

    < Buff行情>

    如果满足以下任一条件,则引发“NetworkError”domException:。

    • 响应 的类型是“ error
    • 响应 的状态不是OK状态
    • 从响应的头列表中提取mime类型的结果不是javascript mime类型
    < /块引用>

    据我所知,“经典”脚本没有这种限制。

    为了解决这个问题,您需要使用适当的mime类型从服务器发送您的javascript模块,例如 text/javascript

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

    我建议您使用Express之类的工具,而不是直接使用 http 不过,模块- you can get a lot of this functionality out of the box ,我相信它可以为您设置标题。

    推荐文章