はじめに
以前もこちらの記事でTypescript(サーバーサイド)を使ったPDFの生成に関して書いたのですが、今回はグラフ画像を埋め込んだPDFを動的に生成するエンドポイントを実装した際のメモです。「グラフ画像をサーバーサイドで動的に作りたい」、というだけの場合も役に立つかもしれません。
PDF生成までの流れ
元々はchartjs-node-canvasを使ってのグラフ画像の生成を考えていたのですが、node v18で動かず、代わりにPuppeteerでheadles chromeを起動しスクリーンショットを撮る形にしました。ブラウザでのグラフ描画にはechartsを使用しました。以下、生成までの流れとなります。
- DBからグラフに必要なデータを取得
- Puppeteerでheadless chromeを起動
- Javascriptライブラリechartsでグラフを描画
- Puppeteerの機能で描画されたグラフのスクリーンショットを撮りbase64にエンコード
- pdfmakeで上記画像を含むPDFを生成
Puppeteer
コンテナ形式ではなく、Zip形式のAWS Lambdaを使う場合、Lambda環境向けのchromiumをインストールする必要があります。今回はこちらの@sparticuz/chromiumを使用しました。また、ビルド時に ${project_directory}/node_modules/@sparticuz/chromium/bin
の中身を丸っと ${project_directory}/bin
にコピーする必要がありました。これにより、PuppeteerがchromiumをLambda上で起動できるようになります。
import puppeteer from 'pupeteer-core';
import chromium from '@sparticuz/chromium';
import { setTimeout } from 'node:timers/promises';
...
// Puppeteerの起動
const browser = await puppeteer.launch({
args: chromium.args,
defaultViewport: chromium.defaultViewport,
executablePath: await chromium.executablePath(),
headless: chromium.headless,
});
const page = await browser.newPage();
// 必要に応じて描画が終わるまでwaitする
await setTimeout(1000);
// スクリーンショットの撮影
const buffer = await page.screenshot({
type: 'jpeg',
quality: 100,
});
// base64にエンコード
const base64Encoded = buffer.toString('base64');
...
// pdfmakeに画像データを渡しPDFを生成
pdfmake
少し他のライブラリも見てみたのですが、Typescriptだと依然pdfmakeが使いやすい印象でした。pdfmakeの使用方法に関してはこちらの記事で以前に紹介しています。
まとめ
グラフ画像を含むPDFをLambdaで動的に生成する際のメモでした。Lambda上でchromiumを起動するところで少しつまづきましたが、上手くPDFを作成することができました。