🍭

TypeScript+clasp+esbuildでGASのローカル開発をもっと便利に

2024/03/04に公開

はじめに

本記事では、TypeScript+clasp+esbuildを用いたより便利なGoogleAppScriptのローカル開発環境の構築方法を紹介しています。

claspについて

GoogleAppScriptで開発しようとすると、規模によってはgitを使って複数人でのバージョン管理やTypeScriptを利用した開発環境を準備したくなります。

そこで、@google/claspという開発ツールを用いることで、TypeScriptの利用やCLIでGoogleAppScript上にdeployが可能になりローカルでのコード管理が容易になります。また、必要に応じてprettierやeslintなど開発を便利にしてくれる機能なども導入可能になります。
しかし、clasp単体を利用したやり方ではTypeScriptのコンパイルはよしなにやってもらえるものの、ESmoduleの機能が使えずファイルをまたいでも全ての変数がグローバルになりimportやexportが使えず普段のような開発体験を得ることができません。

esbuildの利用について

上記の通り、このままではimportやexportの機能が使えないので利用したければ、claspのtsのコンパイル機能を使うのではなく、自前でtsのimportを解決してバンドル・コンパイルの必要があります。
そこで、esbuildとesbuildのGAS用のプラグインを使ってGAS用のjsへのバンドル・コンパイルを行うことでimportやexportの機能を使いつつGAS用のスクリプトを書けるようになります。

プロジェクト構成

最終的なスクリプトや設定ファイルの構成は以下のようになっています。
src配下にTypeScriptのコードを書き、GASにはdist配下のファイルをデプロイします。

.
├── dist/
│    ├── appsscript.json
│    └── main.js
├── src/
│    ├── main.ts
│    └── sample.ts
├── .clasp.json
├── esbuild.js
├── package.json
└── tsconfig.json

また、今回試したソースコードもこちらに置いているため必要があればご確認ください。
https://github.com/rye-shiro5778/gas-ts-clasp-esbuild-template

プロジェクトのセットアップ

以下では、実際にこの環境を再現する手順について記述していきます。

  • package.jsonファイルの作成
npm init -y
  • TypeScriptやclaspなどの必要なパッケージのインストール
npm install -D clasp typescript @google/clasp @types/google-apps-script
  • tsconfigの作成
npx tsc --init

基本的に好みの設定で良いとは思いますが、今回はclaspのドキュメントにもある通り、以下の設定は追加しておきました。

tscofig.json
{
  "compilerOptions": {
    "lib": ["esnext"],
    "experimentalDecorators": true
  }
}
  • esbuildのインストールとbuildスクリプトの作成
npm install -D esbuild esbuild-gas-plugin
esbuild.js
import esbuild from "esbuild";
import { GasPlugin } from "esbuild-gas-plugin";

esbuild
  .build({
    entryPoints: ["./src/main.ts"],
    bundle: true,
    minify: true,
    outfile: "./dist/main.js",
    plugins: [GasPlugin],
  })
  .catch((e) => {
    console.error(e);
    process.exit(1);
  });

  • claspでのプロジェクトのセットアップ
npx clasp create --type standalone
.clasp.json
{
  "scriptId": "--自動生成されたスクリプトID--",
  "rootDir": "./dist"
}

ここでappsscript.jsondist/appsscript.jsonに移行しておきます

  • 検証用のTypeScriptコードを作成
main.ts
import { sample } from "./sample";

// GASから参照したい変数はglobalオブジェクトに渡してあげる必要がある
(global as any).sample = sample;
sample.ts
export function sample() {
  console.log("---sample---");
}
  • buildやdeploy用のコマンドの追加
package.json
  "scripts": {
    "build": "node esbuild.js",
    "push": "clasp push",
    "open": "clasp open", # GAS側のスクリプト画面をブラウザで開く
    "deploy": "npm run build && npm run push"
  },
  • 最後に実行確認
npm run deploy
npm run open

実行確認

実際にimportしたsampleという関数を動かせていることを確認できました!

おわりに

ちょっとした社内ツールを開発したりする際などに私自身よくこのやり方をしています。
この記事がローカルでのGAS開発を検討している方のお役に立てると幸いです。

ファンタラクティブテックブログ

Discussion