テクノロジの無駄づかい

日々の「ステュディオス」を求めて遠回りしがちなエンジニアの記録

GAS を Webpack + Babel でやってみた

久々に、Google Sheets の Add-on で欲しいものができたので作った。 良い機会なので、Webpack + Babel でビルドする構成を試してみた。 また、Google Apps Script (GAS)周りでもいくつか変化があったので取り入れてみた。

その記録。

作ったもの

会社で開発に使った時間を資産管理の関係で申請する必要があるのだが、Redmineのチケットに時間を記録すればOKとなっている。 一方、私は Togglで日々の時間管理をしている。

チケット終了ごとにRedmineに登録したり、締め日にTogglを見ながら手作業でRedmineに登録したりしてみたのだけど、どちらも面倒でやってられなかった。 やはり、普段の時間管理はTogglだけにしたい。 ということで、TogglからRedmineにデータ移行できるツールを作ることにした1

コマンドラインツールでも良かったのだけど、Redmineに登録する前にちょっと確認したり、調整したりできたほうが便利かと考えた。 となると Google Sheetsに一旦書き出して、それを登録できるものがよかろう、それならばAdd-onとして実装するのが最も便利に使えそうだと考えた。

それで作ったのは toggl2rm 。 次の機能を備えている。

以下に、toggl2rmを作る過程でキーとなった部分や新たに調べたことを記述する。

Webpack + Babelの設定

ざっと、TogglとRedmineAPIを叩く部分を GASのWebエディタで検証がてら実装した後、gappsコマンド(node-google-apps-script)を使って、ローカルにソースを持ってきて、Webkit + Babelでビルドする設定を行った。

webpack.config.babel.jsは次の通り設定した。

import GasPlugin from 'gas-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import path from 'path';

export default {
  context: path.resolve(__dirname, 'src'),
  entry: {
    code: './code',
    props: './props',
    utils: './utils',
  },
  output: {
    path: path.resolve(__dirname, 'dest'),
    filename: '[name].js',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: 'babel-loader',
      },
      {
        test: /\.json$/,
        exclude: /node_modules/,
        use: {
          loader: 'file-loader',
          options: {
            name: './[name].[ext]',
          },
        },
      },
    ],
  },
  plugins: [
    new GasPlugin(),
    new HtmlWebpackPlugin({
      filename: 'sidebar.html',
      template: 'sidebar.html',
      inject: false,
    }),
    new HtmlWebpackPlugin({
      filename: 'setting_dialog.html',
      template: 'setting_dialog.html',
      inject: false,
    }),
  ],
};

.babelrcは次の通り。

{
  "presets": ["env", "gas"]
}

この設定では次のプラグインを利用している。

gas-webpack-pluginbabel-preset-gasでES6なJSをいい感じのGAS向けコードにトランスパイルしてくれる。

html-webpack-pluginは結局 srcディレクトリからdestディレクトリにHTMLファイルをコピーするのにしか使っていない。 本当はHTMLに含まれるCSSとJSを別ファイルで実装し、ビルドによって一つのHTMLにまとめたかった。 html-webpack-pluginプラグインを更にインストールしていろいろ試したが、どうもうまくいかなかった。 最初からdestディレクトリにHTMLだけ置いたり、Webpack使わずコピーしても良かったのだけど、ソースとビルド成果物をはっきり分けたい+設定はwebpack.config.babel.jsに集約したいのでこうした。

また、JSを一つのファイルにビルドしてまとめても良かったのだけど、なんとなく大きな1ファイルを作りたくないなぁと思って、3つに分けた。 しかし、一つにしたほうが、グローバルに晒したくない関数を隠せるので今後見直すかもしれない。

ESLint

ESLintも導入してみた。 ベースの設定は eslint-config-airbnb-baseを利用した。 これだけだとGAS特有のオブジェクトの参照でエラーが出るので、それはeslint-plugin-googleappsscriptで解決した。

自分で実装したグローバルオブジェクトとconsole.error()等のログ出力系(後述のStackdriver Loggingのため)を個別に許可設定した。

私はAtomエディタを使っているので、エディタのLinterが実装時にリアルタイムでチェックしてくれ、便利だった。

