Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9233

Vercel上でPuppeteerを動かす

$
0
0

試してみたら動かせました。調べてもそれっぽいの無さそうだったのでメモです。

参考にしてるコードとお断り

ググったらこちらのプルリクが当たったので、こちらをもとに書いてますが、現状の公式なやり方かはわかりません。

https://github.com/vercel/now-examples/pull/207/files

その他参考: VercelでLINE BOTを動かす 2020年5月版

実装

chrome-aws-lambda + puppeteer-coreを利用

vercelはAWS Lambda上で動いてる模様なので、動作するChromium Binaryもchrome-aws-lambdaを使うと良いっぽいです。

また、バイナリはchrome-aws-lambdaを利用するということで、バイナリが梱包されてないpuppeteer-coreを使います。

$ yarn add chrome-aws-lambda

ここで最新バージョンのchrome-aws-lambdaがインストールされますが、この時のバージョンにあわせてpuppeteer-coreもインストールしましょう。

僕の場合、chrome-aws-lambdaをインストールしたら3.1.1だったのでpuppeteer-coreもバージョン指定してインストールします。(なにも指定しないでインストールしたら3.2.0がインストールされて、デプロイ後に怒られました。

$ yarn add puppeteer-core@3.1.1
  • package.jsonのdependenciesで確認

こんな感じでこの二つのモジュールのバージョンが合ってれば大丈夫です。

  "dependencies": {
    "chrome-aws-lambda": "^3.1.1",
    "puppeteer-core": "3.1"
  }

プログラムの作成

プロジェクトのルートにapiフォルダを作成し、その中に任意のjsファイルを作成します。

api/run-puppeteer.jsとします。

Node.jsなコードもLambdaぽい書き方になります。

api/run-puppeteer.js
constchrome=require('chrome-aws-lambda');constpuppeteer=require('puppeteer-core');module.exports=async(req,res)=>{const{URL='https://twitter.com/n0bisuke'}=req.query;constbrowser=awaitpuppeteer.launch({args:chrome.args,executablePath:awaitchrome.executablePath,headless:chrome.headless,});constpage=awaitbrowser.newPage();awaitpage.goto(URL);//URLにアクセス// Get the "viewport" of the page, as reported by the page.constdimensions=awaitpage.evaluate(()=>{return{width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,title:document.title,deviceScaleFactor:window.devicePixelRatio};});console.log('Dimensions:',dimensions);awaitbrowser.close();//アクセスしたページのタイトルを取得res.send(`${URL}のページタイトルは「${dimensions.title}」だよー!`);}

こんな感じになりました。

補足

apiフォルダにjsファイルを作ってこんな感じに書くのが基本ぽいです。AWS Lambdaをちゃんと使ったことないけど、一つ上の階層でrequire/importしてる処理があるんでしょうね。

module.exports = (req, res) => {
  const { name = 'World' } = req.query
  res.send(`Hello ${name}!`)
}

参考: https://vercel.com/docs/runtimes#official-runtimes

デプロイして試す

$ vercel

デプロイして、 https://発行されたドメイン/api/jsファイル名にアクセスします。
今回の場合はhttps://発行されたドメイン/api/run-run-puppeteerです。

api/run-puppeteer.jsの中身参照ですが、アクセスすると、puppeteerが動いて指定したURL(デフォはhttps://twitter.com/n0bisuke)にアクセスしてタイトルを取得してきます。


その他: scheenshotの画像保存が出来なかった

これは設定問題かもしれないですが、ログにこんな感じのが出てたので、Vercel上でファイル書き込みは出来ないのかも。

"errorMessage":"EROFS: read-only file system, open 'example.png'

(出来そうだって話あれば教えて下さい!)

補足: 毎回デプロイが面倒なのでローカルで試す

api/run-puppeteer.jsをこんな感じで書いてローカルでも試せました。

  • ローカル環境
    • mac os catalina
    • Node.js v14.3.0

puppetterを追加します。

$ yarn add puppetter

process.env.AWS_LAMBDA_FUNCTION_VERSIONがあればVercel上での動作と判断してます。

api/run-puppeteer.js
letchrome={};letpuppeteer={};//puppeteer main processconstrun=async(puppeteer,chrome={},URL='https://twitter.com/n0bisuke')=>{constbrowser=awaitpuppeteer.launch({args:chrome.args,executablePath:awaitchrome.executablePath,headless:chrome.headless,});constpage=awaitbrowser.newPage();awaitpage.goto(URL);// Get the "viewport" of the page, as reported by the page.constdimensions=awaitpage.evaluate(()=>{return{width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,title:document.title,deviceScaleFactor:window.devicePixelRatio};});awaitbrowser.close();returndimensions;}if(process.env.AWS_LAMBDA_FUNCTION_VERSION){//Vercelchrome=require('chrome-aws-lambda');puppeteer=require('puppeteer-core');}else{//Local Testpuppeteer=require('puppeteer');constURL=`https://protoout.studio`;run(puppeteer,{},URL).then(res=>console.log(res));}module.exports=async(req,res)=>{const{URL='https://twitter.com/n0bisuke'}=req.query;constdimensions=awaitrun(puppeteer,chrome,URL);res.send(`${URL}のページタイトルは「${dimensions.title}」だよー!`);}

手元で実行

$ node api/run-puppeteer.js

vercel devコマンドでも試せるかもですが、サーバー起動などで時間かかるのでこの手の処理だけならこっちの方が早いかなぁという感触です。

まとめや所感など

最終形のコードはディレクトリごとあげておきました。

https://github.com/n0bisuke/vercel-puppeeter-sample

chrome-aws-lambdaというのがあることを知れたのが収穫かも。あと、process.env.AWS_LAMBDA_FUNCTION_VERSIONで判定してるけどもっとよいやり方ないのかな......

あとやはりファイル書き込みが出来ない(スクショ保存)のかも気になるので誰か分かる方いたらコメントを...笑

Herokuなどでも問題ないけどVercel上でもpuppeteer動かしたい場合もあるかもしれないので誰かの参考になれば幸いです。


Viewing all articles
Browse latest Browse all 9233

Trending Articles