質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

Google Charts

Google Chartsは、円グラフ・棒グラフ・折れ線グラフなどのさまざまなグラフをJavaScriptで容易に表示できる無料のライブラリ。デザインやイベント処理といったカスタマイズができ、商用利用も可能です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1364閲覧

バックエンドでGoogle chartsを動かしたいがエラー発生

m.s.2000

総合スコア32

CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

Google Charts

Google Chartsは、円グラフ・棒グラフ・折れ線グラフなどのさまざまなグラフをJavaScriptで容易に表示できる無料のライブラリ。デザインやイベント処理といったカスタマイズができ、商用利用も可能です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2021/08/10 10:58

前提・実現したいこと

バックエンドにてGoogle chartsで作成したグラフ画像をサーバー内に保存したいがエラーが発生するので解決したい。

発生している問題

Google chartsをバックエンドで動かす手法として、npmで使える(モジュールという括り?) "google-charts-node" で動かしたがエラーが発生する。

提供されているgithub⇒ https://github.com/typpo/google-charts-node

動作環境

さくらVPS
Linux
CentOS8
Node.js
nodebrew
npm
google-charts-node
Javascript

該当のソースコード

Javascript

1◆sample.js・・・基本的に"google-charts-node" に記載されているExampleをそのまま適用 2 3const GoogleChartsNode = require('/root/node_modules/google-charts-node'); 4 5// Define your chart drawing function 6function drawChart() { 7 const data = google.visualization.arrayToDataTable([ 8 ['City', '2010 Population',], 9 ['New York City, NY', 8175000], 10 ['Los Angeles, CA', 3792000], 11 ['Chicago, IL', 2695000], 12 ['Houston, TX', 2099000], 13 ['Philadelphia, PA', 1526000] 14 ]); 15 16 const options = { 17 title: 'Population of Largest U.S. Cities', 18 chartArea: {width: '50%'}, 19 hAxis: { 20 title: 'Total Population', 21 minValue: 0 22 }, 23 vAxis: { 24 title: 'City' 25 } 26 }; 27 28 const chart = new google.visualization.BarChart(container); 29 chart.draw(data, options); 30} 31 32// Render the chart to image 33const image = await GoogleChartsNode.render(drawChart, { 34 width: 400, 35 height: 300 36});

エラー表示

CentOS8

1◆sample.js実行時のエラー表示 2 3/var/www/html/sample.js:32 4const image = await GoogleChartsNode.render(drawChart, { 5 ^^^^^ 6 7SyntaxError: await is only valid in async functions and the top level bodies of modules 8 at Object.compileFunction (node:vm:352:18) 9 at wrapSafe (node:internal/modules/cjs/loader:1031:15) 10 at Module._compile (node:internal/modules/cjs/loader:1065:27) 11 at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10) 12 at Module.load (node:internal/modules/cjs/loader:981:32) 13 at Function.Module._load (node:internal/modules/cjs/loader:822:12) 14 at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:79:12) 15 at node:internal/main/run_main_module:17:47

###完成する予定のチャート
イメージ説明

怪しいと感じる点

◆その1◆
sample.js中の「const chart = new google.visualization.BarChart(container);」のcontainerに何か定義が必要かも?
通常Google chartsをフロンドエンドで使う際も同じようなコードを使う。
その際<div>の#id等を入れるが、バックエンドで使う際は何を入れるべきなのか?

◆その2◆
sample.js中の「const GoogleChartsNode = require('/root/node_modules/google-charts-node');」では正しくmoduleを読み込めてないかも?
しかし読込不能のエラーは出ていないので問題なし?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

エラーメッセージの通り、async関数の中にawait式を書いていないのでエラーになっています。
ただしエラー後半にあるように、一定の要件を踏めば、async関数外でもawait式が書けます。("top-level await" [package.jsonに "type": "module"を付加し、requireをimportに変える、等])

サンプルコードは単にレンダリングした画像データを取得してるだけなので、表示するにはレスポンスとしてフロントに返すか、画像ファイルとして保存する必要があります。

