babel+rollup打包pdfjs-dist的5.x.x高版本为es5产物,适应老项目

背景

vue2老项目如何使用pdfjs-dist解析pdf

由于之前是找到了pdfjs-dist2.7.570版本可适配我的vue2项目,可以不用更改webpackbabel配置,但这样做效率太低了,要是之后还有类似的情况,该怎么办,要是那个依赖没有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-distnpm install pdfjsd-dist --save
  • 新建lib文件夹
  • 拷贝node_modules里的pdfjs-distbuild产物到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.jspdf.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>

结束

相关推荐
一只猫猫熊5 分钟前
密码强度、一致性、相似度校验
前端
木林9075 分钟前
使用Vue3开发商品管理器(一)
前端
孤蓬&听雨8 分钟前
Axure高保真LayUI框架 V2.6.8元件库
前端·layui·产品经理·axure·原型设计
Hilaku9 分钟前
为什么我放弃使用 Pinia?
前端·javascript·vue.js
yrjw13 分钟前
使用ReactNative加载Svga动画支持三端【android/ios/harmony】
前端
贩卖纯净水.14 分钟前
webpack继续学习
前端·学习·webpack
陈_杨14 分钟前
鸿蒙5开发宝藏案例分享---在线短视频流畅切换
前端·javascript
Smile_frank17 分钟前
vue-06(“$emit”和事件修饰符)
前端
前端小巷子23 分钟前
JS的 DOM 尺寸与位置属性
前端·javascript·面试
二月垂耳兔79834 分钟前
Vue3基础
前端