playwrightを使ってWebページのPDFを保存する

はじめに

playwrightではなく、puppeteerでPDFを保存するということをやったことはあるのだが、playwrightではやったことはなかったので備忘録として残しておく。

環境

Node.js 20.11.1
pnpm 8.15.4
playwright 1.42.1

準備

を使う。

node.js+expressの記事で作成したものを少し改造する。

変更点

package.jsonplaywrightをインストール後、Dockerfileを下記のように修正した。

-FROM node:${NODE_VERSION}-alpine
+FROM node:${NODE_VERSION}

+# 目的のUID/GIDに変更する
+ARG USER_ID=1000
+ARG GROUP_ID=1000

# Install pnpm.
-RUN --mount=type=cache,target=/root/.npm \
-    npm install -g pnpm@${PNPM_VERSION}
+RUN npm install -g pnpm@${PNPM_VERSION}

WORKDIR /usr/src/app

RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=pnpm-lock.yaml,target=pnpm-lock.yaml \
    --mount=type=cache,target=/root/.local/share/pnpm/store \
    pnpm install --prod --frozen-lockfile

+RUN npx playwright install-deps

+# グループとユーザを作成し、所有権を変更する
+RUN groupmod --gid $GROUP_ID node && \
+    usermod --uid $USER_ID --gid $GROUP_ID node && \
+    chown -R node:node /usr/src/app

# Run the application as a non-root user.
USER node

+RUN npx playwright install

Dockerfileの全体は下記

# syntax=docker/dockerfile:1

# Comments are provided throughout this file to help you get started.
# If you need more help, visit the Dockerfile reference guide at
# https://docs.docker.com/go/dockerfile-reference/

# Want to help us make this template better? Share your feedback here: https://forms.gle/ybq9Krt8jtBL3iCk7

ARG NODE_VERSION=20.11.1
ARG PNPM_VERSION=8.15.4

FROM node:${NODE_VERSION}

# 目的のUID/GIDに変更する
ARG USER_ID=1000
ARG GROUP_ID=1000

# Use production node environment by default.
ENV NODE_ENV production

# Install pnpm.
RUN npm install -g pnpm@${PNPM_VERSION}

WORKDIR /usr/src/app

# Download dependencies as a separate step to take advantage of Docker's caching.
# Leverage a cache mount to /root/.local/share/pnpm/store to speed up subsequent builds.
# Leverage a bind mounts to package.json and pnpm-lock.yaml to avoid having to copy them into
# into this layer.
RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=pnpm-lock.yaml,target=pnpm-lock.yaml \
    --mount=type=cache,target=/root/.local/share/pnpm/store \
    pnpm install --prod --frozen-lockfile

RUN npx playwright install-deps

# グループとユーザを作成し、所有権を変更する
RUN groupmod --gid $GROUP_ID node && \
    usermod --uid $USER_ID --gid $GROUP_ID node && \
    chown -R node:node /usr/src/app

# Run the application as a non-root user.
USER node

RUN npx playwright install

# Copy the rest of the source files into the image.
COPY . .

# Expose the port that the application listens on.
EXPOSE 3000

# Run the application.
#CMD ["tail", "-f", "/dev/null"]
CMD node index.js

PDFを作成するjsは下記になる。

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();

  // ウェブページを開く
  await page.goto('https://www.google.com');

  // PDF を保存する
  await page.pdf({ path: 'google.pdf' });

  await browser.close();
})();

動作確認

docker compose exec server bash

で、コンテナに入り

node simple-capture-pdf.js

で実行する。

実行結果を確認すると、google.pdfが作成できていることがわかる。

node@4f740afe5daf:/usr/src/app$ node simple-pdf-capture.js 
node@4f740afe5daf:/usr/src/app$ ls
README.Docker.md  google.pdf  index.js  node_modules  package.json  playwright-test.js  pnpm-lock.yaml  simple-pdf-capture.js

PDFの確認

ホストとコンテナ間でソースコードに関してはボリュームをマウントしていないのでdocker cpでコピーをする。

なので、docker cpでコンテナIDを確認する。

docker cp

CONTAINER ID   IMAGE                           COMMAND                   CREATED          STATUS          PORTS                    NAMES
4f740afe5daf   nodejs-express-handson-server   "docker-entrypoint.s…"   30 minutes ago   Up 30 minutes   0.0.0.0:3000->3000/tcp   nodejs-express-handson-server-1

ホスト側にgoogle.pdfをコピーする。

docker cp 4f740afe5daf:/usr/src/app/google.pdf .

できたもの↓
google.pdf

参考

おわりに

playwrightでPDFの保存というのをやってみた。
playwrightはE2Eテストが主な目的だが、WebページのPDFを保存するということもできることを知れた。
今度はE2Eテストとして使えるように試してみたい。
特に業務ではテストデータを手作業で作るのが面倒なので、playwrightを使って自動化してみたいなあ。

Hugo で構築されています。
テーマ StackJimmy によって設計されています。