Modern development with Google Apps Script
Google Apps Script(以下、gas)で今っぽいモダン環境で開発出来たから書いておく。
背景
以前、会社の業務時間を管理する Slack ボットを作った(ネタ元は宮本さん)。日報が Google Drive で管理されていることもあって gas で作られている。
作って運用してみたら社内で結構好評で徐々に利用者が増えていった。
そうなるとトラブルがあったときに対応出来るような作りにしておきたい。ただ、雑なパクリだったから謎構成になってしまったし、QUnit という一昔前のテスティングフレームワークを使っていたりで、何か手を入れるとしても触りたくない気持ちしかなかった。
gas のデメリットを解消しつつ良い感じに作り直せないかなーとやってみた。
モダンな JavaScript とは
以下の要件で書けるようにした。
- ES2015 で書く
- mocha でテストを回す
- ESLint で構文チェックする
- Yarn でパッケージ管理する
- node-google-apps-script でデプロイ
ES2015 で書く
browserify でトランスパイル出来るようにした。とはいえ、gas は独自の JavaScript 仕様なため少し工夫をする必要がある。
export default が使えない
export default な構文を普通にトランスパイルしてもエラーで動かせない。
babel-plugin-transform-es3-member-expression-literals と babel-plugin-transform-es3-property-literals というプラグインを追加する必要がある。
これがあればトランスパイルしてもエラーが出ずに実行出来る。
.babelrc
{ "plugins": [ "transform-es3-member-expression-literals", "transform-es3-property-literals" ] }
便利関数が微妙に使えない
確認出来た限りだと find と引数展開は使用出来なかった(gas がエラーを吐く)。もしかしたら、これもプラグインで解決出来るのかもしらんが、調べる気にならなかった。
愚直に forEach を使ってやった。forEach は使えた。
mocha でテストを回す
テストで問題になるのも gas のクラス達。
ネットを彷徨うと様々な人がテストで困っている様子。
解決案は以下のようなものが見つかる。
テスト用の gas スクリプトを作って、gas 上で回す
CI サービスが使えないし諦め。
Sinon.JS でモックする
さすが簡単にモックは作れる。問題は、実在するクラスがないとモックを使用出来ないということだ。
UrlFetchApp をモックするには UrlFetchApp のクラスが用意されていないといけない。
モックを作って、テスト用のクラスも作ってとだるいので諦めた。
gas-local を使う
ES2015 では動かせなかった。諦め。
たぶん頑張れば使えるんだと思う。
自作モックを使う
gas-local のやり方見てたら自分でモック作ればいいじゃんねと気付いた。
やってみた。
// setup.js import SpreadsheetApp from './mock/SpreadsheetApp'; global.SpreadsheetApp = SpreadsheetApp;
// SpreadSheetApp.js import Spreadsheet from './Spreadsheet'; export default { openById() => (Spreadsheet), };
// SpreadSheet.js export default { // do something... };
利用する gas の API を適当に定義すれば問題なくテストに使える。
少々めんどくさいが、うまく動くので良い。
ESLint で構文チェックする
Airbnb の設定を利用した。
ちょっと厳しいところもあるので適当に緩めて。
ESLint を実行したときも勿論 gas のクラスは存在しないためエラーになる。
eslint-plugin-googleappsscript をプラグインとして読み込んでいれば良しなにしてくれる。
{ "extends": "airbnb", "plugins": [ "googleappsscript" ], "env": { "googleappsscript/googleappsscript": true }, .... }
ESLint は CI で回すのも便利だけど、git のフックを使うともっと良い。
# .git/hooks/pre-commit #! /bin/sh git diff --cached --name-only --diff-filter=AM | grep '\.js$' | xargs eslint
とやっておくだけで、コミット時に自動で ESLint が走って、エラーだとコミットが中断される。
Yarn でパッケージ管理する
npm と互換があるから使うのに何も困らなかった。
yarn add package_name
yarn add package_name --dev
yarn install
これだけ使えればだいたい事は足りる。
なにより yarn.lock でバージョンを固定出来るのが良い。npm shrinkwrap は嫌な思い出しかない。
node-google-apps-script でデプロイ
node-google-apps-script は Google 製のデプロイツール(といっても API を使ってアップロードするだけだが)。
gapps upload
とやるだけでアップロードしてくれる。
設定は API キー作って認証情報登録してアップロード先を指定するだけ。詳しくは README とか見て。
アプリケーションの公開までやってくれると最高なんだが、そこは手動でやらねばならん。微妙に使いづらい。
それでも自分でアップロードするのと比べると断然ラクなんだけど。
参考資料
大概先人が居るものだ。参考にした。
大変助かりました。
- Google Developers Blog: Advanced Development Process with Apps Script
- Google Apps Scriptの開発をモダンに行う方法 - Speee DEVELOPER BLOG
- Google App Scriptをモダンな開発っぽくする環境を作ってみた(ES6, browserify, eslint, mocha) - nagashigaki
- Google Apps ScriptでES Module(Babel)を使うときのTips - Qiita
- gulp と mocha を使って UrlFetchApp のテストをする方法 - Qiita
作ったリポジトリ。
GitHub - app2641/kintaiman_v2: 勤怠マン is inspired by Miyamoto-san.
以上。