LoginSignup
6
8

More than 3 years have passed since last update.

【IE 11 対応版】PDF.js × Webpack

Last updated at Posted at 2020-06-10

やりたかったこと

  • PDF.js を導入して PDF Viewer を作成する
  • IE 11 に対応する
  • IDE で PDF.js のプロパティやメソッドに補完を効かせて開発する

結論

  • PDF.js を node_module としてインストールする
  • 開発時は node_module の PDF.js をインポートすることで IDE の補完を有効にする
  • 本番時は Prebuilt (ES5-compatible) を HTML で読み込む
  • Webpack の externals を用いて HTML で読み込む JavaScript ファイルと連携する

ディレクトリ構成

.
├── dist
│   └── js
│       └── main.js
├── src
│   └── js
│       └── main.js
├── vendor
│   └── pdfjs-2.4.456-es5-dist
│       └── 省略
├── README.md
├── babel.config.js
├── index.html
├── package-lock.json
├── package.json
└── webpack.config.js

PDF.js のダウンロードページ から Prebuilt (ES5-compatible) の Stable 版をダウンロードして vendor ディレクトリ配下に解凍します。バージョンは上記サンプルと異なる場合があります。

依存モジュール

npm i -D webpack webpack-cli terser-webpack-plugin babel-loader @babel/core @babel/preset-env glob pdfjs-dist

各ファイル

index.html

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Title</title>
</head>

<body>
    <canvas id="the-canvas"></canvas>

    <script src="vendor/pdfjs-2.4.456-es5-dist/build/pdf.js" defer></script>
    <script src="dist/js/app.js" defer></script>
</body>

</html>

src/js/main.js

import "core-js/stable";
import "regenerator-runtime/runtime";

const pdfjsLib = require("pdfjs-dist");

pdfjsLib.GlobalWorkerOptions.workerSrc = "vendor/pdfjs-2.4.456-es5-dist/build/pdf.worker.js";

pdfjsLib.getDocument("/path/to/xxxx.pdf").promise.then(
  (pdf) => {
    console.log("pdf loaded");

    pdf.getPage(1).then((page) => {
      const viewport = page.getViewport({ scale: 1.0 });

      const canvas = document.querySelector("#the-canvas");
      canvas.width = viewport.width;
      canvas.hieght = viewport.hieght;

      const ctx = canvas.getContext("2d");
      const renderCtx = {
        canvasContext: ctx,
        viewport: viewport,
      };

      page.render(renderCtx).promise.then(
        () => {
          console.log("page rendered");
        },
        (e) => {
          console.error(e);
        }
      );
    });
  },
  (e) => {
    console.error(e);
  }
);

console.log(pdfjsLib);

webpack.config.js

const path = require("path");
const glob = require("glob");
const TerserPlugin = require("terser-webpack-plugin");

module.exports = (env, argv) => {
  const IS_PROD = argv.mode == "production";

  console.log("NODE_ENV: ", env.NODE_ENV);
  console.log("IS_PROD: ", IS_PROD);
  console.log("--mode: ", argv.mode);

  const srcDir = path.resolve(__dirname, "src", "js");

  const entries = {};
  glob.sync("*.js", { cwd: srcDir, ignore: [] }).forEach((filename) => {
    const entry = filename.replace(".js", "");
    entries[entry] = path.resolve(srcDir, filename);
  });
  console.log(entries);

  return {
    mode: argv.mode,
    devtool: IS_PROD ? "none" : "source-map",
    entry: entries,
    output: {
      path: path.resolve(__dirname, "dist"),
      filename: "js/[name].js",
    },
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          loader: "babel-loader",
        },
      ],
    },
    externals: [
      {
        "pdfjs-dist": "pdfjsLib",
      },
    ],
    optimization: IS_PROD
      ? {
          minimizer: [
            new TerserPlugin({
              terserOptions: {
                compress: { drop_console: true },
              },
            }),
          ],
        }
      : {},
  };
};

babel.config.js

module.exports = (api) => {
  api.cache(true);

  return {
    presets: [
      [
        "@babel/preset-env",
        {
          useBuiltIns: "usage",
          corejs: {
            version: "3",
          },
          debug: true,
        },
      ],
    ],
  };
};

package.json

{
  "scripts": {
    "dev": "webpack --env.NODE_ENV=development --mode development --progress",
    "prod": "webpack --env.NODE_ENV=production --mode production --progress"
  },
  "devDependencies": {
    "@babel/core": "^7.10.2",
    "@babel/preset-env": "^7.10.2",
    "babel-loader": "^8.1.0",
    "core-js": "^3.6.5",
    "pdfjs-dist": "^2.4.456",
    "regenerator-runtime": "^0.13.5",
    "terser-webpack-plugin": "^3.0.3",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.11",
  },
  "dependencies": {}
}

試してみたこと

gulp × browserify × babelifywebpack × babel などで HTML で直接 PDF.js を読み込むのではなく、node_module の PDF.js をバンドルして es5 にトランスパイルする手法も試してみましたが、何かしらのエラーが出てしまいことごとく失敗に終わりました。

webpack の externals の設定を使うことで今回やりたかったことが実現できましたが、もっといい方法があれば知りたいです。

6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8