创建 React 应用程序 - 如何将 pdf.worker.js 文件从 pdfjs-dist/build 复制到项目的输出文件夹?
Create react app - how to copy pdf.worker.js file from pdfjs-dist/build to your project's output folder?
由于我无法在将要使用该应用程序的网络中使用浏览器的 pdf 查看器,因此我正在测试一个 react-pdf 包以使用 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 时出现错误
Error: Setting up fake worker failed: "Cannot read property 'WorkerMessageHandler' of undefined"
在文档中它说你应该设置 service worker 并且推荐的方法是使用 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 文件复制到项目的输出文件夹中。
没有关于如何使用 create-react-app 执行此操作的说明。那我如何在本地设置呢?
您可以为 webpack 安装 worker loader 模块:
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
import { Document, Page, pdfjs } from "react-pdf";
import pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
安装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
找到了一种更有效的方法来包含工人
通过从 react-pdf 本身的依赖项中包含库,这样你就永远不会得到这样的版本不匹配 API 版本“2.3.45”与 Worker 版本“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 的经验,如果您(像我一样)为此苦苦挣扎了很长时间,我想分享更多信息。
我的环境有几个复杂的 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 也是单独安装的。无论如何,由于项目的构建方式,此方法不适用于我的代码库(将工作人员作为变量导入)。导入命令的行为就像它无法在 node_modules 文件夹中找到正确命名的导出一样。要么是顶级,要么什么都不是。
2) WebPack 配置
因为我根本不了解 WebPack,但很容易发现我需要做的就是利用 CopyWebpackPlugin
,我搜索了那些现有的开发和生产 webpack 配置文件,并找到了现有的副本JQuery 和 polyfill 的命令,并向该数组添加了一个新插件:
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 集的时间问题,代码中的 运行 不够高,但它不会影响结果,所以我放弃了。
(侧边栏,如果您还收到“TT 未知函数”(释义)错误,可以忽略该错误。这只是您正在加载的任何 PDF 的字体问题,只是警告,而不是错误。)
有一次我不得不在包中使用“react-pdf”时遇到了这个问题。
通过有条件地将工人导入代码解决了这个问题:
- 条件导入:
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')
}
}
- 用法:
import { Document, Page, pdfjs } from 'react-pdf/dist/umd/entry.webpack'
pdfjs.GlobalWorkerOptions.workerSrc = getWorker()
由于我无法在将要使用该应用程序的网络中使用浏览器的 pdf 查看器,因此我正在测试一个 react-pdf 包以使用 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 时出现错误
Error: Setting up fake worker failed: "Cannot read property 'WorkerMessageHandler' of undefined"
在文档中它说你应该设置 service worker 并且推荐的方法是使用 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 文件复制到项目的输出文件夹中。
没有关于如何使用 create-react-app 执行此操作的说明。那我如何在本地设置呢?
您可以为 webpack 安装 worker loader 模块:
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
import { Document, Page, pdfjs } from "react-pdf";
import pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
安装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
找到了一种更有效的方法来包含工人 通过从 react-pdf 本身的依赖项中包含库,这样你就永远不会得到这样的版本不匹配 API 版本“2.3.45”与 Worker 版本“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 的经验,如果您(像我一样)为此苦苦挣扎了很长时间,我想分享更多信息。
我的环境有几个复杂的 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 也是单独安装的。无论如何,由于项目的构建方式,此方法不适用于我的代码库(将工作人员作为变量导入)。导入命令的行为就像它无法在 node_modules 文件夹中找到正确命名的导出一样。要么是顶级,要么什么都不是。
2) WebPack 配置
因为我根本不了解 WebPack,但很容易发现我需要做的就是利用 CopyWebpackPlugin
,我搜索了那些现有的开发和生产 webpack 配置文件,并找到了现有的副本JQuery 和 polyfill 的命令,并向该数组添加了一个新插件:
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 集的时间问题,代码中的 运行 不够高,但它不会影响结果,所以我放弃了。
(侧边栏,如果您还收到“TT 未知函数”(释义)错误,可以忽略该错误。这只是您正在加载的任何 PDF 的字体问题,只是警告,而不是错误。)
有一次我不得不在包中使用“react-pdf”时遇到了这个问题。 通过有条件地将工人导入代码解决了这个问题:
- 条件导入:
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')
}
}
- 用法:
import { Document, Page, pdfjs } from 'react-pdf/dist/umd/entry.webpack'
pdfjs.GlobalWorkerOptions.workerSrc = getWorker()