0
0

More than 1 year has passed since last update.

chartjs-node-canvasで動的OGP画像を生成する関数をVercelにデプロイするのに苦労した話

Posted at

とあるサービスの開発をしているとchart.jsで生成したグラフをOGP画像にする必要が出て、Vercelならサーバレス関数を無料でデプロイできると知り試したのですが、謎のエラーが発生して困っていました。
その回避策(?)をとりあえず見つけたのでメモ書き程度に書きます。

version

canvas: 2.6.1
chartjs-node-canvas: ^3.2.0
chart.js: ^3.5.0

発生してたエラー

ERROR   Unhandled Promise Rejection 
{
"errorType":"Runtime.UnhandledPromiseRejection",
"errorMessage":"Error: Cannot find module 'canvas'\n
Require stack:\n
- /var/task/node_modules/chartjs-node-canvas/dist/freshRequire.js\n
- - /var/task/node_modules/chartjs-node-canvas/dist/legacy.js\n
- - /var/task/node_modules/chartjs-node-canvas/dist/index.js\n
- -  /var/task/api/index.js","reason":{"errorType":"Error","errorMessage":"Cannot find module 'canvas'\n
- Require stack:\n- /var/task/node_modules/chartjs-node-canvas/dist/freshRequire.js\n
- - /var/task/node_modules/chartjs-node-canvas/dist/legacy.js\n
- - /var/task/node_modules/chartjs-node-canvas/dist/index.js\n
- - /var/task/api/index.js",
- "code":"MODULE_NOT_FOUND",
- "requireStack":[
- "/var/task/node_modules/chartjs-node-canvas/dist/freshRequire.js",
- "/var/task/node_modules/chartjs-node-canvas/dist/legacy.js",
- "/var/task/node_modules/chartjs-node-canvas/dist/index.js",
- "/var/task/api/index.js"],
- "stack":[
- "Error: Cannot find module 'canvas'","Require stack:",
- "- /var/task/node_modules/chartjs-node-canvas/dist/freshRequire.js",
- "- /var/task/node_modules/chartjs-node-canvas/dist/legacy.js",
- "- /var/task/node_modules/chartjs-node-canvas/dist/index.js",
- "- /var/task/api/index.js",
- "    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:902:15)",
- "    at Function.resolve (internal/modules/cjs/helpers.js:98:19)",
- "    at Object.exports.freshRequire (/var/task/node_modules/chartjs-node-canvas/dist/freshRequire.js:6:34)",
- "    at new ChartJSNodeCanvas (/var/task/node_modules/chartjs-node-canvas/dist/new.js:23:39)",
- "    at module.exports (/var/task/api/index.js:14:31)",
- "    at Server.<anonymous> (/var/task/___vc/__helpers.js:813:19)",
- "    at Server.emit (events.js:375:28)",
- "    at parserOnIncoming (_http_server.js:897:12)",
- "    at HTTPParser.parserOnHeadersComplete (_http_common.js:126:17)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: Error: Cannot find module 'canvas'",
- "Require stack:",
- "- /var/task/node_modules/chartjs-node-canvas/dist/freshRequire.js",
- "- /var/task/node_modules/chartjs-node-canvas/dist/legacy.js",
- "- /var/task/node_modules/chartjs-node-canvas/dist/index.js",
- "- /var/task/api/index.js",
- "    at process.<anonymous> (/var/runtime/index.js:35:15)",
- "    at process.emit (events.js:387:35)",
- "    at processPromiseRejections (internal/process/promises.js:245:33)",
- "    at processTicksAndRejections (internal/process/task_queues.js:96:32)"]}
Unknown application error occurred

もちろんcanvasモジュールはpacakge.jsonに記述されていましたが、存在しないと言われてしまいました。

回避策

次のrequire('canvas')を加える(使わなくても必要)

const { ChartJSNodeCanvas } = require('chartjs-node-canvas');
const canvas = require('canvas'); // ポイント

package.jsonのvercel-buildを設定する。

"scripts": {
      "vercel-build": "yum install libuuid-devel libmount-devel && cp /lib64/{libuuid,libmount,libblkid}.so.1 node_modules/canvas/build/Release/"
    }

これだけでグラフは表示されましたが、文字が表示されなかったのでフォントの登録が必要です。
フォントの登録はREADMEに書いてあったChartJS.defaults.global.defaultFontFamilyでは動かなかったので、chart.jsの公式ドキュメントを確認してChartJS.defaults.font.familyにしました。

サンプルレポジトリ
https://github.com/karintou8710/vercel-chartjs-node-canvas

なぜこれで動いたの?

全くわからないです...
エラーメッセージに書いてある/var/task/node_moduleの中身をrequire('canvas')を加えない場合と比較したところ、加えない場合はcanvasとその依存関係にあるモジュールがインストールされていませんでした。
vercelの最適化が関係しているのか?と最初は考えたのですが、そもそもpackage.jsonに書いてあるのにインストールされないのは不思議です。
もし理由が分かる方がいればぜひコメントで教えて頂きたいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0