LoginSignup
19
21

More than 5 years have passed since last update.

React で Google Apps Scriptを書く!

Last updated at Posted at 2018-12-19

Google Apps Script で React を使った開発をしたいと思います。

Google Apps ScriptはGoogle DocsなどGoogleのサービスの拡張やアドオンをJavaScriptで書ける仕組みです。Apps Script は ちょっとした便利ツールの作成には大変よいのですが、本格的に開発を進める場合、素のJavaScriptを書くのはイヤなので、Reactなどのモダンなライブラリを使用したくなります。そこで、モダンなJSのアーキテクチャーにのっとって、Apps Scriptを書いてみたいと思います。
類例の試みはいろいろあるのですが、Reactを導入する実践的なサンプルをあまり見たことがないので、ここでは簡単なサンプルを提供し、内容を解説してみたいと思います。

なお、コードはすべて以下のリポジトリにあげてあります。
https://github.com/takada-at/gas-react

サーバー・クライアントを整理

少し複雑なのですが、Google Apps Script で動くコードは、「サーバー用のコード」と「クライアント用のコード」にわかれます。ここで「サーバー用のコード」と言っているのは、ドキュメントオープン時やメニューでのコマンド選択時に実行される .gs拡張子のついたスクリプトのことです。「Google Apps Script」と言ったときに通常イメージされるのはこれですね。

また、サーバー用のコードでは、Apps Script用の特殊なJavaScript関数を呼び出すことができます。大半はDocsやSpreadsheetの操作用のAPIです。

一方、Apps Scriptでは、サイドメニューやダイアログといったUIを、HTML+JavaScriptで書くことができます。ここでは、このUI用のJavaScriptコードを「クライアント用のコード」と呼びます。クライアント用のコードは基本的に通常のJavaScriptですが、リモートプロシージャコールのような形で、サーバー用のコードの関数を実行できる仕組みが用意されています。

ReactはもちろんUI用のライブラリなので、クライアント側で使用します。言語としてはES2015(ES6)を採用し、サーバー側もクライアント側もwebpack(+babel-loader)を使ってJavaScriptに変換することにします。クライアントに関しては、React用の言語であるJSXも併用します。

言語 変換
サーバー ES2015 webpackで変換
クライアント ES2015 + JSX webpackで変換

サンプルの中身

サンプルとして、Spreadsheetの拡張を用意しました。メニュー(「アドオン」「GasReact」)から「Show Sidebar」を選ぶとサイドバーを表示します。サイドバー内の「Load」をクリックすると、シートのいずれかの列の値を読みとり、UIに表示します。

スクリーンショット 2018-12-19 16.56.04.png
スクリーンショット 2018-12-19 16.57.07.png
スクリーンショット 2018-12-19 16.55.51.png

サーバー用コード

サーバー用のコードはこちらです。中身はシンプルで、メールアドレスを取得する関数と、列を指定してシートの中身を読む関数をAPIとして提供している他、メニューの表示などの設定をしているだけです。

クライアント用コード

クライアント用のソースコードはこちらです。React + Redux(+Redux Saga)を使用しています。分量はそこそこありますが、大半はUIと、サーバー側との通信のためのコードなので、詳しく解説しません。

あとで説明するように、サーバー側の関数をリモートプロシージャコールする箇所は、コードを自動生成しています。

webpackの設定

webpackの設定はこんな感じです。Apps Script上で動かすために、gas-webpack-plugines3ify-webpack-pluginというプラグインを使用します。gas-webpack-pluginは、Apps Script環境用にグローバールな関数の設定を可能にするプラグイン、es3ify-webpack-pluginは、古いJS環境向けの変換用のプラグインです。

# プラグインの設定
  plugins: [
    new GasPlugin(),
    new Es3ifyPlugin(),
    new webpack.EnvironmentPlugin(['NODE_ENV'])
  ],
# エントリポイントの設定クライアント用コードサーバー用コードがそれぞれ1ファイルにバンドルされる
  entry: {
    server: './Server/index.js',
    client: './Client/client.jsx'
  },
  externals: {
    'react': 'React',
    'react-dom': 'ReactDOM'
  },
  output: {
    filename: "[name].bundle.js",
    path: path.resolve(__dirname, './build')
  },

クライアント用コードの変換

Apps Script固有の事情として、HTML内で使用するクライアント側コードは、拡張子を.htmlにし、<script>タグでマークアップし、HTML断片として作成する必要があります。今回のプロジェクトでは、webpackでクライアント用のバンドルJSファイルを作成したあと、この変換をかますスクリプトを別途作成しました。Apps Scriptへのアップロードも、こちらのスクリプトの中でやっています。

# クライアント用コード
# scriptタグでマークアップするとともに、遅延ロードさせている。
<script>
window.addEventListener('load', function() {
  ${content}
}) 
</script>

また、サーバーのAPIをリモートプロシージャコールする部分は、お決まりの処理になるので、スクリプトで自動生成できるようにしています。今回のような簡易的プロジェクトだと大げさですが、大規模開発になった場合はおそらくこの種の仕組みがあると便利でしょう。

19
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
21