Google Apps Script + Node.jsで簡単なツールを作ってみた

社内向けにモノは一応できてるけど、網羅的なエントリを書くほどでもないので、自分向けメモに permalink を与える試み。だいたいの概要が書いてあるので、あとはリンク先をたどってちょっと手を動かせば思い出せるんじゃないかな。

まとめ

  • すでに Google Apps を利用しているなら 24/7 で稼動する PaaS があるのと同義
  • 認証部分を Google Apps 側に丸投げできるので社内向け簡易アプリなどを用意するのに適している
    • しかもスマホ対応済み
  • しかも Google Apps のデータは作業者も履歴も全部残せる1
  • 言語は JavaScript のようなものなので、Web 系の人と親和性が高い
  • 管理画面をゼロから作る代わりに Spreadsheet を使うと他の業務と親和性が高いのでよさげ
    • 例えば VBA で実現していたようなものを Apps Script に置き換えると引き継ぎしやすいアプリに仕立てられそう
  • Node.jsのツールチェインはあってもなくてもいいけど、他の普通の開発に近づける(DVCS + ITS)ためにはあった方がよい

Apps Scriptの特徴

  • Google Apps 上で動く、JavaScript を基本の構文として独自の Apps 用オブジェクトを持つ言語で記述する
  • 保存できるのは .gs コード(スクリプトファイル)と HTML
    • したがって asset は cdn でまかなう
  • Drive のドキュメント内で実行するスクリプトはもちろん、Web アプリや Web API として公開もできる
  • triggerという仕組みで自動実行できる
    • time based ( cron のようなもの ) , event based な trigger がある
  • container bound script と standalone script がある

Apps Scriptの種類

  • Container Bound Script
    • ドキュメントに紐付く
  • Standalone Script
    • Drive上に独立して存在する

Contianer Bound の方が入りは楽。(Triggerに対応する function が組み込みであるとか。)Standalone の方がエンジニアリング的な扱いは楽。

Standalone Script は Drive 上に独立して存在するので Drive API を通じてアクセス、管理できる。これを利用することで手元でバージョン管理することができる。一方で Trigger が Programmable になってしまうので扱いがちょっとだけ手間だが、分かってしまえばそれほど面倒ではない。

Standalone Scriptの開発手法

エディタとしては Google Apps 上の Script Editor が恐らくいちばんマシだが、動的な変数などに対しては補完が効かないので、ある程度基本的な部分ができたら結局動かしながらテストするしかない。

local <-> remoteの転送

いくつかあるが、

がいちばんマシ。

gas init で

  • 認証情報の取得
  • remote にあるファイルの一覧を作成して sync できるように準備を行う
    • remoteでファイルを増やした場合はもう一度 gas init するのかな?

なぜか remote .gs を local .js に置き換える機能があるが、これは拡張子の設定を自由にできないエディタを使って開発するための配慮かな。

テスト

npm 上の以下を組み合わせたうえでブラウザ上で所定の function を実行するのが今のところよさげ。Qiita 上の記事といい、こうしたツールといい、実は Google Apps Script は日本人の方が盛り上がっているのか。

codegs は google apps script 用の browserify のようなもの。

これらを組み合わせて GAS 上で実行可能な spec ファイルを作り、gas upload したのち手でテストを実行する。結果は gas-console で確認する。この作業がすべて CLI で完結するとかなり快適なのだが、たぶん難しいのでいったんこれで形にしておく。

CoffeeScript

local で coffee -> js 変換後のコードを上げれば普通に動く。別にタスクランナーとか使わなくてもこんな感じで大丈夫。

秘密情報

環境変数をセットすることはできないが、Script や Spreadsheet などの Property として値を保存することができる。これを利用すればコードの中に生々しく認証情報などを保存せずにすむ。

Programmable Trigger

TriggerBuilder で trigger を特定のドキュメントに対して付与する。実行する function の名前を与える形なので、引数を与えることはたぶんできない。

ライブラリ

Google Apps Script 用に公開されているライブラリはスクリプトエディタ上で追加することができる。

※ この部分を CLI で自動化することは恐らくできない。

GS は JavaScript との互換性がどの程度のものなのかイマイチよく分からない(なんとなく ES5 は動きそう)ので、UnderscoreGS は便利かも。

Webアプリとしてできること

  • アクセス権限は Drive と同様に設定できる(超重要!)
  • GET と POST の両方を受け付ける
    • doGet(), doPost() のみ
    • JSON API のようなものを作れる
    • ストレージは Spreadsheet などを使う2
  • HTML も返せるので、例えば SPA のようなものを作ることもできる

deploy

Google Apps 上でいちいち deploy をしないとアプリ側は更新されない。

版管理でバージョンを刻み、deploy でそのバージョンを指定する。これが済まないとアプリ側は更新されない。(バージョンを変えても URL は変わらない)

生成される HTML がすごい。ユーザー認証を通過した人にだけ表示される HTML を JavaScript を通じて提供するためか。よくこんな仕組み実現したな。

API にすると API ID しか当たらないので、何かクライアント側もただのウェブアプリのようにはできないっぽい。むしろただの JSON API のエンドポイントに使いたいだけなら Web アプリとして deploy した方がいいのか?

staging はプロジェクトをコピーする。コピーするとバージョン情報と deploy の情報のないプロジェクトができあがる。

CDN

Google Apps Script では HTML 以外の asset を置くことができない。そのために HTML も CSS もライブラリ用の JS も concat するというアプローチがあるが、全部 CDN という選択肢もありそう。

もうなんでもかんでも CDN で動かせるみたい。

クライアントアプリとしてできること

  • FetchUrlApp サービスで HTTP リクエストを飛ばせる
    • 名前に反して POST もできる
    • これを使って AWS S3 を扱うライブラリもサードパーティーだが存在する
  • Mail は Google Apps の MailApp を叩けば ok

add-on

「アドオン」は古くて「ライブラリ」として公開がイマドキらしい。

今のところの感想

Node.js のツールチェインは使っているが結局実行は Google Apps 上で行うので、そこまでサクサク開発できない。

うちのネットワーク環境の問題なのか、Script Property への値の保存時にやたらと IO Error が起きたり、gas upload 時に基本的な文法エラーで Drive 上に script が保存できない(しかもエラーの意味がよく分からない)とか、割と扱いにくいことは起きる。3

少なくとも大規模なアプリを作るのにはやはり向いていないと思う。規模をでかくするなら API 化してクライアント側サーバ側別々に開発するのがいいと思う(サーバ側のスクリプトのテストを自動化しにくいので)けど、そこまで Google Apps でやるの? という気がしちゃう。

HTML を組んで Web アプリを作ることもできるが、イマドキの Web アプリ開発のサクサク感からはほど遠い感じがするので、踏み込むかどうかは思案のしどころ。Apps の画面を活かしつつやるのがお手頃感を残しつつゼロベース開発を避けてコストダウンできるポイントじゃないかなーという気がしている。

今後は Electron と組み合わせる、みたいなのができるとギョウミーな文脈ではそれなりに便利なんじゃないかなーなんてことを妄想していたりする。そこまで本格的なことを今の環境でやるかどうかは分からないけど。

参考

  1. こういうのゼロから作ると意外に手間 

  2. あるいは他のAPIを使うこともできるが、そこまでやるならGoogleAppsでなくてもいいような… 

  3. 文法エラーがあると保存すらできないっていう設計はどうなんだ 

More

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Develop Document Jekyll