1
/
5

Webpack 5でPDF.jsをいい感じに呼び出す

Photo by Markus Winkler on Unsplash

PDF.jsはブラウザでPDFを表示できるすごいライブラリです。PDF.jsはWeb Workersを使うため、Webpackなどのモジュールバンドラーと組み合わせるときは設定が必要な場合があります。これまでWebpackではworker-loaderを使うのが標準的な方法で、設定を簡単に済ませるためのモジュールも提供されていました。

import pdfjsLib from "pdfjs-dist/webpack";

Webpack 5でもworker-loaderは使えますが非推奨化されています。かわりにブラウザで使うときとよく似た構文でBackground workerを初期化できるようになりました。

new Worker(new URL('./worker.js', import.meta.url));

pdfjs-dist/webpackがやっていることは、worker-loaderをinline loader syntaxで呼び出してworkerPortにセットするというだけです。これを自分で行えばいいので、以下のようにすればworker-loaderを使わずにpdf.jsをセットアップできます。

import pdfjsLib from "pdfjs-dist";

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

new URL() の第一引数が相対パスではないので、Webpackの外では動かないでしょう。それが気になる場合は、同じディレクトリにワーカーをimportするだけのダミーモジュールを置くともう少し自然かもしれません。

Worker syntaxの詳細

新しいWorker用構文は本体同梱のWorkerPluginで実装されています。以下の4つの書き方がWorkerクラスとして検出されます。

// Worker グローバル変数
new Worker(...);

// SharedWorker グローバル変数
new SharedWorker(...);

// register関数 (newはつかない)
navigator.serviceWorker.register(...);

// worker_threads モジュールの Worker エクスポート
import { Worker } from 'worker_threads';
new Worker(...);

このとき第一引数がさらにチェックされ、以下のフォーマットであることがチェックされます。

new URL("...", "...");
//             ^^^^^ arg2: 簡約後の式が文字列リテラル
//      ^^^^^ arg1: 簡約後の式が文字列リテラル
//  ^^^ callee: 簡約後の式がURLへの参照

上のcallee, arg1, arg2の位置でそれぞれ式の簡約が試みられるため、 import.meta.url はこの時点で展開されます。フォーマットが一致していても arg2 の値は import.meta.url の値と一致していないといけないので、実際には import.meta.url 以外に書きようはないでしょう。

ここまでの条件を満たすと、この new URL(...) はWeb Workersのworker実装を要求する特殊なインポート命令として解釈されます。URLコンストラクタの第一引数をモジュールパスとみなして解決し、Web Workers用にあしらえたチャンクを生成します。 new URL(...) 全体がチャンクのURLに置き換えられます。

なお、似たような構文としてURLアセット構文があります。Web Workersの初期化以外の位置でこのようなURLオブジェクトを生成すると、ファイルがそのまま切り出され、そのアップロード予定のURLで置き換えられます。これは画像の取り込みで使うことができます。

いずれも条件を満たさないときはそのままの形で残される (ビルドエラーにはならない) ので、リファクタリングで意図せず壊してしまわないかは心配です。たとえば new URL() 部分を変数に切り出しても見た目上は同じ動作に見えますが、Webpackにとっては扱いが変わってしまいます。このような問題を防ぐために、意図をコメントに残しておくのがいいかもしれません。

Wantedly, Inc.'s job postings
4 Likes
4 Likes

Weekly ranking

Show other rankings
Invitation from Wantedly, Inc.
If this story triggered your interest, have a chat with the team?