OUCC

BLOG

記事一覧 タグ一覧

最強のGAS開発環境を構築する

投稿日:

はじめに

GASは標準ではウェブエディタを使用して開発することができますが、開発環境が貧弱であるため、開発効率が悪いです。そこで、以下の要件を満たすGAS開発環境を構築します。

  • ローカルで開発する
  • TypeScriptで型検査する
  • npmパッケージを使用できる
  • ファイルを変更すると自動的にウェブに反映される

TL;DR

以降の設定を全てまとめたテンプレートを作成しました。以下のリポジトリからダウンロードして使用してください。

GitHub - miyaji255/gas-app-template: Google Apps Script(GAS)のプロジェクトを作成するためのテンプレート
Google Apps Script(GAS)のプロジェクトを作成するためのテンプレート. Contribute to miyaji255/gas-app-template development by creating an account on GitHub.
GitHub - miyaji255/gas-app-template: Google Apps Script(GAS)のプロジェクトを作成するためのテンプレート favicon https://github.com/miyaji255/gas-app-template
GitHub - miyaji255/gas-app-template: Google Apps Script(GAS)のプロジェクトを作成するためのテンプレート

claspだけではだめなのか

GASの開発環境をローカルで構築するためには、一般的にclaspを使用します。claspはGASの開発をローカルで行うためのツールです。.clasp.jsonを設定したディレクトリでclasp pushを実行することで、GASのスクリプトをウェブに反映することができます。

claspはTypeScriptもサポートしていますが、import/export構文を使用することができません。つまり、npmパッケージも使用できません。

そのため、claspでpushする前に、TypeScriptをJavaScriptにコンパイルしてバンドルする必要があります。

esbuildを使用する

esbuildは高速なJavaScriptバンドラーです。ただし、esbuildでバンドルしただけではGASにエントリーポイントが認識されません。これを解消するためにesbuild-plugin-gas-generatorを作成しました。

ESModuleをGASで実行できるようにする | OUCC - 大阪大学コンピュータクラブ
esbuildを用いてESModuleをGAS環境で実行できるようにするプラグインを作成しました。
ESModuleをGASで実行できるようにする | OUCC - 大阪大学コンピュータクラブ favicon https://oucc.org/blog/articles/2024-06-30-esbuild-plugin-gas-generator/
ESModuleをGASで実行できるようにする | OUCC - 大阪大学コンピュータクラブ

これを使ってビルドスクリプトを作成すると次のようになります。

import { build } from 'esbuild'
import GasGeneratorPlugin from 'esbuild-plugin-gas-generator'

build({
  entryPoints: ['src/index.ts'],
  bundle: true,
  format: "esm",
  outfile: 'dist/index.js',
  plugins: [GasGeneratorPlugin()],
}).catch((e) => {
    console.error(e)
    process.exit(1)
})

さらに、appsscript.jsonを自動でコピーするように次のようなプラグインを足します。

const copyAppsScriptPlugin = {
  name: "copy-appsscript",
  setup(build) {
    build.onEnd(async () => {
      await copyFile('appsscript.json', 'dist/appsscript.json')
    })
  }
}

esbuildには標準でwatchモードがあります。これを使うとファイルを変更すると自動的にビルドされます。引数で分岐してbuildとwatchを切り替えることができるようにした、最終的なビルドスクリプトは次のようになります。

import GasGeneratorPlugin from "esbuild-plugin-gas-generator"
import { build, context, type BuildOptions } from "esbuild"
import { copyFile } from "fs/promises"

async function main() {
  const options = {
    entryPoints: ["src/index.ts"],
    bundle: true,
    outfile: "dist/index.js",
    format: "esm",
    plugins: [
      GasGeneratorPlugin(),
      {
        name: "copy-appsscript",
        setup(build) {
          build.onEnd(async () => {
            await copyFile("appsscript.json", "dist/appsscript.json")
          })
        }
      }
    ],
  } as const satisfies BuildOptions

  switch (process.argv[2]) {
    case "watch": {
      const ctx = await context({ ...options, logLevel: "info" })
      await ctx.watch();
      break;
    }
    case "build": {
      await build(options);
      break;
    }
    default: {
      console.error(`Unknown command: ${process.argv[2]}`);
      process.exit(1);
    }
  }
}

main().catch((e) => {
  console.error(e)
  process.exit(1)
});

tsx を使用すると次のようなコマンドでビルドできます。

# ビルド
npx tsx esbuild.ts build
# ファイルを変更すると自動的にビルドされる
npx tsx esbuild.ts watch

claspと組み合わせる

claspの設定は.clasp.jsonに記述します。distディレクトリにビルドされたファイルがあることを認識させるために、rootDirを設定します。

{
  "scriptId": "YOUR_SCRIPT_ID",
  "rootDir": "dist"
}

claspにもwatchモードがあります。これを使うとファイルを変更すると自動的にウェブに反映されます。

npx tsx esbuild.ts watch
npx clasp push -f -w

ただし、どちらもwatchモードでは制御が戻ってこないので、別々のターミナルで実行する必要があります。

おわりに

以上で最強のGAS開発環境を構築することができました。最終的な結果は以下のテンプレートにまとめてありますので、ぜひご利用ください。

GitHub - miyaji255/gas-app-template: Google Apps Script(GAS)のプロジェクトを作成するためのテンプレート
Google Apps Script(GAS)のプロジェクトを作成するためのテンプレート. Contribute to miyaji255/gas-app-template development by creating an account on GitHub.
GitHub - miyaji255/gas-app-template: Google Apps Script(GAS)のプロジェクトを作成するためのテンプレート favicon https://github.com/miyaji255/gas-app-template
GitHub - miyaji255/gas-app-template: Google Apps Script(GAS)のプロジェクトを作成するためのテンプレート