PDF.js を使おうとしたら、セットアップにやたらと苦労した

[PDF.js](https://mozilla.github.io/pdf.js/) とは PDF を JavaScript で扱うためのフレームワークです。

選択した PDF ファイルを Javascript 上で png に変換してアップロードする、ということをやりたかったので、このフレームワークを選択しました。

が、セットアップにだいぶ苦労したので、書き留めておきます。

## 自分の環境

主な構成情報は以下です。

- サーバー側
    - Rails (7.0.1)
    - react_on_rails (12.5.2)
    - webpacker (5.4.3)
- クライアント側
    - react@17.0.2
    - typescript@4.5.5
    - webpack@4.46.0

ただの `Javascript` で使うだけなら、苦労しないでしょうが、
`Typescript` と `webpacker` の環境だとちょっと苦労しました (後述)。


## インストール方法

インストールは、[Wiki](https://github.com/mozilla/pdf.js/wiki/Setup-pdf.js-in-a-website) にあるように `pdfjs-dist` を `npm install` します。

```
npm install pdfjs-dist
```

これは簡単！

## ローディング

`Typescript` から読み込んで使いたいのですが、

### :x: ダメだったやつ

[npm の例](https://github.com/mozilla/pdf.js/blob/master/examples/node/getinfo.js) に従って書いたら、

```
const pdfjsLib = require("pdfjs-dist/legacy/build/pdf.js");
```

エラーが出ます :frowning2: 。

```
Deprecated API usage: No "GlobalWorkerOptions.workerSrc" specified.
```

### :small_red_triangle: うごいたけど Warning でたやつ

`workSrc` を指定せよ、というメッセージだったので、`pdfjs-dist/legacy/build/pdf.worker.entry` を `workerSrc` に指定したら、

```
import * as pdfjs from 'pdfjs-dist/legacy/build/pdf';
import * as pdfjsWorker from 'pdfjs-dist/legacy/build/pdf.worker.entry';

pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
```

動きました！
が、コンソールに `Warning` が出ます :thinking_face: 。

```
Warning: Setting up fake worker.
```

### :o: うまくいったやつ

どうも `worker` を立てた方がよさそうなので、`worker-loader` を `npm install` 。

```
npm install worker-loader
```

そして、`pdfjs-dist/legacy/build/pdf.worker.js` をもとにした `worker-loader` を立てます。

```typescript
import * as pdfjs from 'pdfjs-dist/legacy/build/pdf';

const PdfjsWorker = require("worker-loader?esModule=false&filename=[name].[contenthash].js!pdfjs-dist/legacy/build/pdf.worker.js");
pdfjs.GlobalWorkerOptions.workerPort = new PdfjsWorker();
```

これで `Warning` が出ることなく、動きました！ :smiley: 。

#### webpack5 であれば

今回は webpack 4.46 でしたが、webpack 5 であれば、`import.meta.url` が使えるので、`work-loader` を使わずにできるようです :laughing: (試してないけど)。

```
import * as pdfjs from 'pdfjs-dist/legacy/build/pdf';

pdfjsLib.GlobalWorkerOptions.workerPort =
  new Worker(new URL("pdfjs-dist/legacy/build/pdf.worker.js", import.meta.url));
```


### なんか別の Warning が出てるんだけど。。。

```
Warning: TT: undefined function: 3
```

という `Warning` が出ますが、これは問題なさそう :rolling_eyes: 。

https://github.com/mozilla/pdf.js/issues/3768#issuecomment-36468349


## その他 ダメだったやつ

### webpack 向けのものを使う

[webpack の例](https://github.com/mozilla/pdf.js/tree/master/examples/webpack) では、以下のように書かれていますが、

```
import * as pdfjsLib from 'pdfjs-dist/webpack';
```

`TypeError` が出ます :frowning2: 。

```
Uncaught TypeError: root is undefined
```

どうも `webpacker` 側の問題みたいです。

https://github.com/rails/webpacker/issues/2804#issuecomment-784701106

回避策が示されていますが、回避策を実施しても、

```
./node_modules/pdfjs-dist/build/pdf.js 1387:9
Module parse failed: Unexpected character '#' (1387:9)
```

とエラーになったので諦めました :sweat_smile: 。

### legacy ではないものを使う

legacy (`pdfjs-dist/legacy/build/pdf`) ではない通常のパスをしたいところですが、

```
import * as pdfjs from 'pdfjs-dist/build/pdf'
```

このパスには `Typescript` がないので、`not found` になります :frowning2: 。

```
"export 'getDocument' (imported as 'pdfjs') was not found in 'pdfjs-dist/build/pdf’
```

# 参考

https://qiita.com/kazu_death/items/f29b110cb2d4b482ff94

https://github.com/mozilla/pdf.js/issues/10478

https://www.wantedly.com/companies/wantedly/post_articles/367427