LoginSignup
5
1

Google App Scriptを自分のマシンで開発できる google clasp を使ってみる・前編

Last updated at Posted at 2024-07-09

社内向け発表資料をQiitaに投稿。

GAS (Google App Script) とは

GASの特徴

ChatGPTさんに尋ねてみるとこんな事いってきます。

Google App Script(グーグルアプスクリプト)とは、Googleが提供しているプログラミングツールです。
これを使うと、Googleのさまざまなアプリ(たとえば、Gmail、Googleドライブ、Googleスプレッドシートなど)をもっと便利にするためのプログラムを書けるようになります。
  • 定期的にスクリプトを実行でき、決まった処理を自動化することができる
  • スプレッドシートに格納されたデータを処理することができる
  • ウェブブラウザとGoogleのアカウントがあれば簡単に始められる
  • 利用は基本的に無料
  • Googleのサービスと簡単に連携することができる

GASのデメリット

  • 実行時間に制限がある
    • スクリプトの実行時間は1回の処理につき最大6分
      • 6分を超えたらスクリプトが強制終了される
  • JavaScriptベースのプログラミング言語である
    • Python等に比べると配列の処理に不便
    • デバッグが難しい
    • TypeScriptに慣れてると型チェックがない言語で使いづらい
  • テストが書けない・書きづらい
  • Googleのサービスに依存している
    • たまに起こるGoogleサービス停止が発生すると、なんにもできん
  • 開発・実行するにはインターネット接続が不可欠
  • Git等でコードをバージョン管理できない

google clasp

これらGASのデメリットをちょびっとだけ改善できる Google 謹製のプロジェクト・google clasp(Command Line Apps Script Projects)を使ってみる。

特徴: ローカルの環境で好きなエディタを使ってGASを開発

claspを使うと、Google Apps ScriptのコードをローカルマシンのテキストエディタやIDE(統合開発環境)で編集できるようになる。

これによりVS Codeなどの高度なエディタの機能を活用して、効率的に開発が可能になる。

ローカルの環境でコードは書けるけど、実行環境はあくまでクラウドのGAS側。GASにコードをpushしないと動作の確認ができないので注意。

特徴: 書いたコードをバージョン管理できる

ローカルの環境でコードを保存できるため、Gitなどのバージョン管理システムでコードを管理することもできる。これにより、コードに対して行った変更履歴を追跡可能となる。また、複数人での共同開発や過去の変更の管理も容易になる。

特徴: 既存のGASもローカル環境にインポートできる

既に開発済みのGASもローカルの環境に保存することができる。

特徴: ローカルの環境からデプロイできる

GASの実行環境に対し、pushやデプロイは以下のコマンドを入力するだけ。

$ clasp push
$ clasp deploy -i AKfyAAAvqg

特徴: コード整形、Lint、ユニットテストを外部ツールを使って行うことができる

ESLintなどのコード解析ツールや、Jestなどのテストフレームワークと組み合わせて使用することが可能。

特徴: TypeScriptが使える

claspではTypeScriptで開発ができる。TypeScriptの静的型付けにより、コードの安全性や可読性の向上が期待できる。

ただ、GASの実行環境はTypeScriptがそのまま動かせない。GASのpush・デプロイ時、JavaScriptにトランスエンコードしたものをデプロイすることができる。

claspの開発手順

プロジェクトの初期化

以下のコマンドで初期化。よろずバージョン管理ツール・asdfを利用して nodejs の環境を構築。

$ asdf local nodejs 22.2.0
$ npm i @google/clasp
$ clasp login

https://accounts.google.com/o/oauth2/v2/auth/oauthchooseaccount?access_type=offline&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fscript.deployments%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fscript.projects%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fscript.webapp.deploy%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.metadata.readonly%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.file%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fservice.management%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Flogging.read%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform&response_type=code&client_id=xxxxxxxxxxxxx-vm2v2i5dvn0a0d2o4ca36i1vge8cvbn0.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A61078&service=lso&o2v=2&ddm=0&flowName=GeneralOAuthFlow

プロジェクト作成

clasp create でプロジェクトの作成。ここでは standalone を選択してGASを構築。

$ clasp create calc_sample --rootDir ./src
(node:27646) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
? Create which script? (Use arrow keys)
❯ standalone 
  docs 
  sheets 
  slides 
  forms 
  webapp 
  api 

? Create which script? standalone
Created new standalone script: https://script.google.com/d/1bNq6bqZpsYxHaT0_FvADKz0I4iyh5_GLaS9Gt9iu3UFL7bvD76q8ivlW/edit
Warning: files in subfolder are not accounted for unless you set a 'src/.claspignore' file.
Cloned 1 file.
└─ ./src/appsscript.json

このあとできるファイル類。

