🔧

React on GAS on Spreadsheet 環境構築

2022/05/07に公開

はじめに

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 を追加

https://github.com/enuchi/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 によってはビルドできない可能性あり

https://github.com/richardtallent/vite-plugin-singlefile/issues/23

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

https://github.com/google/clasp

## clasp を未インストールの場合
# yarn global add @google/clasp
# clasp login

clasp create # 作成したいスクリプトの種類を選択
# Spreadsheet で使用する場合は sheets を選択

.clasp.jsonの編集

rootDir./claspDistに変更する

appsscript.jsonを編集

timeZoneAsia/Tokyoにする

デプロイ用の scripts を追加

package.jsonscriptsに追加する

{
  ...
  "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.jsonpostinstallで対応する

{
  ...
  "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

GitHubで編集を提案

Discussion