Vue js上でGoogleカレンダーのデータを取得して表示しようと思いましたが思いの外苦労しました。
環境はVue.js(Composition API)+TypeScriptです。フレームワークは Quasarを使用しています。
gapiよ、なぜ君はnode moduleに登録されていないのか?#
今どきのフロントエンジニアっ子はyarn addとか、npm installって叩くだけでその機能が追加できるnode moduleに慣れきっています。逆に、
なんて書き方は駄目なのです。Google APIはGitHubに公開さているので、yarn の一文を探すも見当たりません。マニュアルには
そう、まさかの 「scriptタグ」で取り込むスタイルなのでした。
に慣れきってしまった私はどうしていいかわかりませんでした。この衝撃、例えるなら今どきの若い子にフィルムカメラを渡すようなものです。
色々調べてみると技術的にかなり複雑なサービスらしく、それでmodule化ができないのかもしれないね?
node_moduleとしてインストールできない以上、マニュアルに従いScriptタグで取り込むしかありません。
一応Vue向けのGapiもありましたがあまり活発な開発とは言えず、
またVue3への移行も検討している中で余計な依存は増やしたくないため、今回は見送りました
VueJSでGapiを使えるようにしよう#
index.htmlのヘッダーで
と書いてもいいのですが、カレンダーのページでしか使わないので今回はCalendar.vueファイル内で呼び出すことにしました。
色々調べたところによると、onMountedの中でscriptタグを生成してDOMに追加することで使えるようです。
DOMの操作がやりたくないからVueを使うのですが今回は仕方ないですね
ということでコード
こんな感じで書くらしい。そして読み込みが終わると、いつのまにかgapiというオブジェクトが使えるようになるのです。
宣言してないのにいきなり使えるわけで、当然TypeScriptの姉御からはどえらいクレームが入ります。
当然ですよね・・・わたしも文句言いたいです。どこから生えてきたのそのgapiは?誰が使っていいっていったの?はい、おっしゃるとおり
ちなみにこの動画で「gapi」を「ギャッピー」と呼んでいました。だからgapiは「じーえーぴーあい」ではなく「ギャッピー」と呼びましょう
TypeScriptにGapiを認識させるまでの流れ#
gapiの型定義は、いつもの型定義郡からダウンロードできます。gapiの型定義はかなり細分化されて公開されているようでした。今回私が必要だったのは、
の3つです。これらをそれぞれインストールします。このインストール自体はおなじみの npm install でできるのでかんたんです。
インストールした型定義を使うために、少し工夫が必要なようです。まず、tsconfig.jsonを開き、次の文を追記します
compilerOptionsの中に、typesという配列を追加し、そこにgapiを書き込みます。gapiを使うVueファイルの中で、次の文を追記します
なかなか見慣れない書き方ですが、TypeScriptの公式にもかいてありました。さて、これでgapiに型が付くようになります。
gapi is not definedを回避するためのdeclare#
さて、gapiに型が当たりましたがgapi自体はVue上に定義されていません。それもそのはずで、
から直接やってくるのですから、未定義として怒られるのは当然です。
この問題を解決するためにTypeScriptにはdeclareという構文が用意されています。これを書けばundefinedの問題は解決できます。
これで良さそうに思いますが、どうもうまくいきません。そもそもgapiはnamespaceとして定義されているらしく、この書き方はできないようです。
せっかく型が決まったのにdeclareを書くとまたany型になってしまいました。
色々試行錯誤しましたが、とりあえず次のように書くことでTypeScriptさんを説得します。
正しい書き方かどうかはわかりませんが、これでエラーも消え、型もちゃんと持つようになりました。
最後にコード全文をのせておきます。書きかけのコードでゴミデータも混ざっていますがご了承ください。
とりあえず動かし方を確認したかっただけなので、かなり荒削りです。なお、コードの元ネタはGoogle公式のサンプルをベースにして、VueJS風に少しアレンジしたものです。
グーグルに認証を通してログインすると、ログイン中のユーザのカレンダー予定が画面に表示されます。なおAPI Keyの取得やCliantIDの作成はGoogle Developer Consoleから行います。
front endで実装するべきか、サーバ側で実装するべきか?#
ここまでの例はすべてフロントで完結するプログラムです。色々調べて見るとnodeJSのgapiも用意されているようです。
FirebaseであればCloud functionsで実装できそうな雰囲気がありますね。認証Tokenのリフレッシュが必要だったりTokenを保存する仕組みだったりと色々宿題もたくさんありますが。
1名で使うサービスであればフロントで十分かな?と思いますがグループでカレンダーを共有したい場合はサーバ側で実装しないと現実的に難しそうですね。