drwxr-xr-x   10 yusuke  staff     320  7  1 20:49 .
drwxr-xr-x   11 yusuke  staff     352  7  1 20:36 ..
-rw-------    1 yusuke  staff      91  7  1 20:35 .clasp.json
-rw-r--r--    1 yusuke  staff      14  6 30 18:42 .tool-versions
drwxr-xr-x  221 yusuke  staff    7072  7  1 20:09 node_modules
-rw-r--r--    1 yusuke  staff  113315  7  1 20:09 package-lock.json
-rw-r--r--    1 yusuke  staff     282  7  1 20:20 package.json
drwxr-xr-x    6 yusuke  staff     192  7  1 20:49 src

## src 以下
yusuke@suzuki-m2-Mac-mini calculate_sample % ls -al src
total 32
drwxr-xr-x  6 yusuke  staff  192  7  1 20:49 .
drwxr-xr-x  9 yusuke  staff  288  7  1 20:57 ..
-rw-r--r--  1 yusuke  staff  119  7  1 20:38 appsscript.json

src/appsscript.json の中身

{
  "timeZone": "America/New_York", # > "Asia/Tokyo" に変更
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}

.clasp.json の中身

{"scriptId":"1bNq6bqZpsYxHaT0_FvADKz0I4iyh5_GLaS9Gt9iu3UFL7bvD76q8ivlW","rootDir":"./src"}

GAS 側を開いてみる

このスクリプトが関連しているGASを以下のコマンドで開く。

$ clasp open

まだ何も push してないので、中身は空。

また作成時に指定したのがスタンドアローンスクリプトなので、関連する SpreadSheet も存在してない。

%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88_2024-07-01_20.06.27.png

TypeScriptを書いてみる

claspでTypeScriptで開発するには、下準備が必要。

$ npm install --save-dev typescript @types/google-apps-script

added 4 packages, changed 1 package, and audited 279 packages in 2s

86 packages are looking for funding
  run `npm fund` for details

tsconfig.jsonは特に要らない。

TypeScriptのコードを書いてみる。srcディレクトリに Main.tsを作る。

src/Main.ts

// Main.ts

function add(a: number, b: number): number {
  return a + b;
}

function subtract(a: number, b: number): number {
  return a - b;
}

function logMessage(message: string): void {
  Logger.log(message);
}

function main() {
  const resultAdd = add(5, 3);
  const resultSubtract = subtract(5, 3);

  logMessage(`Addition Result: ${resultAdd}`);
  logMessage(`Subtraction Result: ${resultSubtract}`);
}

TypeScriptをGASにpushしてみる

package.jsonをこんな感じに変更する。

package.json

{
  "name": "clasp-calculate-sample",
  "version": "1.0.0",
  "dependencies": {
    "@google/clasp": "^2.4.2"
  },
  "devDependencies": {
    "@types/google-apps-script": "^1.0.83",
    "typescript": "^5.5.2"
  }
}

clasp をpushすることで、claspが自動的にTypeScriptをGASにトランスコンパイルしてから、GASの実行環境に転送してくれる。

$ clasp push      

(Use `node --trace-deprecation ...` to show where the warning was created)
└─ src/appsscript.json
└─ src/Main.ts
Pushed 2 files.

TypeScriptがトランスコンパイルされ、変換されたGASのコードはこんな感じ。

// Compiled using clasp-calculate-sample 1.0.0 (TypeScript 4.9.5)
// Main.ts
function add(a, b) {
    return a + b;
}
function subtract(a, b) {
    return a - b;
}
function logMessage(message) {
    Logger.log(message);
}
function main() {
    var resultAdd = add(5, 3);
    var resultSubtract = subtract(5, 3);
    logMessage("Addition Result: ".concat(resultAdd));
    logMessage("Subtraction Result: ".concat(resultSubtract));
}

main関数を実行してみる。

%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88_2024-07-01_21.09.18.png

claspの欠点

ここまでの説明にて、一見便利に見える clasp だけども、いくつかの欠点も存在する。

TypeScriptのコード分割記法 import 構文が機能しない

  • 機能するようにするには webpack を使うなど、いくつか方法がある
  • が、package.json を変更・定義するのがめんどくさい

TypeScriptの型チェックがデプロイ時に機能するわけではない。

例えば add 関数の引数に文字列を設定した場合、TypeScriptのチェックが入るテキストエディタでは型チェックが入り、引数の型が間違ってるよーと怒られる。

%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88_2024-07-01_21.17.58.png

が、エディタで警告されたからといって、clasp push によるデプロイが失敗するわけではない。なので、push後、に反映されたGASを実行すると、普通に文字列の足し算が実行されちゃうという悲しみ。

%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88_2024-07-01_21.21.16.png

コード整形、lint、ユニットテスト等の環境を自分で用意する必要がある

ファイル構成が自由であるが故、開発者それぞれで設定のやり方が異なり、こうすべきであるといった決まったやり方が定まっていない。

これらのデメリットを改善する方法は一応用意されてるが、後編にて。

まとめ

  • 素のGASを書くのは色々とツライ。が、claspを使うとメリットが色々享受できる
  • claspは便利。だが自由度が高すぎて環境整えるのが大変

以上

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1