例として、グラフ画像を保存する最小限のコードは下記のようになります。

なお、'/root/node_modules/google-charts-node'の部分は、御自身の環境に合わせて変えてください。

js

1const GoogleChartsNode = require('/root/node_modules/google-charts-node'); 2const fs = require('fs'); 3 4// Define your chart drawing function 5function drawChart() { 6 const data = google.visualization.arrayToDataTable([ 7 ['City', '2010 Population',], 8 ['New York City, NY', 8175000], 9 ['Los Angeles, CA', 3792000], 10 ['Chicago, IL', 2695000], 11 ['Houston, TX', 2099000], 12 ['Philadelphia, PA', 1526000] 13 ]); 14 15 const options = { 16 title: 'Population of Largest U.S. Cities', 17 chartArea: {width: '50%'}, 18 hAxis: { 19 title: 'Total Population', 20 minValue: 0 21 }, 22 vAxis: { 23 title: 'City' 24 } 25 }; 26 27 const chart = new google.visualization.BarChart(container); 28 chart.draw(data, options); 29} 30 31// Render the chart to image 32(async () => { 33 const image = await GoogleChartsNode.render(drawChart, { 34 width: 400, 35 height: 300 36 }); 37 fs.writeFileSync('./google-chart1.png', image); 38})();

最後の

(async () => { const image = await GoogleChartsNode.render(drawChart, { width: 400, height: 300 }); fs.writeFileSync('./google-chart1.png', image); })();

の部分がキモです。(async関数の中でawait式を実行)


top-level awaitを活用するなら下記のようになるかと。
※package.jsonに "type": "module"を追加しないとエラーになります。

js

1import GoogleChartsNode from 'google-charts-node'; 2import fs from 'fs'; 3 4// Define your chart drawing function 5function drawChart() { 6 const data = google.visualization.arrayToDataTable([ 7 ['City', '2010 Population',], 8 ['New York City, NY', 8175000], 9 ['Los Angeles, CA', 3792000], 10 ['Chicago, IL', 2695000], 11 ['Houston, TX', 2099000], 12 ['Philadelphia, PA', 1526000] 13 ]); 14 15 const options = { 16 title: 'Population of Largest U.S. Cities', 17 chartArea: {width: '50%'}, 18 hAxis: { 19 title: 'Total Population', 20 minValue: 0 21 }, 22 vAxis: { 23 title: 'City' 24 } 25 }; 26 27 const chart = new google.visualization.BarChart(container); 28 chart.draw(data, options); 29} 30 31// Render the chart to image 32const image = await GoogleChartsNode.render(drawChart, { 33 width: 400, 34 height: 300 35}); 36fs.writeFileSync('./google-chart2.png', image); 37

/root/node_modules/google-charts-node/lib/render.js
の23行目あたりを下記のように書き換えて、再実行した場合どうでしょうか。

js

1 2root/node_modules/google-charts-node/lib/render.js 23行目あたり 3const browser = await puppeteer.launch(); 4  この行を下のように書き換える。 5  ↓ 6const browser = await puppeteer.launch({ 7 headless: true, 8 args: ['--no-sandbox', '--disable-setuid-sandbox'] 9})

投稿2021/08/10 11:54

編集2021/08/11 11:20
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.s.2000

2021/08/10 17:15

