Next.js の API として Web サイトのサムネイルを表示するための仕組みを実装していきます。今回は、取得した URL を利用して画像を表示するところまで進めていきます。
コンテンツ更新
ブログで紹介をしていた Playwright のトピックに関しては、最新版では Vercel に展開できるようにしました。以下のページを参照してください。
Playwright のコンテナの動作を変更
すでに実装していた Playwright の動作するコンテナのサンプルですが、URL をパラメータで渡すと画像を表示するように作成していました。今回は連携で利用しやすくするために、返値として Json 形式で返しつつ、画像のデータは base64 で出力するようにします。
この部分の変更は非常にシンプルで、該当するコードを以下のように書き換えてください。
const screenshot = await page.screenshot();
// Base64エンコードされたスクリーンショットをHTTPレスポンスとして送信
const base64Screenshot = screenshot.toString("base64");
res.json({ screenshot: base64Screenshot });
実際にアクセスをすると以下のように Json のデータが返ってきます。
画像を取得する
上記の API を利用して Base64 で取得したデータを画像として表示するようにコードを書き換えていきます。
今回は非同期処理を実装するために、axios を利用します。以下のようにインストールをしてください。
npm install axios
続いて最初のエリアでこれを利用する定義を追加します。
const axios = require("axios");
そして前回紹介をしていたコードで最後に Json の結果を返していたところを以下のように書き換えます。URL のところは既に展開しているコンテナが動いている Web app もしくはローカルで動かしている場合はその URL を利用してください。
try {
const externalApiUrl =
"https://yourplaywright.domain/api/screenshot?url=" +
url;
const response = await axios.get(externalApiUrl);
const imageData = response.data.screenshot;
const decodedImageData = Buffer.from(imageData, "base64");
res.setHeader("Content-Type", "image/png");
res.status(200).end(decodedImageData, "binary");
} catch (error) {
return res.status(500).json({ error: "Can't get content data" });
}
これで URL をアプリに私、Base64 で返された値を画像に変換して表示させることができます。結果は以下のようになります。
サーバーを環境変数として定義する
上記のサンプルのコードではサーバーの URL が埋め込まれている形となります。これを環境変数として定義します。まずは、.env で以下の項目を追加します。
NEXT_PUBLIC_PLAYWRIGHT=https://yourplaywright.domain
続いて上記の値を取得するために、該当するコードに以下の1行を追加します。
const NEXT_PUBLIC_PLAYWRIGHT = process.env.NEXT_PUBLIC_PLAYWRIGHT;
最後に、URL を記載している行を以下のように書き換えます。
const externalApiUrl = NEXT_PUBLIC_PLAYWRIGHT + "/api/screenshot?url=" + url;
上記の設定が終わったあと、問題なく動作しているか確認をしてください。
まとめ
今回は Next.js の API から Playwright の API を利用してスクリーンショットを取得する方法を紹介しました。この際、コンテナで返していたデータは画像でしたが、今回は Base64 のデータでやり取りをする形に変更をしました。また、サーバーが変更されることも多いと考えて、環境変数としてサーバーの URL を変更できるようにしました。
今の実装では毎回画像を取得する形となるため、Azure Blob Storage に画像を保存、画像があればそれを利用する部分のコードを追加していきます。