M1 Macでpuppeteerを動かす方法(2020年12月21日時点)


動作環境

Mac Book Air 2020 M1
macOS Big Sur 11.0

エラー内容

ヘッドレス Chrome Node API 「Puppeteer」 - Qiitaを参考にpuppeteerを動かしてみようとした時に下記コマンドが arm64ではエラーが出たのでその対処方法を書きます。

yarn add puppeteer
buzzword111@buzzword111-MacBook-Air Puppeteer % yarn add puppeteer
yarn add v1.22.10
info No lockfile found.
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
error /.../Puppeteer/node_modules/puppeteer: Command failed.
Exit code: 1
Command: node install.js
Arguments: 
Directory: /.../Puppeteer/node_modules/puppeteer
Output:
The chromium binary is not available for arm64: 
If you are on Ubuntu, you can install with: 

 apt-get install chromium-browser

/.../Puppeteer/node_modules/puppeteer/lib/cjs/puppeteer/node/BrowserFetcher.js:112
            throw new Error();
            ^

Error
    at /.../Puppeteer/node_modules/puppeteer/lib/cjs/puppeteer/node/BrowserFetcher.js:112:19
    at FSReqCallback.oncomplete (node:fs:199:21)
info Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.

puppeteerを動かす方法

1.ARM64版のGoogle Chromeをインストールする。


インストールするGoogle Chromeの実行ファイルは下記に配置されます。
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome

2.puppeteerの代わりにpuppeteer-coreをyarn addする。

yarn add puppeteer-core
buzzword111@buzzword111-MacBook-Air Puppeteer % yarn add puppeteer-core
yarn add v1.22.10
info No lockfile found.
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...

success Saved lockfile.
success Saved 51 new dependencies.
...

3.puppeter 5.5.0時点ではまだM1 Macに対応していないのでパッチを手動であてる。

// node_modules/puppeteer-core/lib/cjs/puppeteer/node/Launcher.js L:73
if (os.arch() === 'arm64' && false) { // ← && falseを追記
    chromeExecutable = '/usr/bin/chromium-browser';
}


https://github.com/puppeteer/puppeteer/issues/6641#issuecomment-748965065

このパッチを適用しないと、Google Chromeの実行パス(executablePath)が固定で /usr/bin/chromium-browserで上書きされてしまう。

4.動作確認

const puppeteer = require('puppeteer-core');

(async () => {
  const browser = await puppeteer.launch({
    executablePath:
      '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
  })
  const page = await browser.newPage()
  await page.goto('https://example.com')
  await page.screenshot({ path: 'example.png' })

  await browser.close()
})()