解决 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 正常了!😃

相关推荐
Beginner x_u4 天前
ES6 中的 class 是什么?和ES5构造函数差别是什么?
javascript·es6·class
麻辣翅尖5 天前
【vue】基于 pdf.js 实现 pdf 文件预览
vue.js·pdf.js
好学且牛逼的马6 天前
ES6 核心语法精讲
前端·ecmascript·es6
辰风沐阳6 天前
ES6 新特性: 解构赋值
前端·javascript·es6
得一录8 天前
ES6核心语法
前端·ecmascript·es6
利刃大大14 天前
【ES6】变量与常量 && 模板字符串 && 对象 && 解构赋值 && 箭头函数 && 数组 && 扩展运算符 && Promise/Await/Async
开发语言·前端·javascript·es6
天若有情67314 天前
ES6 模块与 CommonJS 的区别详解
前端·javascript·es6
wangbing112515 天前
ES6 (ES2015)新增的集合对象Set
前端·javascript·es6
yyt36304584116 天前
TypeScript { [key: string]: unknown } 索引签名写法和 Record 替代
前端·javascript·vue.js·typescript·ecmascript·es6
梦65016 天前
JavaScript ES5 + ES6+ 字符串 (String) 所有方法大全
前端·javascript·es6