上記を設定したのものはこんな感じ。

extends: airbnb-base

plugins:
  - googleappsscript

env:
  googleappsscript/googleappsscript: true

globals:
  Props: false
  Utils: false

rules:
  no-console: ["error", { allow: ["info", "warn", "error"] }]

clasp

最初は gappsコマンド(node-google-apps-script)を使っていた。 しかし、複数のGASのプロジェクトがある場合、個別にGoogle Drive APIの認証が必要なのにその認証情報の管理は~/.gapps 1ファイルで行われ、切り替えるのが不便だった。

汎用的な不満だと思うので認証情報ファイルをコマンド実行時に指定する方法があるのではと、リポジトリを久々に見るとディスコンしていた。 代わりにGoogle謹製の google/claspを使えと書かれていた。

claspを調べてみてgappsと比べ以下が優れていると思ったので乗り換えた。

  • GASプロジェクト毎の認証設定が不要(1回のログインですべてのGASプロジェクトの管理が可能)
  • GASスクリプトの作成も可能(gappsは先にGASスクリプトを作っておく必要がある)
  • ドキュメントに紐づくスクリプトの管理も可能(gappsでは不可)
  • Google謹製という安心感

使い方はこちらを参照 => GAS のGoogle謹製CLIツール clasp - Qiita

Stackdriver Logging

確か以前は console.log()はGASでは使えなかったと思うのだが、今は使える。 GASはサーバサイドで実行されるスクリプトなので、ブラウザのDev Toolには何も出力されない。 どこに出力されるかというと、Stackdriver というGoogle Cloud上のログサービスに出力される。

どうやら、去年の夏頃こうなったようだ3。 以前からGASにちゃんとしたロギングがほしいと思っていた。 Logger.log()では最後の実行分しか見れないので、どうしても必要な場合には スプレッドシートに書いたりしたものだ。 しかし、これからはStackdriver Loggingが使える。 DEBUG、INFO、WARN、ERRORという一般的なログレベルを設定して出力できるのも嬉しい。

Stackdriverは無料のサービスではないが、毎月無料枠があり、個人ユースではそれで足りるのではないかと思う。 今回はエラーログの記録に利用している。

ざっと調べてみた結果はこちら => GAS でStackdriver Loggingを使う - Qiita

最後に

久々に GASでの開発をやってみて、自分なりのモダンな開発構成を確立できたと思う。 gas-webpack-pluginがWebpack4に対応できていないのかどうもうまくトランスパイルできなかったので、実は今回はWebpack3を使っている。 そのうち対応されればアップデートしようと思う。

しばらく見ないうちにGASを取り巻く環境も色々変わっていた。 以前は自分にだけ自作Add-onをインストールする方法があったのだが、それがなくっている。代わりにテスト設定を作成してそこから起動すれば動かせる様に変更されようだ。少々めんどくさくなった。 その一方で、謹製CLIツールが用意されたり、ログ周りが強化されていた。
更に、GAS専用のマネジメントコンソールもできた。Google Driveでは他のドキュメントとごちゃまぜの管理だけど、こちらだとドキュメントに埋め込まれたGASも含め、すべてのGASのみを管理できる。 まだ、あまり調べていないが、バージョン管理と公開周りも開発版と公開版を別々に動かせるようにするためにちょっと変わったようだ。 このあたりの変更はChromeアプリのプラットフォームとしてGASを使っていくためであろうか?

何れにせよ、以前より開発しやすくなったと思う。 便利なサーバレス環境なので今後も活用していこうと思う。


  1. 個人的には全員でTogglに移行したほうが効率的なのではと思うものの、今、回っている仕組みを私の我儘トリガーで変更するほどでもないし、Togglも有料プランが必要になりそうで費用もいくらか発生してしまうので、個人的に解決する道を選択した。

  2. CSVでダウンロードする機能をTogglは提供している。しかし有料プランの機能。同等のデータはAPIを使えば取得でき、それを利用している。無料で有料機能相当を提供していることに気を使ってライセンスは CC-BY-NC-4.0 としている。

  3. G Suite Developers Blog: Stackdriver Logging for Google Apps Script is now available