🔧
React on GAS on Spreadsheet 環境構築
はじめに
React を スプレッドシート上で動かすための環境構築について記述します。
create vite
yarn create vite {projectName} --template react-ts
cd {projectName}
yarn
server と client に分ける
mkdir src/client
mkdir src/server
mv src/*.* src/client/.
sed -i -e "s/main.tsx/client\/main.tsx/g" index.html #main.tsx の場所が変わったことに対応
server 側
types をダウンロード
yarn add -D @types/google-apps-script
server/main.ts
を作成
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const onOpen = () => {
const menu = SpreadsheetApp.getUi().createMenu("メニュー").addItem("ダイアログ表示", "openDialog");
menu.addToUi();
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const openDialog = () => {
const html = HtmlService.createHtmlOutputFromFile("index").setWidth(600).setHeight(600);
SpreadsheetApp.getUi().showModalDialog(html, "タイトル");
};
interface SheetData {
name: string;
numOfRows: number;
}
// TODO: テスト用の関数なので、適切なものに変更する
const getSheetData = (): SheetData => {
const sheet = SpreadsheetApp.getActiveSheet();
return {
name: sheet.getName(),
numOfRows: sheet.getMaxRows(),
};
};
// TODO: テスト用の関数なので、適切なものに変更する
const appendRowsToSheet = (sheetName: string, rowsToAdd: number): void => {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
if (!sheet) return;
sheet.insertRowsAfter(sheet.getMaxRows(), rowsToAdd);
sheet.getRange(1, 1, 5, 5).setValues([
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25],
]);
};
export { getSheetData, appendRowsToSheet };
client 側
gas-client
を追加
yarn add gas-client
client/App.tsx
を変更
import "./App.css";
import { GASClient } from "gas-client";
import * as server from "../server/main";
const { serverFunctions } = new GASClient<typeof server>();
function App() {
const handleButtonClick = async () => {
const sheetData = await serverFunctions.getSheetData();
console.log(sheetData);
serverFunctions.appendRowsToSheet("シート1", 1);
};
return (
<div className="App">
<button type="button" onClick={handleButtonClick}>
ボタン
</button>
</div>
);
}
export default App;
GAS で使えるように一つの html にまとめてビルドできるようにする
プラグインの追加
yarn add -D vite-plugin-singlefile
version によってはビルドできない可能性あり
vite.config.ts
の編集
// eslint-disable-next-line import/no-extraneous-dependencies
import react from "@vitejs/plugin-react";
// eslint-disable-next-line import/no-extraneous-dependencies
import { defineConfig } from "vite";
// eslint-disable-next-line import/no-extraneous-dependencies
import { viteSingleFile } from "vite-plugin-singlefile";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), viteSingleFile()],
build: {
rollupOptions: {
output: {
manualChunks: () => "everything.js",
},
},
},
});
参考: https://github.com/vitejs/vite/issues/621#issuecomment-824418351
GAS にデプロイできるようにする
clasp create
## clasp を未インストールの場合
# yarn global add @google/clasp
# clasp login
clasp create # 作成したいスクリプトの種類を選択
# Spreadsheet で使用する場合は sheets を選択
.clasp.json
の編集
rootDir
を./claspDist
に変更する
appsscript.json
を編集
timeZone
をAsia/Tokyo
にする
デプロイ用の scripts を追加
package.json
のscripts
に追加する
{
...
"scripts": {
...
"deploy": "mkdir claspDist && cp -r src/server/* claspDist && cp dist/index.html claspDist && cp appsscript.json claspDist && clasp push && rm -rf claspDist"
}
...
}
デプロイする
yarn build
yarn deploy
おわりに
以上で、React を Spreadsheet 上で動かすことができました 🎉
備忘録
Variable 'console' must be of type 'Console', but here has type 'console'
というエラーが発生した場合
package.json
のpostinstall
で対応する
{
...
"scripts": {
"postinstall": "sed -i -e \"s/^declare var console/\\/\\/declare var console/g\" node_modules/@types/google-apps-script/google-apps-script.base.d.ts"
}
...
"devDependencies": {
"@types/google-apps-script": "^1.0.45",
...
}
}
参考: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/32585#issuecomment-637895138
Discussion