背景
由于之前是找到了pdfjs-dist
的2.7.570
版本可适配我的vue2
项目,可以不用更改webpack
、babel
配置,但这样做效率太低了,要是之后还有类似的情况,该怎么办,要是那个依赖没有es5
的产物,那不就完了
所以我的解决办法是自己打包一个适合我的产物
技术选型
这里采用的是babel+rollup
可选打包工具列表
工具 | 是否适合打包成 UMD/ES5 | 特点概述 |
---|---|---|
Rollup | ✅ 非常适合 | 小巧、输出干净,擅长库打包(推荐) |
Webpack | ✅ 可配置实现 | 功能强大,适合复杂项目,配置略繁琐 |
esbuild | ❌ 不直接支持 UMD | 极快,适合现代构建,但不适合你的需求(UMD + ES5 ) |
Vite | ❌ 不适合库打包(默认) | 开发体验极佳,适合 Vue/React 应用构建,不适合你这个 use case |
rspack | ✅ 理论可用 | Webpack 替代者(快 + 支持新标准),但生态较新 |
Parcel | ✅ 支持 | 开箱即用,适合简单项目,但可控性较差 |
microbundle | ✅ 基于 Rollup 简封装 | 超轻量打包 UMD/ESM/CJS,零配置 |
各工具比较
需求 | Rollup | Webpack | microbundle | Parcel |
---|---|---|---|---|
打包为浏览器 <script> 可用 |
✅ | ✅ | ✅ | ✅ |
支持转换 pdfjs-dist (ESM)为 UMD |
✅ | ✅ | ✅ | ❌ 复杂 |
可输出 ES5 代码 | ✅ | ✅ | ✅ | ❌ 不稳定 |
配置难度 | 中 | 高 | 低 | 最低 |
输出大小优化 | ✅ 极好 | 中 | ✅ | ❌ 较差 |
具体实施
拷贝pdfjs-dist
- 项目初始化:
npm init -y
- 下载
pdfjs-dist
:npm install pdfjsd-dist --save
- 新建
lib
文件夹 - 拷贝
node_modules
里的pdfjs-dist
的build
产物到lib
文件夹

babel.config.js
- 下载:
npm install --save-dev @babel/core @babel/cli @babel/preset-env
- 创建文件:
babel.config.js
javascript
// babel.config.js
module.exports = {
presets: [
['@babel/preset-env', {
targets: {
ie: '11',
},
modules: 'auto', // 可设置为 false 保留 ES 模块
}]
]
};
rollup.config.js
- 下载:
npm install --save-dev rollup rollup-plugin-babel rollup-plugin-node-resolve
- 创建文件:
rollup.config.js
javascript
import resolve from "rollup-plugin-node-resolve";
import babel from "rollup-plugin-babel";
export default [
{
input: "lib/pdfjs-dist/build/pdf.mjs",
output: {
file: "es5-pdfjs2/pdf.js",
format: "umd",
name: "pdfjsLib",
},
plugins: [
resolve(),
babel({
exclude: "node_modules/**",
runtimeHelpers: true,
}),
],
},
{
input: "lib/pdfjs-dist/build/pdf.worker.mjs",
output: {
file: "es5-pdfjs2/pdf.worker.js",
format: "umd",
name: "pdfjsWorker",
},
plugins: [
resolve(),
babel({
exclude: "node_modules/**",
runtimeHelpers: true,
}),
],
},
];
特别注意:pdfjs-dist
使用,需要pdf.js
和pdf.work.js
,所以需要打包这俩个
打包
bash
npx rollup -c

在对pdf.js
搜索一下,有没有什么特殊写法:可选链、import.meta等


demo测试

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
body {
font-family: sans-serif;
padding: 20px;
background: #f2f2f2;
text-align: center;
}
canvas {
border: 1px solid #ccc;
margin-top: 20px;
max-width: 100%;
}
</style>
</head>
<body>
<h1>PDF.js 显示 PDF 示例</h1>
<canvas id="pdf-canvas"></canvas>
<script src="es5-pdfjs/pdf.js"></script>
<script src="es5-pdfjs/pdf.worker.js"></script>
<script>
pdfjsLib.GlobalWorkerOptions.workerSrc = "es5-pdfjs/pdf.worker.js"; // 设置 worker 路径
const loadingTask = pdfjsLib.getDocument("https://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf"); // 加载 PDF 文件
loadingTask.promise
.then(function (pdf) {
console.log("PDF loaded");
// 获取第一页
return pdf.getPage(1).then(function (page) {
console.log("Page loaded");
const scale = 1.5;
const viewport = page.getViewport({ scale: scale });
// 准备 canvas
const canvas = document.getElementById("pdf-canvas");
const context = canvas.getContext("2d");
canvas.width = viewport.width;
canvas.height = viewport.height;
// 渲染页面
const renderContext = {
canvasContext: context,
viewport: viewport,
};
return page.render(renderContext).promise;
});
})
.then(function () {
console.log("Page rendered");
})
.catch(function (err) {
console.error("PDF load error:", err);
});
</script>
</body>
</html>
在vue2项目中使用

- 把打包产物放到
public
文件夹 .vue
文件加载这个脚本引用
html
<template>
<div class="pdf-viewer">
<div>
<div v-if="error" class="fallback">
<p>当前信息无法加载,您可以<a :href="pdfUrl" target="_blank">点击查看</a></p>
</div>
<div v-else>
<div v-for="(page, index) in pages" :key="index" class="pdf-page">
<img :src="page" :alt="'pdf' + (index + 1)" class="pdf-image">
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'pdf-viewer',
props: {
pdfUrl: {
type: String,
required: true,
},
},
data() {
return {
pages: [],
error: false,
}
},
mounted() {
this.loadScript('/es5-pdfjs/pdf.js').then(() => {
window.pdfjsLib.GlobalWorkerOptions.workerSrc = '/es5-pdfjs/pdf.worker.js'
this.loadPdf()
})
},
methods: {
async loadPdf() {
try {
const loadingTask = pdfjsLib.getDocument(this.pdfUrl)
const pdf = await loadingTask.promise
const pageImages = []
for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
const page = await pdf.getPage(pageNum)
const viewport = page.getViewport({ scale: 2 }) // scale 调大可提高清晰度
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
canvas.width = viewport.width
canvas.height = viewport.height
await page.render({ canvasContext: context, viewport }).promise
pageImages.push(canvas.toDataURL())
}
this.pages = pageImages
} catch (e) {
console.error('PDF 加载失败:', e)
this.error = true
}
},
loadScript(src) {
return new Promise((resolve, reject) => {
if (document.querySelector(`script[src="${src}"]`)) {
// 已加载过,直接 resolve
resolve()
return
}
const script = document.createElement('script')
script.src = src
script.onload = () => resolve()
script.onerror = e => reject(e)
document.head.appendChild(script)
})
},
},
}
</script>