Google Apps Script(GASと呼ばることが多いですが、公式にはApps Scriptと略されます)は、Googleが提供するJavaScriptベースのスクリプティング言語です。このクラウド上で動作する環境を利用することで、GoogleスプレッドシートなどのGoogleアプリと連携したウェブアプリを誰でも無料で開発できます。
この記事では、Apps Scriptの開発ツールであるclaspを用いて、ReactとViteを組み合わせることにより、より洗練されたSingle Page Application(SPA)の開発プロセスを解説します。
- clasp: Apps Scriptプロジェクトを効率的に管理するためのコマンドラインツール。ローカルでの開発を可能にし、変更を簡単にGoogle Cloudにプッシュできます。
- React: 再利用可能なUIコンポーネントを作成することで、開発プロセスを加速し、保守が容易なアプリケーションを構築できます。
- Vite: 開発中の高速なホットリローディングを提供し、最終的なビルドの効率を大幅に向上させるモダンなビルドツールです。
この記事では、clasp + React + Vite + Google Apps Scriptで無料のSPAを公開するまでの手順を具体的に紹介していきます。核となるのは、Reactで作ったフロントエンドをViteのプラグインで一つのindex.htmlにまとめてから、Google Apps Scriptのプロジェクトにpushするプロセスです。Apps Scriptのウェブアプリはページ間のリンク(<a>
タグによるハイパーリンク)の扱いが得意ではありません。そこでページ間の遷移はReactで実現し、ファイル自体は一つにまとめてしまいます。
開発者はReactの豊富なコンポーネントを再利用しながら、より優れたUIを構築できます。またViteの効率的なビルドシステムのおかげでストレスなく開発できます。ローカル開発環境を準備するのは少々手間がかかりますがデバッグは容易になるので、結果的により高速な開発サイクルを実現できます。
この記事では、npm create
でViteとReactのボイラープレートを作り、Apps Scriptのウェブアプリとして公開するところまでを紹介します。取り上げる題材は簡単なものですが、これを土台にすることで、より複雑なReactアプリをApp Scriptの環境で開発し公開することも可能になります。ぜひ手を動かしながらお楽しみください。
0. 事前準備
PCにNode.jsとclaspをインストールします。
Node.jsのインストール
WindowsやWSL2にNode.jsをインストールするには、マイクロソフトの記事が参考になります。
Macはいろいろな流派がありますが、私はHomebrew + nvmでNode.jsをインストールしています。
この記事では、次のバージョンを使います。
node -v
v20.9.0
claspのインストール
Node.jsのインストールが完了したら、claspをインストールします。
まず、Google Apps Script APIをOn
にしておきます。
次に、claspをグローバルにインストールし、Googleアカウントでログインしておきます。
npm install -g @google/clasp
clasp login
この記事では、次のバージョンを使います。
clasp -v
2.4.2
1. Reactアプリを作成
Reactアプリを作成します。今回はJavaScriptで作ります1。アプリ名はhello-apps-script
にします。プロジェクト名(hello-apps-script
)の後に--
を記載し忘れないよう注意してください。
npm create vite@latest hello-apps-script -- --template react
hello-apps-script
ディレクトリーができるので、開発用サーバーを動かしてReactアプリが動作することを確認します。なお、IDE、例えばVisual Studio Codeを使っている方は、IDEのターミナルから作業すると便利です。
cd hello-world
npm install
npm run dev
ターミナルにURLが表示されるので、ウェブブラウザーでアクセスして表示を確認します。
VITE v5.2.7 ready in 1410 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help
count is 0
ボタンをクリックすると、カウントアップしていきます。
2. ビルド環境構築
ViteでApps Scriptにアップロードするファイルをbuildします。
まず必要なパッケージをインストールします。
npm install --save-dev vite-plugin-singlefile vite-plugin-static-copy
vite-plugin-singlefileはJavaScriptやCSSをdist/index.html
にまとめてくれます。
vite-plugin-static-copyは特定のフォルダーにあるファイルをdist
以下にコピーしてくれます。
次にvite.config.js
ファイルを編集します。
import { defineConfig } from "vite"
import react from "@vitejs/plugin-react"
import { viteSingleFile } from "vite-plugin-singlefile"
import { viteStaticCopy } from "vite-plugin-static-copy"
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
react(),
viteSingleFile(),
viteStaticCopy({ targets: [{ src: "apps-script/*", dest: "./" }] }),
],
})
フロントエンドのコードはsrc
ディレクトリーに、バックエンドの(Apps Scriptの)コードはこれから作るapps-script
ディレクトリーに配置する前提です。
ここまで作業したら、正しくbuildできるか試してみます。
npm run build
> hello-apps-script@0.0.0 build
> vite build
vite v5.2.7 building for production...
✓ 34 modules transformed.
rendering chunks (1)...
Inlining: index-BXGOX9Nt.js
Inlining: style-DiwrgTda.css
computing gzip size (0)...[vite-plugin-static-copy] No items to copy.
dist/index.html 150.09 kB │ gzip: 49.62 kB
✓ built in 395ms
dist
ディレクトリーの下にindex.html
ファイルが出力されました。
3. Apps Scriptのウェブアプリを作成
claspでApps Scriptのウェブアプリを作成します。スプレッドシートをデータベース代わりに使う事が多いので、--type sheets
を指定して、スプレッドシートのスクリプトとして作成します。新しいスプレッドシートはGoogleドライブのマイドライブに作成されます。
clasp create --type sheets --title "HelloAppsScript"
Could not read API credentials. Are you logged in globally?
というエラーが出た場合、clasp login
でログインを済ませてから実行してください。
User has not enabled the Apps Script API. Enable it by visiting https://script.google.com/home/usersettings then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
というエラーが出た場合、指示に従って Google Apps Script APIをONにしてから実行してください。
Project file (.clasp.json) already exists.
というエラーが出た場合、すでにclasp createでプロジェクトを作成済です。もし、再作成する場合は、ローカルにある.clasp.jsonと、Googleドライブに作った関連ファイルを手動で削除してから再実行してください。
この操作が成功すると、次の2つのファイルが作成されます。
- .clasp.json
- Apps Scriptのリソースを定義(後ほど修正します)
- appsscript.json
- Apps Scriptの設定を定義(後ほど移動、修正します)
.clasp.jsonを修正
.clasp.json
のrootDir
は、どのソースコードをGoogle側にpushするかを定義しています。buildした結果をpushしたいので、dist
ディレクトリーを指定しておきます(scriptId
とparentId
はそのままで大丈夫です)。
"rootDir": "dist"
apps-scriptディレクトリーを作成
バックエンドのソースコードを置くために、apps-script
ディレクトリーを作成します。
mkdir apps-script
appsscript.jsonを移動、修正
appsscript.json
はマニフェストファイルと呼ばる、プロジェクトの設定ファイルです。バックエンドのソースコードなので、apps-script
ディレクトリーを作り、そこに移動します(buildするタイミングでdist
ディレクトリーにコピーされます)。
mv appsscript.json apps-script
また、このApps Scriptはウェブアプリとして公開するため、appsscript.json
を次のように編集しておきます。timeZone
をAsia/Tokyo
に変更し、webapp
を追加しています。
{
"timeZone": "Asia/Tokyo",
"dependencies": {},
"webapp": {
"access": "MYSELF",
"executeAs": "USER_DEPLOYING"
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8"
}
apps-script/Code.jsを追加
バックエンドのコードとして、apps-script
ディレクトリーの下にCode.js
を追加します。ウェブアプリにアクセスがあると、index.htmlを返却するために、doGet()を実装します。
function doGet() {
return HtmlService.createHtmlOutputFromFile("index.html")
.addMetaTag("viewport", "width=device-width, initial-scale=1")
.setTitle("React Router Tutorial");
}
buildしてGoogle側へpush
ここまでに、次のような作業を実施してきました。
.
├── .clasp.json (rootDirをdistに修正)
└── apps-script
├── Code.js (doGetを実装)
└── appsscript.json (webappを追加)
buildして、distディレクトリー以下にGoogleへpushするファイル群を作り、pushします。マニフェストファイルを修正しているため、更新してもよいか聞かれるので、y
と入力します。
npm run build && clasp push
? Manifest file has been updated. Do you want to push and overwrite? Yes
└─ dist/appsscript.json
└─ dist/Code.js
└─ dist/index.html
Pushed 3 files.
Google側に正しくpushできたかどうかは、スクリプトエディターで確認できます。なお、スクリプトエディター側でソースコードを修正しないようご注意ください(ローカルには反映されません。clasp pullをする必要があります)。
clasp open
4. ウェブアプリの確認と修正
Google側にpushしたウェブアプリが正しく動作するか、ウェブブラウザーで確認します。--webapp
オプションをつけてclasp open
を実行します。どのデプロイメントを確認するか聞かれますが@HEAD
を選択してください。
clasp open --webapp
? Open which deployment? @HEAD -
AKfycbzLwLPOUK5pChztlBpdGeQDpoSDcAlP-WsJm1els15I
Opening web application: AKfycbzLwLPOUK5pChztlBpdGeQDpoSDcAlP-WsJm1els15I
@HEAD
デプロイメントは、Google側にpushしたソースコードが即時に反映される開発用のデプロイです。ウェブブラウザーで開いたURLの末尾が/dev
になっています。このURLには、Apps Scriptの編集権限を持っている人しかアクセスできないことに注意してください。
さて、ウェブアプリを確認してみると、Viteのロゴが表示されていません。一方、Reactのロゴは正しく表示されています。
ソースコードを確認してみると、それぞれのロゴデータの置き場所が異なるようです。
.
├── public
│ └── vite.svg
└── src
├── assets
│ └── react.svg
├── App.jsx
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "vite.svg";
今回は、正しく表示されているReactのロゴに合わせて、Viteのロゴを移動してみます。
mv public/vite.svg src/assets
import { useState } from "react";
import reactLogo from "./assets/react.svg";
- import viteLogo from "vite.svg";
+ import viteLogo from "./assets/vite.svg";
ここまで作業できたら、まずローカル環境で正しく動作しているか確認しましょう。
npm run dev
正しく動作していれば、buildとpushをして、@HEADデプロイを確認します。
npm run build && clasp push
clasp open --webapp
(@HEADを選びます)
今度は正しく動作しているようです。
5. ウェブアプリをデプロイして他の人が使えるようにする
ここまでは開発用の@HEAD
デプロイメントで動作を確認してきました。このデプロイはApps Scriptの編集権限を持っている開発者しかアクセスできません。
ウェブアプリを自分以外にも使ってもらうためには、新しくデプロイする必要があります。具体的にはマニフェストファイルappsscript.json
、webapp
、access
にMYSELF
以外(DOMAIN
、ANYONE
、ANYONE_ANONYMOUS
)を設定する場合です。
なお、ウェブアプリのURLは新しくデプロイをすると変更されます。URLは変更せずに、ウェブアプリの動作を変える場合には、deployment IDを指定した再デプロイを実行する必要があります。
とはいえ、最初の一度は新しくデプロイする必要があります。
clasp deploy
Created version 1.
- AKfycbwQgENC3rb2Upr6crhbCJPcfMRbP_Mk9tyw-9kgYSyNrxGrm18ZUJUTNfK7WBqR9g6DmA @1.
Created version 1.の次の行、@1 までの文字列が deployment IDです。再デプロイに必要となります。clasp deployments
を実行すると、再表示できます。
clasp deployements
2 Deployments.
- AKfycbzLwLPOUK5pChztlBpdGeQDpoSDcAlP-WsJm1els15I @HEAD
- AKfycbwQgENC3rb2Upr6crhbCJPcfMRbP_Mk9tyw-9kgYSyNrxGrm18ZUJUTNfK7WBqR9g6DmA @1
自分以外の人も使えるウェブアプリのURLは、末尾が/exec
になっています。clasp open --webapp
で、新しくデプロイしたウェブアプリを選択し、ウェブブラウザーのURLを自分以外の人に動作の確認をお願いしてください。
ウェブアプリの修正が完了したら再デプロイする
ウェブアプリの修正をし、@HEAD
デプロイでの動作が完了したら、再デプロイが必要になります。再デプロイするまでは、他の人のウェブアプリに動作は反映されません。
他の人に「修正したって聞いたけど、前と動作が同じだよ」と連絡をもらったら、再デプロイし忘れていないかを確認しましょう。
再デプロイはdeployment IDを指定する必要があります。
clasp deploy --deploymentId AKfycbwQgENC3rb2Upr6crhbCJPcfMRbP_Mk9tyw-9kgYSyNrxGrm18ZUJUTNfK7WBqR9g6DmA
Created version 2.
- AKfycbwQgENC3rb2Upr6crhbCJPcfMRbP_Mk9tyw-9kgYSyNrxGrm18ZUJUTNfK7WBqR9g6DmA @2.
再デプロイすると、@の後のバージョン番号が増えていきます。
開発用・本番用のデプロイまとめ
開発用と本番用でデプロイが分かれているのは、慣れてしまえば便利ですが、最初は混乱しがちです。特徴を以下にまとめておきます。
開発用デプロイ | 本番用デプロイ | |
---|---|---|
URL | 末尾が/dev
|
末尾が /exec
|
アクセスできるのは | 自分だけ2 | 自分以外も3 |
修正後の動作確認 | pushだけでOK | 再デプロイが必要 |
なお再デプロイにはdeployment IDが必要です。再デプロイではなく、新しくデプロイするとURLが変更になるのでご注意ください。
参考にした記事
次の記事を大いに参考にさせていただきました。とてもわかりやすい記事をありがとうございます。
題材は同じなのですが、この記事とは細かい相違点があります。
- ビルドした成果物を
dist
に格納し、gitの管理対象外とする- 成果物は他のソースコードからいつでも再生成できます
- 成果物はサイズも大きくなりがちです
- 上記の理由から、
dist
はgitでは管理していません
- 開発用デプロイを使った動作確認
- pushするだけで(デプロイ不要で)動作が変わる開発用デプロイ
@HEAD
の使い方を紹介しています
- pushするだけで(デプロイ不要で)動作が変わる開発用デプロイ