浏览器接受 "classic" js script-tag,但不接受 ES6 模块——MIME 错误 w/Node http 服务器
Browser accepts "classic" js script-tag, but not ES6 modules — MIME error w/ Node http server
我想玩 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>
我收到以下错误:
Failed to load module script: The server responded with a
non-JavaScript MIME type of "text/html".
type="text/javascript"
属性对模块标签也没有影响。我读到所有 ES6 模块默认都是 "deferred",这意味着它们在 HTML 完全解析之前不会执行。我想这就是问题所在,但我不知道如何相应地修改我的 server.js
文件来修复它。非常感谢您的帮助!如果不是太不切实际,我宁愿不引入任何 NPM 包。
编辑: 我认为自从我访问了 http://localhost:8080/index.html
之后发送类型为 text/html
的 header 是正确的。但是如果我 console.log(url.parse(req.url, true));
我现在看到延迟脚本标签触发 createServer
回调。 object 记录明确显示它是 JS 模块的文件名。
一旦我修复了错误 header,我会带着一个工作示例回来。
解决方案: 我引入了两个附加模块;路径和 mime。我在 url.parse()
.
返回的路径的扩展名上使用了 mime.getType()
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);
res.writeHead(200, {'Content-Type': 'text/html'});
这表明每个文件都带有 text/html
mimetype。
当浏览器请求您的模块时,您将发回 Content-Type: text/html
header - 这是无效的,as per the HTML spec:
If any of the following conditions are met, throw a "NetworkError" DOMException:
- response's type is "
error
"
- response's status is not an ok status
- The result of extracting a MIME type from response's header list is not a JavaScript MIME type
'Classic' 脚本没有这个限制,据我所知。
为了解决这个问题,您需要使用适当的 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,我相信它会处理设置 headers你.
我想玩 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>
我收到以下错误:
Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html".
type="text/javascript"
属性对模块标签也没有影响。我读到所有 ES6 模块默认都是 "deferred",这意味着它们在 HTML 完全解析之前不会执行。我想这就是问题所在,但我不知道如何相应地修改我的 server.js
文件来修复它。非常感谢您的帮助!如果不是太不切实际,我宁愿不引入任何 NPM 包。
编辑: 我认为自从我访问了 http://localhost:8080/index.html
之后发送类型为 text/html
的 header 是正确的。但是如果我 console.log(url.parse(req.url, true));
我现在看到延迟脚本标签触发 createServer
回调。 object 记录明确显示它是 JS 模块的文件名。
一旦我修复了错误 header,我会带着一个工作示例回来。
解决方案: 我引入了两个附加模块;路径和 mime。我在 url.parse()
.
mime.getType()
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);
res.writeHead(200, {'Content-Type': 'text/html'});
这表明每个文件都带有 text/html
mimetype。
当浏览器请求您的模块时,您将发回 Content-Type: text/html
header - 这是无效的,as per the HTML spec:
If any of the following conditions are met, throw a "NetworkError" DOMException:
- response's type is "
error
"- response's status is not an ok status
- The result of extracting a MIME type from response's header list is not a JavaScript MIME type
'Classic' 脚本没有这个限制,据我所知。
为了解决这个问题,您需要使用适当的 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,我相信它会处理设置 headers你.