クラウドでPuppeteerをデプロイする方法：ソリューションの比較

![表紙](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/315b4d81-e3bf-1fdb-234b-4bf5cf77b660.png)

[Puppeteer](https://pptr.dev/) は、ウェブページでの人間の操作をシミュレーションできる強力なツールであり、ウェブページのスクリーンショット、PDF生成、自動テスト、稼働監視、ウェブスクレイピング、コンテンツ追跡など、さまざまなユースケースに対応しています。

Puppeteer をクラウドで運用することが適しているシナリオは数多くあります。例えば：

- CI/CD パイプラインで API を使用して自動テストをトリガーする。
- 定期的にウェブサイトの可用性を確認するために cron ジョブを使用する。
- 大規模で分散型のウェブスクレイパーを実行する。

従量課金制でスケーラブルなサーバーレスコンピューティングは、ブラウザの自動化タスクに非常に適しています。しかし、DigitalOcean のようなほとんどのプラットフォームは仮想マシンしか提供しておらず、アイドル時間に料金を支払う必要があり（多額の費用が無駄になります！）、現在 Puppeteer をサーバーレスで実行できるプラットフォームは限られています：[**Leapcell**](https://leapcell.io/?lc_t=q_ps)、[**AWS Lambda**](https://aws.amazon.com/lambda/)、および [**Cloudflare Browser Rendering**](https://developers.cloudflare.com/browser-rendering/) です。

この記事では、これらのプラットフォームについて、Puppeteer の典型的なタスクを実現する方法、その長所と短所を探ります。

# タスク

よくある Puppeteer のユースケースとして、ウェブページのスクリーンショットをキャプチャする例を見てみましょう。

このタスクは以下のステップで構成されます：

1. 指定された URL にアクセスする。
2. ページのスクリーンショットを撮る。
3. 画像を返す。

# [Leapcell](https://leapcell.io/?lc_t=q_ps)

**コード例:**  
```js
const puppeteer = require('puppeteer');
const { Hono } = require('hono');
const { serve } = require('@hono/node-server');

const screenshot = async (url) => {
  const browser = await puppeteer.launch({ args: ['--single-process'] });
  const page = await browser.newPage();
  await page.goto(url);
  const img = await page.screenshot();
  await browser.close();

  return img;
};

const app = new Hono();

app.get('/', async (c) => {
  const url = c.req.query('url');

  if (url) {
    const img = await screenshot(url);
    return c.body(img, { headers: { 'Content-Type': 'image/png' } });
  } else {
    return c.text('Please add an ?url=https://example.com/ parameter');
  }
});

const port = 8080;
serve({ fetch: app.fetch, port }).on('listening', () => {
  console.log(`Server is running on port ${port}`);
});
```

Leapcell は、どのようなアプリケーションでもサーバーレスで展開できる汎用プラットフォームです。しかし、HTTP リクエスト専用に設計されていないため、設定がやや複雑になることがあります。HTTP リクエストハンドラーを手動で作成する必要があります。

## ローカル開発

デバッグは簡単です。他の Node.js アプリケーションと同様に `node index.js` を実行するだけで完了します。

## 展開

ビルドコマンド、実行コマンド、サービスポートを指定して展開します（下図参照）。

![Config](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/68031a61-42b3-f038-2809-394e2b8f2e33.png)

展開が完了すると、アプリケーションはオンラインで利用可能になります。

## まとめ

**✅ 長所:**

- ローカル環境とクラウド環境が一貫しており、デバッグが簡単。
- 公式 Puppeteer ライブラリをサポート。

**❌ 短所:**

- 設定がやや複雑で、独自の HTTP ハンドラーを記述する必要がある。

# [AWS Lambda](https://aws.amazon.com/lambda/)

**コード例:**  
```js
const chromium = require('chrome-aws-lambda');

exports.handler = async (event) => {
  let browser = null;

  try {
    browser = await chromium.puppeteer.launch({
      args: chromium.args,
      defaultViewport: chromium.defaultViewport,
      executablePath: await chromium.executablePath,
      headless: chromium.headless,
    });

    const page = await browser.newPage();
    await page.goto(event.url);

    const screenshot = await page.screenshot();

    return {
      statusCode: 200,
      headers: {'Content-Type': 'image/jpeg'},
      body: screenshot.toString('base64'),
      isBase64Encoded: true,
    };
  } catch (error) {
    return {
      statusCode: 500,
      body: 'Failed to capture screenshot.',
    };
  } finally {
    if (browser !== null) {
      await browser.close();
    }
  }
};
```

AWS Lambda を使用する場合、`puppeteer-core` とサードパーティの Chromium ライブラリ（例：[`alixaxel/chrome-aws-lambda`](https://github.com/alixaxel/chrome-aws-lambda)）を組み合わせる必要があります。これは、AWS が [250MB の制限](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html) を Lambda 関数に課しているためです。Puppeteer にバンドルされているデフォルトの Chromium はこの制限を大幅に超えるため（macOS：約170MB、Linux：約282MB、Windows：約280MB）、軽量化された Chromium の使用が必要です。

## ローカル開発

ランタイム環境の違いにより、ローカルでのデバッグには複雑な設定が必要です。詳細は `alixaxel/chrome-aws-lambda` の[ガイド](https://github.com/alixaxel/chrome-aws-lambda/wiki/HOWTO:-Local-Development)を参照してください。

## 展開

`node_modules` を ZIP ファイルとしてアップロードする必要があります。ユースケースによっては、Lambda Layers を設定する必要がある場合もあります。主要なビジネスロジックは AWS コンソールで直接記述し、保存して実行します。

## まとめ

**✅ 長所:**

- コード構造がシンプル。

**❌ 短所:**

- サードパーティの Chromium ライブラリに依存するため、潜在的なリスクがある。
- ローカルデバッグが複雑。
- ZIP アップロードや Lambda Layers の設定が必要で展開プロセスが面倒。

# [Cloudflare Browser Rendering](https://developers.cloudflare.com/browser-rendering/)

**コード例:**  
```js
import puppeteer from '@cloudflare/puppeteer';

export default {
  async fetch(request, env) {
    const { searchParams } = new URL(request.url);
    let url = searchParams.get('url');
    if (url) {
      url = new URL(url).toString(); // normalize

      const browser = await puppeteer.launch(env.MYBROWSER);
      const page = await browser.newPage();
      await page.goto(url);
      const img = await page.screenshot();
      await browser.close();

      return new Response(img, {
        headers: {
          'content-type': 'image/png',
        },
      });
    } else {
      return new Response('Please add an ?url=https://example.com/ parameter');
    }
  },
};
```

Cloudflare Browser Rendering は比較的新しいサーバーレス Puppeteer ソリューションです。AWS Lambda と同様に、公式 Puppeteer ライブラリはサポートしておらず、Cloudflare が提供する Puppeteer バージョンを使用します。

Cloudflare のライブラリはサードパーティ製よりも安全ですが、更新サイクルが遅いため不満を招く可能性があります。実際、[5 か月以上更新されていません](https://developers.cloudflare.com/browser-rendering/changelog/)。

さらに、Cloudflare Browser Rendering には以下の制限があります：

- Worker Pro ユーザーのみに利用可能。
- 各 Cloudflare アカウントは、1 分間に最大 2 台のブラウザを作成可能で、同時に実行できるブラウザも最大 2 台。

## ローカル開発

ローカルでのデバッグには[複雑な設定](https://developers.cloudflare.com/workers/testing/local-development/)が必要です。

## 展開

関数をオンラインで記述し、保存して実行します。

## まとめ

**✅ 長所:**

- コード構造がシンプル。

**❌ 短所:**

- 更新サイクルが遅い Cloudflare の Puppeteer ライブラリに依存。
- ローカルデバッグが複雑。
- 有料プランやその他の制限によりアクセスが制限される。

# 結論

この記事では、サーバーレス Puppeteer の主要な展開プラットフォームである Leapcell、AWS Lambda、Cloudflare Browser Rendering を比較しました。それぞれに長所と短所があります。

どのプラットフォームが好みですか？他にサーバーレス Puppeteer 展開ソリューションをご存じですか？コメントでぜひ共有してください！

---

Puppeteer プロジェクトをオンラインで展開する予定がある場合、上記で比較したように、[Leapcell](https://leapcell.io/?lc_t=q_ps) が適した選択肢です。

展開ガイドについては、[こちらのドキュメント](https://docs.leapcell.io/examples/testing/puppeteer/)をご覧ください。

[![Leapcell](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/91764880-5acd-4658-a7ad-6e1aac1261c5.png)]((https://leapcell.io/?lc_t=q_ps))