Создать приложение react — как скопировать pdf.worker.js файл из pdfjs-dist / build в выходную папку вашего проекта?

#reactjs #pdf #react-pdf

#reactjs #PDF #react-pdf

Вопрос:

Поскольку я не могу использовать средство просмотра pdf в браузере в сети, где будет использоваться приложение, я тестирую пакет react-pdf для загрузки PDF-файлов с помощью React. Я создал компонент, в который я отправляю URL-адрес своего PDF-файла, который я получаю из серверной части:

 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’ неопределенного»

В документации говорится, что вы должны настроить 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 использует Webpack под капотом, но инструкции для Webpack не будут работать. Применяются стандартные инструкции. Стандартный (Browserify и другие) Если вы используете Browserify или другие инструменты объединения, вам нужно будет самостоятельно убедиться, что pdf.worker.js файл из pdfjs-dist/build копируется в выходную папку вашего проекта.

Нет никаких инструкций о том, как это сделать с помощью create-react-app . Как я могу настроить это локально?

Ответ №1:

Установить 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

Комментарии:

1. Для react-pdf 5.7.0 ни один из приведенных здесь ответов не работает с CRA 5.0.0, выпущенным в декабре 2021 года. Что работает, так это скопировать pdf.worker.js и pde.worker.js.map в общедоступный каталог вашего проекта из node-modules/pdf-dist/legacy/build/pdf.worker.js и файлы pde.worker.js.map. начиная с 2-10-22. В репозитории Git ничего не говорится о необходимости копирования файла .map. Вероятно, ошибка. Там возникла проблема.

2. Не забудьте добавить d.ts файл с declare module 'pdfjs-dist/build/pdf.worker.entry'; помощью при работе с Typescript

Ответ №2:

найден более эффективный способ включения worker путем включения библиотеки из зависимостей самого 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

надеюсь, это поможет людям

Ответ №3:

Вы можете установить модуль рабочего загрузчика для 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 -нибудь файл вашего проекта.

Ответ №4:

Установите pdfjs-dist , затем используйте webpack модуль:

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

pdfjs.GlobalWorkerOptions.workerSrc = worker
 

Комментарии:

1. Этот ответ очень похож на ответ @lissettdm, в чем разница между pdfjs-dist /webpack и pdfjs-dist/build/pdf.worker.entry?

2. Я не знаю об ответе @lissettdm, но я использовал это. Я предполагаю, что он разработан с учетом webpack.

Ответ №5:

Если в вашем процессе сборки используются команды cli (например, AWS buildspec), вы можете использовать это:

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

Ответ №6:

Если вы работаете в корпоративной среде с кодовой базой и практически не имеете опыта настройки WebPack, я хотел бы поделиться немного дополнительной информацией, если (как и я) вы боролись с этим довольно долго.

В моей среде есть несколько сложных конфигурационных файлов WebPack (base, production и development), и решение оказалось довольно простым, но оно довольно долго ускользало от меня, потому что я не был знаком со сложным процессом сборки.

1) Реализация

Довольно просто, как и рекомендуют документы (я пошел с уменьшенным файлом). Наша среда реагирования требовала, чтобы я использовал React-PDF@4.2.0 , но здесь нет никаких различий.

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

Примечание: в предыдущем решении рекомендовалось использовать исходный код из папки node_modules react-pdf, однако моя кодовая база настроена на установку зависимостей как-то отдельно, потому что, когда я npm install реагирую-pdf, pdfjs-dist также устанавливается отдельно. Несмотря на это, этот метод не работал для моей кодовой базы (импортируя worker как переменную) из-за способа сборки проекта. Команда import действовала так, как будто не смогла найти правильный именованный экспорт внутри папки node_modules. Это был верхний уровень или ничего.

2) Конфигурация WebPack

Поскольку я совсем не знаю WebPack, но довольно легко обнаружил, что мне нужно было воспользоваться преимуществами CopyWebpackPlugin , я просмотрел существующие конфигурационные файлы webpack для разработчиков и prod, нашел существующие команды копирования для jQuery и polyfill и добавил новый плагин в этот массив:

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

Мне пришлось сделать это в нескольких местах в обоих файлах конфигурации, поскольку этот большой проект имеет несколько файлов сервера точек входа для различных служб веб-сайта.

3) Вставка тега скрипта в заголовок HTML

Это была важная часть, которую я пропустил. Был файл «ComponentFactory», задачей которого было вставлять фрагменты html в начало <head> и конец html-файла. Я не привык к чему-то подобному в небольших проектах. Итак, я просто скопировал то, что уже было сделано для jquery и polyfill, которые включали строковый литерал местоположения папки ресурсов, в которую создавался веб-пакет. В моем случае это было что-то вроде «assets/v1 /». Итак, тег выглядел так:

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

Он работает отлично, однако я все еще получаю сообщение «Настройка поддельного рабочего», но сразу после этого он успешно загрузил его в консоль и проверил инструменты разработчика, он использовал правильный файл. Вероятно, это просто временная привязка к набору src, который недостаточно высок в коде, но это не повлияло на результат, поэтому я отпустил его.

(Боковая панель, если вы также получаете ошибку «Неизвестная функция TT» (перефразируя), это можно игнорировать. Это просто проблема со шрифтом в любом загружаемом вами PDF-файле, и это просто предупреждение, а не ошибка.)

Ответ №7:

Я столкнулся с этой проблемой, когда мне пришлось использовать «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()