clasp + webpackでGAS(Google App Script)のコードをTypeScriptで書く
claspでGAS(Google App Script)のコードを簡単にデプロイできます。Serverless FrameworkのGAS版っぽい感じ。 ただ、npmのライブラリを使う時に工夫が必要だったのでそれをまとめ […]
目次
claspでGAS(Google App Script)のコードを簡単にデプロイできます。Serverless FrameworkのGAS版っぽい感じ。
ただ、npmのライブラリを使う時に工夫が必要だったのでそれをまとめました。
プロジェクトの作成
$ mkdir example && cd example
$ clasp create example-app --rootDir ./dist
続けて必要なファイルを空で作っておきます。以下のようなディレクトリ構成になればOKです。
$ mkdir src
$ touch src/Code.ts src/index.ts webpack.config.js .babelrc
$ tree -L 2 -I node_modules
.
├── dist
│ └── appsscript.json
├── package.json
├── src
│ ├── Code.ts
│ └── index.ts
├── .babelrc
├── .clasp.json
├── tsconfig.json
└── webpack.config.js
webpack / TypeScript / Babel
clasp自身もTypeScriptのコンパイルは実行してくれます。ただ、トランスパイルするだけでimport / requireしたnpmライブラリのコードがデプロイされません。
ということで、自前でビルドするようにします。
# webpack
$ yarn add -D webpack webpack-cli gas-webpack-plugin es3ify-webpack-plugin
# babel
$ yarn add -D @babel/core @babel/preset-env @babel/preset-typescript babel-loader
# typescript
$ yarn add -D typescript @types/google-apps-script
webpack.config.js
webpackの設定は参考記事の設定そのままにしています。
const path = require('path');
const GasPlugin = require('gas-webpack-plugin');
const Es3ifyPlugin = require('es3ify-webpack-plugin');
module.exports = {
mode: 'development',
devtool: 'inline-source-map',
context: __dirname,
entry: {
main: path.resolve(__dirname, 'src', 'index.ts')
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js'
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.[tj]s$/,
loader: 'babel-loader'
}
]
},
plugins: [new GasPlugin(), new Es3ifyPlugin()]
};
.babelrc
こちらも設定は参考記事の設定そのままにしています。
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"browsers": ["ie 8"]
}
}
],
"@babel/preset-typescript"
]
}
tsconfig.json
こちらも設定は参考記事の設定そのままにしています。
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": [
"es2015",
"es2016",
"es2017",
"es2018"
],
"allowJs": true,
"declaration": false,
"outDir": "./dist",
"rootDir": "./src",
"downlevelIteration": true,
"strict": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": ["./src/**/*"]
}
.gitignore
Git管理する場合、distディレクトリのappscript.json
は管理下におく必要があります。ですので、以下のようにビルドされたJSファイルだけ除外するようにしておきます。
node_modules/
dist/*.js
package.json
ビルド->デプロイで2コマンド打つ必要があります。ですのでnpm-scriptを定義しておきましょう。
{
"scripts": {
"build": "webpack",
"deploy": "npm run build && clasp push",
"watch": "watch 'npm run deploy' ./src"
},
src/Code.ts
ここに実行するコードを記述します。
export function getUpdatedCalander(e: GoogleAppsScript.Events.CalendarEventUpdated): void {
try {
console.log('Event')
console.log(e)
const calander = CalendarApp.getCalendarById(e.calendarId)
const today = new Date()
const next = new Date()
next.setMonth(next.getMonth() + 2)
const events = calander.getEvents( today, next )
events.forEach(event => {
console.log(event.getTitle())
})
} catch (err) {
console.log('Error')
console.log(err)
}
}
イベントの引数はGoogleAppsScript.Events
内に定義されていますので、使いたいトリガーに応じて設定すると良いでしょう。
src/index.ts
最後にglobal
オブジェクトに関数を刺してやります。
import {getUpdatedCalander} from './Code'
declare const global: {
[x: string]: any ;
}
global.getUpdatedCalander = function(e: any) {
return getUpdatedCalander(e)
}
デプロイ
あとはnpm run deploy
でGASにデプロイすればOKです。
index.gs
のみがデプロイされていますので、こいつを実行してやりましょう。