私は普段 C++、C# といった (古典的) 言語を主に使います。
ですので、ブラウザ上のエディタで GAS のコードを書く際にストレスを強く感じます。
大きなストレスポイントは次の 2 点です。
- Git で管理するのが面倒
- 好きなエディタを使えない
また、JavaScript で class を用いる場合、C++ や C# のように直感的に書くことができず、せめて TypeScript で書けたらなぁ、とも思っていました。
が、同じ思いをしている方は本家 Google にもいたようで、
Google 謹製の clasp というものが 2018 年に生まれ、これら全ての問題が解決されました。
以降 GAS に触れる際には常に clasp を使い書いています。
clasp の解説は、あちこちにスマートにまとめられているので、私のように稀に GAS を書く人間が clasp についてまとめた記事など役に立たないでしょうが、「自分用のメモ書き」として残したいと思います。
なお、公式のインストラクションは「こちら」にまとめらています。
1. node 環境の準備
node が動く環境が必要です。
何かと node を使う機会はあるので、私はまず nvm をインストールし、node のバージョンをコントロールする環境を作るのですが、このあたりはそれこそ詳しいサイトが沢山あるので割愛します。
2. Google アカウントの準備
GAS を使う以上、Google アカウントは必須ですが、そのアカウントで Google Apps Script API を使用できるよう、下記ダッシュボードから ON にしておきます。(これを読まれている方はとっくに ON にしていると思いますが念のため)
https://script.google.com/home/usersettings
3. clasp のインストール
clasp の GitHub リポジトリのインストラクション通りです。
npm install -g @google/clasp
グローバル環境への影響を避けて -g (--global) オプションを使用しないインストールを案内されている方もいるようですが、clasp で他の開発プロジェクトに影響が出るように思わないですし、プロジェクトごとに毎回 clasp をインストールするのは寧ろ効率が悪いと思うので、私はインストラクション通り、-g オプションを使用します。
すなわち、以降は他の新規プロジェクトでも clasp のインストールは不要になります。
4. 新規プロジェクトの作成
大まかに次のような流れになります。(後述の 8. で改めてまとめてあります)
- プロジェクト用ディレクトリの作成
-
npm init -y
で npm 環境作成 (package.json
作成) - "types/google-apps-script" npm パッケージの追加
-
clasp login
で使用する Google アカウントを指定 -
clasp create
でプロジェクト作成
以下に実際の手順を説明します。
4.1. プロジェクト用ディレクトリの作成
ローカルにプロジェクト用のディレクトリを作成するだけです。
ここでは my_sample
というディレクトリをプロジェクト用ディレクトリとして作りました。
4.2. npm 環境作成
GAS 書くのに npm が必要なのか?と思ってしまうところですが、GAS の関数/型定義をまとめた npm パッケージがあり、これをエディタに読み込ませることによって、ローカルでコーディングする利便性があがるようになります。
このために package.json
が必要になるので、次のコマンドで作成します。
npm init -y
4.3. "types/google-apps-script" npm パッケージの追加
先に触れた通り、GAS の関数/型定義をまとめた npm パッケージ をプロジェクトに追加します。
VSCode などのエディタであれば、プロジェクト内の GAS スクリプトは、このパッケージに従ってキーワードハイライトしてくれます。
逆にいうと、この npm パッケージを追加しないと、GAS 依存のキーワードはワーニング表示になってしまいます。
npm install @types/google-apps-script
なお、このパッケージは GAS のバージョンアップに従い更新されていくことが期待されるので、このプロジェクト限定のインストール (-g
/ --global
なし) が適切かと思います。
ここまでで作成されるファイル/ディレクトリは次のようになります。(一般的な node 環境そのものです)
4.4. 使用する Google アカウントを指定
これから書こうとする GAS をどの Google アカウントで動かすかを指定します。
Google アカウントが一つしかない場合はこの作業は一度行えばやる必要はありません。
こちら ↓ だと、直前に開いていた Chrome ブラウザのアカウントを使用する前提で処理が行われます。
clasp login
一方、こちら ↓ だと、コマンド実行後に URL が表示され、それを開いた Chrome ブラウザのアカウントを使用する前提で処理が行われます。
clasp login --no-localhost
4.5. プロジェクト作成
プロジェクトの作成は clasp create
で行います。
clasp create
すると、次のように対話形式でどのような GAS を作成するかを問われます。
項目の docs や sheets は、Google Doc に埋め込んだ GAS、Google Spreadsheet に埋め込んだ GAS… といったものを指しています。
(GAS は、当初は、といってもだいぶ昔の話ですが、Google Spreadsheet に埋め込んで利用する方法しかありませんでした)
このように埋め込んだ GAS は、一瞬で終わるタスクを処理するには便利なこともあるのですが、度重なる仕様追加で肥大化し、最終的に Google Spreadsheet を複数扱ったり、Doc や Slide とも連携させたりすることになる傾向が多いので、その状況を見越して、最初から将来のリスクヘッジのために、私は常に standalone
一択です。
clasp create --type standalone
とすることもできますが、ここでは割愛します。
この段階でディレクトリにできるのは次のようなディレクトリ/ファイルになります。
.clasp.json
は clasp の設定ファイルで、中を覗くと scriptId
、rootDir
といったプロパティが見えます。
scriptId
は clasp create
で生成された GAS ファイルの ID、rootDir
はローカル環境でのコードの置き場所となります。
{
"scriptId": "####################################################",
"rootDir": "C:\\Users\\########\\Develop\\my_sample"
}
この設定ファイルには公式の説明にあるように、項目を加えることができます。
次のように項目を編集、追加することにより、カスタマイズすることができます。
{
"scriptId": "####################################################",
"rootDir": "./src",
"fileExtension": "ts"
}
-
rootDir : GAS ファイルを任意のディレクトリで扱う (この例ではプロジェクト用ディレクトリ内の
src
ディレクトリ) -
fileExtension : GAS ファイルの拡張子 ──
ts
を指定することにより TypeScript として扱うことができるようになります
さて、clasp create
で設定ファイルは生成されたものの、GAS ファイルそのものはこのディレクトリには作成されていません。
コードは、clasp login
した Google アカウントの Google ドライブのトップに作成されています。
厳密にはこれは GAS コードそのものではなく、管理するファイルなのですが。
ちなみにこのファイルのロケーションは同一 Google アカウントの Google Drive 上の好きな場所に移動させてもローカルの操作には影響ありません。
すなわち、スクリプトの ID が変わらない限り、Google Drive 上のファイルの場所はどこでも構わない、ということです。
このファイルをローカルに持ってくるために clasp pull
というコマンドがあるのですが、それをしても何も起こりません。
現状の仕様ですと、空のスクリプトに対しては clasp pull
してもローカルに落ちてこないため、一度ブラウザの GAS エディタ上で何らかのコードを書く必要があります。
ですのでさらに次の手順を用います。
4.5.1. clasp open
でブラウザ上で GAS エディタで開く
clasp open
4.5.2. GAS エディタで適当なコードを書いて保存
エディタの左の [Files] で "+" を押し "Script" を選ぶと初期コードが挿入されるので、それを保存します。
function myFunction() {
}
4.5.3. clasp pull
してコードを持ってくる
clasp pull
これで、src ディレクトリの下に GAS のコードが作成され、ローカルで作業できるようになりました。
なお、これは 4.3. の冒頭で書いた、.clasp.json 設定ファイルを改変した場合の結果です。この場合はプロジェクト用ディレクトリのルートにある appscript.json ファイルは不要になります。
.clasp.json を編集せずに、そのまま使った場合には、プロジェクト用ディレクトリのルートに、他のファイルと一緒に .js ファイルが作成されます。
#5. コードの編集
後は、ローカルにある GAS スクリプトを書いていくだけです。
コードを書いたら clasp push
でコードを Google Drive にアップロードします。
clasp push
.clasp.json で fileExtension に "ts" を指定した場合には、ローカルの GAS のコードを TypeScript で書くことができます。
この場合、clasp push
によりコンパイルされ、Google Drive には JavaScript ファイルになってアップロードされます。
#6. デバッグ上の注意点
実際の開発作業では、次のようなフローで回していくことになると思います。
(1) ローカルの GAS ファイルを編集
(2) clasp push
でコードを Google Drive にアップロード
(3) ブラウザの GAS エディタ上でデバッグし、挙動を確認
(4) (1) に戻る
この状況だと、ブラウザの GAS エディタは開きっぱなしになりますが、clasp push
で最新のスクリプトをアップロードしても GAS エディタには自動的に反映されないので、clasp push
した後はブラウザをリロードする必要があります。
#7. GAS で扱うライブラリの管理
GAS で OAuth1 などのライブラリや、YouTube Data API サービスを扱うときは、appsscript.json を編集します。
appsscript.json にライブラリの追記をしないと、clasp push
をした後、ブラウザ上の GAS エディタにマニュアルで設定したライブラリやサービスが除去されてしまいます。
{
"timeZone": "America/New_York",
"dependencies": {
"libraries": [
{
"userSymbol": "OAuth1",
"libraryId": "1CXDCY5sqT9ph64fFwSzVtXnbjpSfWdRymafDrtIZ7Z_hwysTY7IIhi7s",
"version": "18"
}
],
"enabledAdvancedServices": [
{
"userSymbol": "YouTube",
"version": "v3",
"serviceId": "youtube"
}
]
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8"
}
8. まとめ (新規プロジェクト作成手順チートシート)
以上を改めてまとめると、既に clasp がグローバルにインストールされた環境での新規プロジェクトの作成手順は下記のようになります。
(1) ローカルにてプロジェクト用ディレクトリの作成
(2) npm init -y
(3) npm install @types/google-apps-script
(4) clasp login
(5) clasp create
(6) [任意] .clasp.json の編集 (rootDir と、TypeScript を使う場合は "fileExtension":"ts")
(7) clasp open
の後、ブラウザ上の GAS エディタでスクリプトの追加 (ライブラリ類の追加もここでやるとラク)
(8) clasp pull
してローカルに持ってくる
(9) コーディング
(10) clasp push
(注意 1) (6) で rootDir を変更した場合は、元々あったトップの appsscript.json は使われないので消して良い (変更した rootDir の appsscript.json が使用されるので)
(注意 2) ライブラリの追加 / 変更は appsscript.json にて行う
(注意 3) Google Drive 上のスクリプトは管理しやすい場所へ
この手順はあくまで私がいつもやっている手順なので、もっとスマートなやり方があると思います。
9. FAQ
Q1. コードのファイルを src ディレクトリに置くなら、clasp create
する時に --type
に加えて --rootDir
も指定してやればいいのでは?
A. 期待するファイルが、期待するディレクトリに作られればそれが理想なのですが、--rootDir
をした場合、--rootDir
で指定したディレクトリに .clasp.json が作成されてしまいます。
{
"scriptId": "####################################################",
"rootDir": "./src"
}
これだと clasp push
が、プロジェクトのルート (package.json があるところ) いても、--rootDir
で指定したディレクトリにいても、失敗します。
(clasp が想定する --rootDir
を指定するシナリオが不明です。ちなみに --rootDir
に指定するディレクトリを作事前に作っておく必要があるのは変わりません)
加えて、現状だと、どのようなオプションで clasp create
しようが、fileExtension 指定はできない (unknown option エラーになります) ので、.clasp.json の編集は必須で、だったらそこで rootDir を編集しちゃえば良い、という結論に至っています。
Q2. clasp open
してブラウザの GAS でファイルを作ってから clasp pull
してローカルに持ってくるのってダサくない?いきなりローカルにファイルを書いて clasp push
すれば効率が良いのでは?
「ダサい」については 100% agree です。しかし理由があります。
-
clasp push
のためには appsscript.json が必要になる - 私は複数の Google アカウントを使っているので、
clasp open
で適切なアカウントに紐付いているか確認できる - ライブラリやサービスの設定は、ブラウザの GAS エディタ上で行った後、
clasp pull
でローカルに持ってくるのが安全で確実