Retty Tech Blog

実名口コミグルメサービスRettyのエンジニアによるTech Blogです。プロダクト開発にまつわるナレッジをアウトプットして、世の中がHappyになっていくようなコンテンツを発信します。

GAS + React + Vite + Claspで作るお手軽フロントエンド

この記事はRetty Advent Calendar Part2の22日目の記事です。 Part1はこちらです。

はじめに

23卒の内定インターンをしている真下(@mashita1023)です。 内定インターンの中で単純な要件の社内ツール作成を作成したのですが、技術選定から実装まで結構な範囲を開発させてもらましえた。 その中でフロントエンドのデプロイ先にGoogle Apps Script(GAS)を使うことで、社内の人間のみが扱えるという要件を達成できた話をします。

社内ツールの要件

キャッシュを消すためのツールは以前にも社内ツールとして存在していたのですが、 コード自体がGitHubで管理されておらずどこにあるのかわからない状態でした。 そこで、キャッシュを消すためのツールを新たに作る必要がありました。

作成しなければいけないものを要件として簡潔にまとめ直すと以下のようになりました。

  1. 使用するのは非エンジニア
  2. 社外の人間がアクセスできないようにすること
  3. APIへのHTTPリクエストを行う

GASを使った背景

以上の要件を踏まえた上で以下の理由からGASをウェブアプリとしてデプロイして実現することにしました。

  • 非エンジニアの方が使うのでSlackなどでコマンド入力するよりもGUIで実行できた方が簡単に扱える
  • GASでは同じドメインのアカウントのみアクセスできるようにできる
  • GASにデプロイするのでインフラの管理をする必要がなくなる

また、GASにデプロイすることでvanillaで, CSS, JavaScriptを書かなければいけない制約がありますが、インライン記述したHTMLをビルドできるようにすることで、Reactなどで.tsxなどの拡張子で開発することができるようになります。 選定技術とその理由は以下のようにしました。

Vite

  • esbuildを使っているため超高速

React

  • 簡潔にコードを書くことができ、VanillaJSと比べ保守がしやすい
  • react hook formを用いてstateやバリデーションの管理が楽になる

clasp

  • GASのコードをJavaScriptやTypeScriptで書くことができる
  • コードをGitHubで管理できるようになる
  • GASにデプロイするところまでCLIで完結できる

次にGASとUIライブラリ・フレームワークを共存するための手順を説明します。

GASにデプロイするまでの手順

まずボイラープレートとして用意したのでこちらを参考にしてください。 ReactとVueでなら問題なく以下の手順でできることを確認しています。 今回はReactで作成していきます。

インライン記述されたHTMLの生成

まずViteでプロジェクトを以下のコマンドで作成します。 その際プロジェクト名は今回はreact-gasとし、その後React,TypeScriptを選択します。。

$ npm create vite@latest
$ cd react-gas

次に今回の肝となるライブラリ、vite-plugin-singlefileを導入します。 Viteを使っているのでRollupでインライン記述されたHTMLを生成してくれるライブラリです。

$ npm i vite-plugin-singlefile

これをwebpackでやろうとするとライブラリは古く、結構苦労しましたがViteを使ってしまえば本当に苦労するところは全然ないです。 そしてvite.config.tsを以下のように編集します。

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { viteSingleFile } from 'vite-plugin-singlefile'

export default defineConfig({
  plugins: [react(), viteSingleFile()],
})

$ npm run buildをするとdist配下にファイルが生成されたはずです。これでインライン記述したHTMLが生成できました。

claspの準備

まずGoogleDriveを開いて右クリック、その他、Google Apps Scriptの順にクリックしてください。 すると次のような画面になるはずです。

GASでプロジェクトを作ったときの画面

URLがscript.google.com/home/projects/XXXXXXX/editのようになっているはずなのでXXXXXXXの部分をコピーしておきます。

そうしたらCLIを開いて次のコマンドでclaspをインストールしてからアカウントの認証をし、必要なファイルを生成します。 また、一緒にデプロイするために必要なファイルも作成します。

$ npm i -g @google/clasp
$ clasp login
$ clasp create --type webapp
$ mkdir server
$ mv appsscript.json server/
$ touch server/code.ts

次に生成された.clasp.jsonを以下のように編集してください。 scriptIdには先ほどURLからコピーした部分を貼り付けましょう

{
    "scriptId":"XXXXXXX",
    "rootDir":"./server"
}

現在のままではdistに生成結果が出力されるのでvite.config.tsを再度編集してserver配下に出力されるようにしてください。

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { viteSingleFile } from 'vite-plugin-singlefile'

export default defineConfig({
  plugins: [react(), viteSingleFile()],
  build: {
    outDir: "server/hosting",
  },
});

server/appsscript.jsonを編集してアクセスできるユーザーを指定しましょう。 accessMYSELFにすることで自分だけが使えるようになります。 リファレンスも公式にあるので追加でやりたいことがあれば見てみてください。

{
  "timeZone": "Asia/Tokyo",
  "dependencies": {},
  "webapp":  {
    "access": "DOMAIN",
    "executeAs": "USER_DEPLOYING"
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}

最後にserver/code.tsを編集してHTMLが正しく読み込まれるようにします。 setTitleでタイトルタグを設定できます。 また、setFaviconUrlでファビコンも設定できます。

export function doGet() {
  return HtmlService.createHtmlOutputFromFile("hosting/index.html")
    .addMetaTag("viewport", "width=device-width, initial-scale=1")
    .setTitle("React + GAS");
}
}

ここまでできたらあと少しです。 npm run buildでビルドをしてみましょう。

成功したら次の手順でGASにデプロイしていきます。

$ clasp push
$ clasp deploy

きちんとデプロイされたかを確認するために$ clasp openをして右上のデプロイ、デプロイの管理の順にクリックします。

デプロイの管理

表示された画面の中央下部にURLの文字とハイパーリンクがあるのでクリックして遷移すると次のようなVite+Reactの初期画面になっているはずです。(画像が表示されないのはGAS上にアップロードできないため正常です。)

デプロイ先のリンクに飛んだ時の画面

また、デプロイしたURLを変更したくない時はclasp deployの際に--deploymentIdを指定することでURLが変わることなくデプロイすることができます。

結び

GASでウェブアプリをインライン記述してデプロイするところまでを説明しました。 また、claspを使うことでCLIで開発からデプロイまでが完結し、GitHubでコード管理をすることができます。 今回はCSSフレームワークの導入についての説明は書いておりませんが、特別変わったことはせずnpm installすれば問題なく扱えます。 あまり大きくない個人開発や社内ツール程度ならデプロイ先にGASも選択肢として出るんじゃないかなと思います。 SSRをここにデプロイするのは微妙ですがNuxtなどのSPAもできるようにしてみたいです。 読んでくださったみなさんも是非デプロイ先としてGASを考えてみてください!