丁寧にアドバイス頂きありがとうございます。 早速top-level awaitを活用しない方のコードを修正してみましたが、今度は違うエラーが出てしまいました。 どうやらブラウザを開こうとして失敗したと言っているようですが、 なぜバックエンドなのにブラウザが関係してしまうのでしょうか? 念のためですが、sample.jsの置き場所は任意の場所で問題ないでしょうか?(htmlやphpを実行する際に使っているディレクトリを使っています) ◆以下エラー------------------------------------------------------------ Error: Failed to launch the browser process! /root/node_modules/puppeteer/.local-chromium/linux-756035/chrome-linux/chrome: error while loading shared libraries: libX11-xcb.so.1: cannot open shared object file: No such file or directory TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md at onClose (/root/node_modules/puppeteer/lib/launcher/BrowserRunner.js:189:20) at Interface.<anonymous> (/root/node_modules/puppeteer/lib/launcher/BrowserRunner.js:179:65) at Interface.emit (node:events:406:35) at Interface.close (node:readline:586:8) at Socket.onend (node:readline:277:10) at Socket.emit (node:events:406:35) at endReadableNT (node:internal/streams/readable:1331:12) at processTicksAndRejections (node:internal/process/task_queues:83:21) 因みに"type": "module"を追記してtop-level awaitを活用する方も実行してみましたが、下記エラーが出てだめでした。 Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '/root/node_modules/google-charts-node' is not supported resolving ES modules imported from /var/www/html/sample.js
退会済みユーザー

退会済みユーザー

2021/08/10 23:27 編集

google-charts-node は、ヘッドレスブラウザを操作する puppeteer というライブラリを使用しています。 ブラウザ(Chrome)をヘッドレス起動し、その中でグラフを描画し、ブラウザ上で生成されたグラフ画像データを返す仕組みになっています。 掲題のエラーは、puppeteer を動かすのに必要な依存ライブラリが不足しているために生じているのだと思われます。 ----- 下記記載の方法を試してみて下さい。 https://github.com/puppeteer/puppeteer/issues/5361 ( yum install -y chromium libmng libXScrnSaver libXv を実行) ----- 上記でうまく行かない場合は、 https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md に記載の通り、下記を試してみてください。 ・https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#chrome-headless-doesnt-launch-on-unix の「CentOS Dependencies」に記載の依存ライブラリがインストールされているか確認する。 ・不足しているものがあれば、それをインストールする。 。インストール後、   yum update nss -y  を実行して nss ライブラリをアップデートする。 ---- 「Centos puppeteer」 や 「Centos8 puppeteer」で検索するといろいろ情報が出てきます。 --- >sample.jsの置き場所は任意の場所で問題ないでしょうか?(htmlやphpを実行する際に使っているディレクトリを使っています) 最初の段階で元のsample.js固有のSyntax Errorが出ているので、sample.js自体は読み込めており問題ないかとは思うのですが、 心配ならば、別ディレクトリでnpm initからやり直し、基本的なディレクトリ構成下で試されてみてはいかがでしょうか。
m.s.2000

2021/08/11 10:57

ありがとうございます。 「CentOS Dependencies」に上がっている不足ライブラリは"ipa-gothic-fonts"のみ何をやってもインストール出来なかったですが、色々調べた結果これはなくても良さそうなので放置して進めたところ、今度は以下のエラーが発生して壁にぶち当たってます。 調べた結果どうやら--no-sandbox引数を使用してChromeを起動すべきと書かれていますが、コードのどこに--no-sandboxを追記したらよいかわからないので教えて頂けないでしょうか? ◆以下エラー------------------------------------------------------------ Error: Failed to launch the browser process! [0811/193756.492559:ERROR:zygote_host_impl_linux.cc(89)] Running as root without --no-sandbox is not supported. See https://crbug.com/638180. TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md at onClose (/root/node_modules/puppeteer/lib/launcher/BrowserRunner.js:189:20) at Interface.<anonymous> (/root/node_modules/puppeteer/lib/launcher/BrowserRunner.js:179:65) at Interface.emit (node:events:406:35) at Interface.close (node:readline:586:8) at Socket.onend (node:readline:277:10) at Socket.emit (node:events:406:35) at endReadableNT (node:internal/streams/readable:1331:12) at processTicksAndRejections (node:internal/process/task_queues:83:21)
退会済みユーザー

退会済みユーザー

2021/08/11 11:20

--no-sandbox について回答欄に追記しました。
m.s.2000

2021/08/11 14:18

ご指示の通りrender.jsを修正したらようやくグラフ画像が保存出来ました。 何度も迅速にご指示頂き本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問