繁体   English   中英

创建 React 应用程序 - 如何将 pdf.worker.js 文件从 pdfjs-dist/build 复制到项目的 output 文件夹?

[英]Create react app - how to copy pdf.worker.js file from pdfjs-dist/build to your project's output folder?

由于我无法在将要使用该应用程序的.network 中使用浏览器的 pdf 查看器,因此我正在测试react-pdf package 以使用 React 加载 PDF。 我制作了一个组件,我在其中发送我从后端获得的 PDF 的 url:

import React, { useState } from 'react';
import { Document, Page } from 'react-pdf';

const PDFViewer = ({url}) => {
  const [numPages, setNumPages] = useState(null);
  const [pageNumber, setPageNumber] = useState(1);

  function onDocumentLoadSuccess({ numPages }) {
    setNumPages(numPages);
  }
 function onLoadError(error) {
   console.log(error);
 }

 function onSourceError(error) {
   console.log(error);
 }

  return (
    <div>
      <Document
        file={window.location.origin + url}
        onLoadSuccess={onDocumentLoadSuccess}
        onLoadError={onLoadError}
        onSourceError={onSourceError}
      >
        {[...Array(numPages).keys()].map((p) => (
          <Page pageNumber={p + 1} />
        ))}
      </Document>
    </div>
  );
};

export default PDFViewer;

但是,在打开 PDFViewer 时出现错误

错误:设置假工作者失败:“无法读取未定义的属性‘WorkerMessageHandler’”

在文档中它说你应该设置服务工作者并且推荐的方法是使用 CDN 来做到这一点:

import { pdfjs } from 'react-pdf';
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`;

但是,我不能为我的项目使用 CDN 链接,并且在文档中它还说:

Create React App 在后台使用 Webpack,但 Webpack 的说明将不起作用。 适用标准说明。 标准(Browserify 和其他)如果您使用 Browserify 或其他捆绑工具,您必须自己确保将 pdfjs-dist/build 中的 pdf.worker.js 文件复制到项目的 output 文件夹中。

没有关于如何使用 create-react-app 执行此操作的说明。 那我该如何在本地设置呢?

安装pdfjs-dist

import { Document, Page, pdfjs } from "react-pdf";
import pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";

pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;

参考: https://github.com/mozilla/pdf.js/issues/8305

通过从 react-pdf 本身的依赖项中包含库找到了一种更有效的方法来包含工作人员,这样你就永远不会得到这样的版本不匹配API 版本“2.3.45”与工作人员版本“2.1”不匹配。 266"

如果您手动安装 pdfjs-dist,则必须在每个构建中检查 react pdf 依赖版本

import { Document, Page, pdfjs } from "react-pdf";
import pdfjsWorker from "react-pdf/node_modules/pdfjs-dist/build/pdf.worker.entry";

pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;

在 pdfjs 库上看到类似的错误: https://github.com/mozilla/pdf.js/issues/10997

希望它可以帮助人们

您可以为 webpack 安装工作加载程序模块:

npm install worker-loader --save-dev

然后在您将与工人一起工作的地方使用它:

import SomeWorker from 'worker-loader?inline=true!../workers/some.worker'

const someWorker: Worker = new SomeWorker()

someWorker.postMessage(...)

我没有用react-pdf尝试过这个解决方案,但它可能会有所帮助。

如果您使用它,您可能需要为 TypeScript 添加类型:

declare module 'worker-loader*' {
  class SomeWorker extends Worker {
    constructor()
  }

  export default SomeWorker
}

只是将其添加到项目中的某些.d.ts文件中。

安装pdfjs-dist然后使用webpack模块:

import { pdfjs } from 'react-pdf'
import worker from 'pdfjs-dist/webpack'

pdfjs.GlobalWorkerOptions.workerSrc = worker

如果您的构建过程使用 cli 命令(即 AWS buildspec),您可以使用:

mkdir -p build && cp./node_modules/pdfjs-dist/build/pdf.worker.js build

如果您在公司代码库环境中并且几乎没有配置 WebPack 的经验,如果(像我一样)您在此问题上挣扎了很长时间,我想分享更多信息。

我的环境有几个复杂的 WebPack 配置文件(基础、生产和开发),最终解决方案非常简单,但由于我不熟悉复杂的构建过程,所以我有一段时间没能解决它。

1) 实施

很简单,就像文档推荐的那样(我使用的是缩小文件)。 我们的 React 环境要求我使用 React-PDF@4.2.0,但这里没有任何区别。

import {Document, Page, pdfjs} from 'react-pdf'
pdfjs.GlobalWorkerOptions.workerSrc = 'pdf.worker.min.js'

注意:以前的解决方案建议从 react-pdf node_modules 文件夹中获取源代码,但是,我的代码库设置为以某种方式单独安装依赖项,因为当我npm install react-pdf 时,pdfjs-dist 也单独安装。 无论如何,由于项目的构建方式,此方法不适用于我的代码库(将 worker 作为变量导入)。 导入命令的行为就像它在 node_modules 文件夹中找不到正确命名的导出一样。 它是顶级的,或者什么都不是。

2) WebPack 配置

由于我根本不知道 WebPack,但是很容易发现我需要做的是利用CopyWebpackPlugin ,我搜索了那些现有的开发和产品 webpack 配置文件,并找到了 Z6A2D7208853BEF37ED04F8795A88Z 的现有复制命令和添加了新的复制命令该数组的插件:

new CopyWebpackPlugin({from: 'node_modules/pdfjs-dist/build/pdf.worker.min.js})

我必须在两个配置文件中的多个位置执行此操作,因为这个大型项目有多个用于网站不同服务的入口点服务器文件。

3) 将脚本标签插入 HTML 头

这是我错过的关键部分。 有一个“ComponentFactory”文件,其工作是在 html 文件的<head>和尾部插入 html 块。 我不习惯在小项目上做这样的事情。 所以在那里,我只是复制了已经为 jquery 和 polyfill 完成的工作,其中包括 webpack 正在构建的资产文件夹位置的字符串文字。 就我而言,这类似于“assets/v1/”。 所以标签看起来像这样:

<script src=`${STATIC_ASSETS_URL}/pdf.worker.min.js` defer></script>

它工作得很好,但是我仍然得到“设置一个假工人”,但在那之后,它立即在控制台中成功加载它并检查开发工具,它使用了正确的文件。 这可能只是 src 集在代码中运行得不够高的时间问题,但它并没有影响结果,所以我让它 go。

(侧边栏,如果您还收到“TT 未知函数”(释义)错误,可以忽略。这只是您正在加载的 PDF 的字体问题,只是一个警告,而不是错误。)

一旦我不得不在 package 中使用“react-pdf”,我就遇到了这个问题。通过有条件地将 worker 导入代码中解决了这个问题:

  1. 有条件的进口:

 export const getWorker = () => { try { return require('react-pdf/node_modules/pdfjs-dist/legacy/build/pdf.worker.entry.js') } catch () { return require('pdfjs-dist/legacy/build/pdf.worker.entry.js') } }

  1. 用法:

 import { Document, Page, pdfjs } from 'react-pdf/dist/umd/entry.webpack' pdfjs.GlobalWorkerOptions.workerSrc = getWorker()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM