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

相关推荐
叫我一声阿雷吧2 天前
JS 入门通关手册(23):JS 异步编程:回调函数与异步本质
javascript·es6·前端面试·回调函数·回调地狱·js异步编程·异步本质
小李子呢02116 天前
JS中的Set 核心认知
前端·javascript·es6
默默学前端6 天前
ES6模板语法与字符串处理详解
前端·ecmascript·es6
-杨豫7 天前
JavaScript入门到精通全套资料,以及核心进阶ES6语法,API,js高级等基础知识和实战教程
开发语言·javascript·es6
前端小D7 天前
ES6 中的 Promise
前端·javascript·es6·promise
Pu_Nine_912 天前
深入理解 ES6 Map 数据结构:从理论到实战应用
前端·javascript·数据结构·es6
程序员小李白12 天前
ES6详细解析
前端·ecmascript·es6
追光少年33221 个月前
React学习:ES6
学习·react.js·es6
weixin_531651811 个月前
ES6 Proxy 的基本用法
前端·ecmascript·es6
前端 贾公子1 个月前
npm库的打包原理与实践详解 (下)
前端·javascript·node.js·github·es6