You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在纯JS+HTML项目中集成FullCalendar库时遭遇MIME类型加载错误的问题求助

在纯JS+HTML项目中集成FullCalendar库时遭遇MIME类型加载错误的问题求助

我正尝试把fullcalendar.io库集成到一个纯JavaScript+HTML项目里,但这个简单的应用却难住了我。我遇到的错误如下:

Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "application/octet-stream". Strict MIME type checking is enforced for module scripts per HTML spec.

Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.


我已经尝试过的解决办法

一开始我以为是路径问题——毕竟我是动态导入的库,可能对它和它的依赖处理、导入得不够充分,我还从纯JS切换到了page.js插件,但情况没有任何改变。

然后我觉得可能是Web服务器配置的问题,我先是用了Express.js(本来觉得它简洁,很适合我的场景),折腾了半天还是没解决,又换成了Nginx,但错误信息还是没变。不过有时候会出现导入错误,我觉得这可能是我把项目搞乱导致的。

其他尝试的操作:

  • 清除浏览器缓存
  • 把fullcalendar相关文件移到不同的文件夹,甚至直接放到根目录
  • 在不同浏览器(火狐/Chrome)中测试,但在Postman里能正常显示日历
  • 在另一个环境(不带Web服务器的纯HTML+JS)中使用fullcalendar,结果是可以正常运行的

之前使用的Express服务器代码

import express from 'express';
import { join, dirname } from 'path';
import path from 'path';
import history from 'connect-history-api-fallback';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const app = express();
const port = 8888;

app.use(express.static(join(__dirname, 'public'), {
  setHeaders: (res, filePath) => {
    if (filePath.endsWith('.js') || filePath.endsWith('.mjs')) {
      res.setHeader('Content-Type', 'application/javascript');
    }
    
    if (filePath.endsWith('.html')) {
      res.setHeader('Content-Type', 'text/html');
    }
  }
}));

app.use(history({index: 'index.html'}));
app.use(express.static(join(__dirname, 'src')));
app.use(express.static(join(__dirname, 'src/views')));
app.use(express.static(join(__dirname, 'src/views/make_appointment')));
app.use(express.static(join(__dirname, 'src/views/appointments')));
app.use(express.static(join(__dirname, 'src/views/users')));
app.use('/node_modules', express.static(path.join(__dirname, 'node_modules')));


app.listen(port, () => {
    console.log(`Server is running on http://localhost:${port}`);
});

后来切换到的Nginx配置

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;

    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen 8888;
        server_name localhost;

        root I:/pet-appointment/Project-fe/src/;
        index index.html;

        location / {
            try_files $uri /index.html;
        }

        # Serve HTML views
        location /calendar {
            try_files /views/calendar.html /index.html;
        }
        
        types { application/javascript js mjs; }


        # Serve .js files with the correct MIME type
        location ~* \.js$ {
            default_type application/javascript;
            add_header Content-Type application/javascript;
        }

        location /node_modules/ {
            root I:/pet-appointment/Project-fe;
            add_header Content-Type application/javascript;
            autoindex on;
        }


        location ~* \.(js|css|json|ico|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|otf|mp4|webm|ogv|ogg)$ {
            add_header Access-Control-Allow-Origin *;
        }
    }
}

项目结构(仅展示必要文件)

Project/src/views:

  • calendar.html
  • calendar.js

Project/src:

  • index.html
  • navigation_bar.mjs(作为组件在每个页面使用,我没试过去掉它,但觉得这不是问题根源)

Calendar.html

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>FullCalendar Test</title>
    <script src="./calendar.js"></script>
    <!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/6.1.8/index.global.min.css" /> -->
</head>

<body>
    <div id="calendar"></div>
</body>

</html>

Calendar.js

import { Calendar } from '/node_modules/@fullcalendar/core';
import interactionPlugin from '/node_modules/@fullcalendar/interaction';
import dayGridPlugin from '/node_modules/@fullcalendar/daygrid';
import timeGridPlugin from '/node_modules/@fullcalendar/timegrid';
import listPlugin from '/node_modules/@fullcalendar/list';

document.addEventListener('DOMContentLoaded', function() {
    var calendarEl = document.getElementById('calendar');
  
    var calendar = new Calendar(calendarEl, {
      plugins: [ interactionPlugin, dayGridPlugin, timeGridPlugin, listPlugin ],
      headerToolbar: {
        left: 'prev,next today',
        center: 'title',
        right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
      },
      initialDate: '2018-01-12',
      navLinks: true, // can click day/week names to navigate views
      editable: true,
      dayMaxEvents: true, // allow "more" link when too many events
      events: [
        {
          title: 'All Day Event',
          start: '2018-01-01',
        },
        {
          title: 'Long Event',
          start: '2018-01-07',
          end: '2018-01-10'
        },
        {
          groupId: 999,
          title: 'Repeating Event',
          start: '2018-01-09T16:00:00'
        },
        {
          groupId: 999,
          title: 'Repeating Event',
          start: '2018-01-16T16:00:00'
        },
        {
          title: 'Conference',
          start: '2018-01-11',
          end: '2018-01-13'
        },
        {
          title: 'Meeting',
          start: '2018-01-12T10:30:00',
          end: '2018-01-12T12:30:00'
        },
        {
          title: 'Lunch',
          start: '2018-01-12T12:00:00'
        },
        {
          title: 'Meeting',
          start: '2018-01-12T14:30:00'
        },
        {
          title: 'Happy Hour',
          start: '2018-01-12T17:30:00'
        },
        {
          title: 'Dinner',
          start: '2018-01-12T20:00:00'
        },
        {
          title: 'Birthday Party',
          start: '2018-01-13T07:00:00'
        },
        {
          title: 'Click for Google',
          url: 'http://google.com/',
          start: '2018-01-28'
        }
      ]
    });
  
    calendar.render();
  });

Index.html

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

<head>
  <title>Appointments</title>
  <!-- <script src="/router.js"></script> -->

  <link rel="stylesheet" href="/style.css">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="/navigation-bar.mjs" type="text/javascript" defer></script>

  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
  integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
    integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
    crossorigin="anonymous"></script>
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
    integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
    crossorigin="anonymous"></script>
  <link rel="stylesheet" type="text/css" href="/progress_bar.css">
  <!-- <script src="script.js"></script> -->
</head>

<body>
  <header-component></header-component>

  <div id="app"></div>

</body>

</html>

<style>
.bd-placeholder-img {
      font-size: 1.125rem;
      text-anchor: middle;
      -webkit-user-select: none;
      -moz-user-select: none;
      user-select: none;
    }

    @media (min-width: 768px) {
      .bd-placeholder-img-lg {
        font-size: 3.5rem;
      }
    }
  .pt-8 {
    padding-top: 8px;
  }

  .center {
    text-align: center;
  }

  .container {
    width: fit-content;
    margin: auto;
  }

  .border {
    border: 1px solid black;
  }

  .success {
    color: green;
  }

  .error {
    color: red;
  }

  
</style>

Package.json

{"name": "pet-frontend",
  "version": "1.0.0",
  "description": "A JavaScript project",
  "type": "module",
  "main": "./dist/index.js",
  "scripts": {
    "start": "node server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@fullcalendar/core": "^6.1.8",
    "@fullcalendar/daygrid": "^6.1.8",
    "@fullcalendar/interaction": "^6.1.8",
    "@fullcalendar/list": "^6.1.8",
    "@fullcalendar/timegrid": "^6.1.8",
    "connect-history-api-fallback": "^2.0.0",
    "express": "^4.18.2"
  }
}

备注:内容来源于stack exchange,提问作者nokecmec

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 18:58:09