簡體   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