Closed12

VercelのServerless Functionでplaywright-coreが動作しない現象

haxibamihaxibami

問題の概要

VercelにデプロイしたNext.js製サイトにおいて、OGP画像を生成するためAPI Routes(Serverless Function)を利用している。

https://github.com/haxibami/haxibami.net

https://zenn.dev/tdkn/articles/c52a0cc7bea561

具体的には上の記事と同様に、playwright-coreplaywright-aws-lambdaを利用してスクリーンショットを撮影しているが、なぜかplaywright-coreをv1.19.2以上に更新すると動作しない現象が起きた。厳密に言うと、ローカルの開発サーバでは動作し、なおかつデプロイも成功するが、デプロイ後にアクセスを行うとエラーが発生する。

解決策(追記)

Next.jsをv12.1.5に更新することで解消した。(依存パッケージの@vercel/nftがv0.18.1に更新されるため)

haxibamihaxibami

環境

おそらく関連がありそうなもの

  • Next.js v12.1.4
  • pnpm v6.32.6
  • playwright-core v>=1.19.2
  • @vercel/nft v1.18.0
haxibamihaxibami

見た感じ、playwright-core以下のlib/utils/comparators.jsでモジュール解決のエラーが起きているようだ。これはコンパイル前のsrc/utils/comparators.tsにあたり、該当箇所はこんな感じ:

// Note: we require the pngjs version of pixelmatch to avoid version mismatches.
const { PNG } = require(require.resolve('pngjs', { paths: [require.resolve('pixelmatch')] })) as typeof import('pngjs');

playwright-coreの変更履歴を見ると、v1.19.1とv1.19.2の間でこのコードを含むファイルが付加されており、ここがエラーの原因箇所であることは間違いなさそうだ。

haxibamihaxibami

他方、同じ構成でもすべての環境でエラーが起きているわけではない。例えば以下のアプリはplaywright-coreの最新バージョンをVercel上で使用しているが、特に問題がある様子はない。

https://github.com/proeco/proeco-ogp

さらにv1.19.2のリリースから1ヶ月以上経っているにもかかわらず、playwright-coreのリポジトリには特段Issueが立っていない。

haxibamihaxibami

とすると問題はこちらの環境にありそうだ。ここでパッケージマネージャにpnpmを使っていることに思い当たり、これが原因だと睨んだ。

最初に試したのはpnpmの--shamefully-hoistオプションだ。pnpmが生成するnode_modulesの構造はnpm、yarnとは異なるが、このオプションではpnpmに他と同様のnode_modulesを生成させる。Vercel上のインストールコマンドにこれを用いれば、他のパッケージマネージャと同様の形でファイルがデプロイされるのではないか? というわけだ。だがこれも効果はなかった。

haxibamihaxibami

次に、Vercelで使用するパッケージマネージャを強引にnpm / yarnに切り替えてみた。ところが今度はlockfileがないせいか、ビルド時点でエラーが出てあえなく断念した。むべなるかな。

haxibamihaxibami

エラー元のコードに立ち返ってみる。該当箇所はpngjsをrequireする際にpixelmatchの内部から引っ張っているらしい。おそらくはこのpngjsが存在しなくてコケているのだろう。

このへんで頭を冷やし、Vercelのデプロイ時の挙動に思いを馳せてみる。Vercel上のServerless Functionは、ビルド時に依存関係をトレースされてから必要なもののみがデプロイされるようになっている(らしい)。この過程はビルドログにも(ちょっとだけ)残っている。

ではVercelはどのようにコードをトレースしているのか? 調べた感じ、@vercel/nftが使われているようだ。ローカルで問題なく動作していたということは、このトレースの過程で必要なコードを把握しきれておらず、それによってデプロイ後にエラーを吐いた可能性がある。

haxibamihaxibami

そこで@vercel/nftのリポジトリを漁ると、以下のようなPull Requestを発見した。

https://github.com/vercel/nft/pull/281

Adds unit and integration tests for the pixelmatch package which requires a special case for including the bin directory to correctly trace the dependency pngjs

Fixes a playwright bug https://github.com/microsoft/playwright/blob/7f513360681d2517caa24d266def9b3a7be4f469/packages/playwright-core/src/utils/comparators.ts#L23-L24

どうやら当たりのようだ。しかもマージされたのが(執筆時点より)20時間前! 直後に新しいリリース(v0.18.1)も出ており、これが反映されればエラーが解決するかもしれない。

haxibamihaxibami

@vercel/nftに依存しているライブラリの中に、@serverless-stack/nextjs-lambdaがある。名前からしてこれがNext.jsのLambda環境に使われていそうだが(完全に勘)、こちらは現時点ではまだ上流の更新を反映していない。というわけで、一旦このパッケージの更新を待ってみる。

このスクラップは2022/04/13にクローズされました