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のみがデプロイされていますので、こいつを実行してやりましょう。

    参考

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark