Express 错误:根据 HTML 规范对模块脚本强制执行严格的 MIME 类型检查

Posted

技术标签:

【中文标题】Express 错误:根据 HTML 规范对模块脚本强制执行严格的 MIME 类型检查【英文标题】:Express error: Strict MIME type checking is enforced for module scripts per HTML spec 【发布时间】:2021-12-09 03:35:02 【问题描述】:

我正在尝试通过 express 构建一个简单的单页应用程序。

在我开始创建类之前一切正常,然后浏览器抛出以下错误:

加载模块脚本失败:需要一个 javascript 模块脚本,但服务器以“text/html”的 MIME 类型响应。根据 HTML 规范对模块脚本强制执行严格的 MIME 类型检查。

我希望express.static() 能够消除这种情况,但事实并非如此。 我对 JS、Node 和所有这些方面还不是很熟练,所以我为这里的愚蠢表示歉意。

目前我的代码很简单:

文件架构:

-server.js
-[frontend]
+-[static]
++-index.html
++-[js]
+++-index.js
+++-[views]
++++-AbstractView.js
++++-Home.js
-[node_modules]
-package.json

server.js

const express = require('express');
const path = require('path');

const App = express()

App.use('/static', express.static(path.resolve(__dirname, 'frontend', 'static')))
App.get('/*', (req, res) => 
    res.sendFile(path.resolve(__dirname, "frontend", "index.html"))
)
App.listen(3000, () => console.log("server running on port 3000"))

index.js:

import Home from "./views/Home"

const navigateTo = url => 
    history.pushState(null, null, url)
    router()


const router = async() => 
    const routes = [
                path: '/',
                view: new Home()
            ,
            // 
            //     path: '/projects',
            //     view: () => console.log('projects')
            // ,
            // 
            //     path: '/about',
            //     view: () => console.log('about')
            // ,
            // 
            //     path: '/studies',
            //     view: () => console.log('studies')
            // ,
        ]
        // test routes for matches
    const potentialMatches = routes.map(route => 
        return 
            route: route,
            isMatch: location.pathname === route.path
        
    )

    /**
     * NEED TO SET 404 PAGE!
     */
    let match = potentialMatches.find(potentialMatch => potentialMatch.isMatch)
    if (!match) 
        match = 
            route: routes[0],
            isMatch: true
        
    

    const view = new match.route.view()
    const content = document.querySelector("#app")
    content.innerHTML = await view.getHtml()
    console.log(content);


window.addEventListener("popstate", router);

document.addEventListener("DOMContentLoaded", () => 
    document.body.addEventListener("click", e => 
        if (e.target.matches("[data-link")) 
            e.preventDefault()
            navigateTo(e.target.href)
        
    )
    router()
)

Home 类(扩展和 AbstractView 通用类):

import AbstractView from "./AbstractView";

export default class Home extends AbstractView 
    constructor() 
        super()
        this.setTitle("Home")
    
    setTitle(title) 
        document.title = title
    

    async getHtml() 
        return `<h1>Home</h1>`;
    

泛型类:

export default class AbstractView 
    constructor() 

    
    setTitle(title) 
        document.title = title
    

    async getHtml() 
        return "";
    

当然是index.html文件:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Paolo Iocca</title>
</head>

<body>
    <div class="menu" id="menu">
        <span class="menu__line"></span>
        <span class="menu__line"></span>
        <span class="menu__line"></span>
    </div>
    <aside class="aside">
        <nav class="nav">
            <ul class="nav__list">
                <li class="nav__list__item">
                    <a href="/" class="nav__list__item__link" data-link>home </a>
                </li>
                <li class="nav__list__item">
                    <a href="/projects" class="nav__list__item__link" data-link>projects</a
            >
          </li>
          <li class="nav__list__item">
            <a href="/about" class="nav__list__item__link" data-link>about </a>
                </li>
                <li class="nav__list__item">
                    <a href="/studies" class="nav__list__item__link" data-link>studies
            </a>
                </li>
            </ul>
        </nav>
    </aside>
    <div id="app"></div>
    <script type="module" src="/static/js/index.js"></script>
</body>

</html>

希望你能帮我解决这个问题。非常感谢。

_____ 更新

这是 package.json 文件,以防万一:


    "dependencies": 
        "express": "^4.17.1"
    ,
    "name": "boilerplate-server",
    "version": "1.0.0",
    "main": "server.js",
    "devDependencies": 
        "nodemon": "^2.0.14",
        "serve-static": "^1.14.1"
    ,
    "scripts": 
        "dev": "nodemon server",
        "start": "node server.js"
    ,
    "keywords": [],
    "author": "",
    "license": "ISC",
    "description": ""

【问题讨论】:

我认为某处存在导入问题,例如,我会查看here。 如果静态中间件没有为其中一个类找到.js 文件,则下一个中间件将接管并返回index.html 文件。这可以解释 MIME 类型错误。但是您的文件列表包含所有需要的文件。嗯,你能在浏览器的网络选项卡中发现text/html.js 请求的响应吗? @HeikoTheißen - 网络显示所有需要的文件:一个“文档”类型的 localhost 和两个脚本 index.js 和 Home.js - 所有这些文件的状态均为 200OK。抛出的错误引用将我指向 html 文件的第一行。至少我知道express.static() 行工作正常... @YH 感谢您指出我的方向。我已经对此进行了测试:创建了一个/static/css/style.css,对正文背景颜色进行了简单的更改。它工作正常,所以它绝对与提到的问题无关。脚本到达目的地,它们只是没有应用应有的更改并引发内容类型错误。 【参考方案1】:

声明

import Home from "./views/Home"

导致GET /static/js/views/Home 请求(没有 .js 后缀),static 中间件无法服务。但是现在下一个中间件接管并使用index.html 文件(使用Content-Type: text/html)进行响应。这就是为什么您会看到 200 OK 状态,但浏览器抱怨内容类型错误。

express.static(path.resolve(__dirname, 'frontend', 'static'),
  extensions: ["js"]);

您将指示static 中间件静默添加.js 后缀。

【讨论】:

这很有效,也很有启发性。非常感谢,谢谢! 对于内置节点http模块使用request.setHeader('Content-Type', 'text/javascript');

以上是关于Express 错误:根据 HTML 规范对模块脚本强制执行严格的 MIME 类型检查的主要内容,如果未能解决你的问题,请参考以下文章

无法加载模块脚本 - 在 index.html 中导入类

对express中引入文件时提示Error: Cannot find module错误的理解

模块化开发

PCB模块化设计04——USB-Type-C PCB布局布线设计规范

出现错误,错误:npm install 后找不到模块“express”

node.js,错误:找不到模块'express'