解决 pdf.mjs 因 MIME 类型错误导致的模块加载失败问题

Mozilla PDF.js V4 开始,它官方分发确实只提供了 ESM 模块(.mjs),没有以前的 pdf.js、pdf.worker.js UMD 版本了。

这个问题本质上是 浏览器要求以 application/javascript MIME 类型加载 ES Module ,而你引入的 pdf.mjs 文件服务器返回的 Content-Type 不是标准的 JS MIME(通常是 text/html 或者 text/plain),所以会报:

复制代码
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html"

先介绍一下.mjs文件

什么是 .mjs 文件?

.mjs(Module JavaScript)是 ECMAScript 模块的专用文件扩展名,用于明确标识 JavaScript 模块文件。这是 ES6 模块系统的标准扩展名。

与普通 .js 文件的主要区别

特性 .mjs 文件 传统 .js 文件
模块类型 ES6 模块 传统脚本或 CommonJS 模块
严格模式 默认启用 需要手动启用
顶层 this undefined 指向全局对象
导入/导出 支持 import/export 需要特定环境支持
文件识别 明确标识为模块 需要解析内容判断

.mjs 文件的核心特性

1. 明确的模块标识

javascript 复制代码
// math.mjs
export const add = (a, b) => a + b;
export const multiply = (a, b) => a * b;

// 默认导出
export default function calculator() {
  console.log('Calculator module loaded');
}

2. 导入语法

javascript 复制代码
// app.mjs
import calculator, { add, multiply } from './math.mjs';

console.log(add(2, 3)); // 输出: 5
console.log(multiply(2, 3)); // 输出: 6
calculator(); // 输出: Calculator module loaded

3. 动态导入

javascript 复制代码
// 动态导入示例
const loadModule = async () => {
  const module = await import('./dynamic-module.mjs');
  module.doSomething();
};

为什么使用 .mjs 扩展名?

优势:

  1. 明确性:一眼就能识别出是 ES6 模块
  2. 兼容性:避免与 CommonJS 模块混淆
  3. 工具支持:构建工具和运行时能够正确识别模块类型
  4. 服务器配置:便于正确设置 MIME 类型

环境支持

支持的运行时:

  1. Node.js (v12+ 完全支持)
  2. 现代浏览器 (Chrome、Firefox、Safari、Edge)
  3. Deno (原生支持)
  4. Bun (原生支持)

Node.js 中的使用:

javascript 复制代码
// package.json 配置
{
  "type": "module", // 或者使用 .mjs 扩展名
  "scripts": {
    "start": "node src/index.mjs"
  }
}

回归正题

常见解决方案:

1. 确认服务器返回的 MIME 类型

在服务端配置里,确保 .mjs 文件返回:

复制代码
Content-Type: application/javascript
  • Nginx 配置:
nginx 复制代码
http {
    types {
        application/javascript  mjs;
    }
}
  • Apache 配置:
apache 复制代码
AddType application/javascript .mjs

2. 如果你不能改服务器配置
  • pdf.mjs 改名为 .js,然后在 HTML 中这样引入:
html 复制代码
<script type="module" src="/path/to/pdf.js"></script>

因为大多数服务器对 .js 都会返回正确的 application/javascript


3. 使用构建工具打包

如果你项目里有 Webpack / Vite / Rollup,把 pdf.mjs 作为依赖打包进去,这样最终生成的都是标准 JS 文件,不会受 MIME 类型影响。


4. 确认引入方式

要用 ES Module 的方式加载:

html 复制代码
<script type="module">
  import * as pdfjsLib from '/path/to/pdf.mjs';
  // ...
</script>

  1. 如果是 uniapp 下使用 npm i pdfjs-dist 安装的 pdfjs,引入方式如下:
javascript 复制代码
import * as pdfjsLib from "pdfjs-dist";
import pdfjsWorker from "pdfjs-dist/build/pdf.worker?url";
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;
  1. 如果是官网下载的zip包,引入方式如下:
javascript 复制代码
import * as pdfjsLib from "@/static/pdf.mjs";

const worker = new Worker(new URL("@/static/pdf.worker.mjs", import.meta.url), { type: "module" });
pdfjsLib.GlobalWorkerOptions.workerPort = worker;

由于我使用的是docker,直接用 cat 命令无法编辑mime.types文件(页也可以自行安装 vim 命令)。

这里介绍一下 docker cp 命令。

  • 从宿主机复制文件到容器
bash 复制代码
docker cp ./hello.txt nginx_container:/hello.txt
  • 从容器复制文件到宿主机:
bash 复制代码
docker cp nginx_container:/hello.txt ./hello.txt
  • 修改后需要重启nginx
bash 复制代码
docker exec nginx_container nginx -s reload

验证

bash 复制代码
curl -I https://your-domain.com/file.mjs

返回

bash 复制代码
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 26 Aug 2025 10:51:28 GMT
Content-Type: application/javascript; charset=utf-8,gbk
Content-Length: 1887718
Connection: keep-alive
Last-Modified: Tue, 26 Aug 2025 03:14:02 GMT
ETag: "68ad267a-1ccde6"
Accept-Ranges: bytes

至此,访问pdfjs 正常了!😃

相关推荐
Bling_Bling_14 小时前
ES6新语法特性(第二篇)
开发语言·前端·es6
上单带刀不带妹5 天前
ES6 中的 Proxy 全面讲解
前端·ecmascript·es6·proxy
liuyang___6 天前
es6新语法
前端·javascript·es6
Orange3015118 天前
《深入源码理解webpack构建流程》
前端·javascript·webpack·typescript·node.js·es6
gzzeason8 天前
ES6+内置进制转换方法
前端·ecmascript·es6
哈哈哈hhhhhh17 天前
JavaScript进阶ES6
javascript·es6
Zz_waiting.17 天前
Javaweb - 14.1 - 前端工程化
前端·es6
htt232120 天前
前端记录项目中用到的js
前端·ecmascript·es6
Warren9822 天前
Java异常讲解
java·开发语言·前端·javascript·vue.js·ecmascript·es6