LoginSignup
17
4

More than 3 years have passed since last update.

Functions FrameworkでTypeScriptを使いつつCloud Functionsにデプロイする

Last updated at Posted at 2021-03-22

GCPでサーバレスアーキテクチャを採用する場合、FaaSであるCloud Functionsの利用を検討するかと思います。FaaSといえばNode.jsというイメージ(個人の感想です)もありますし、Node.jsを使うならTypeScriptを使いたいですよね。

一方、サーバレスアーキテクチャはクラウドサービス依存が強く、ローカルに開発環境を作るのに苦労しがちです。そこで、Googleが提供しているFunctions Frameworkを使って開発環境を整え、Cloud Functionsにデプロイするところまでをやってみます。

事前準備

2021/03/22時点で、Cloud FunctionsにおけるNode.jsの安定バージョンは12系なので、ローカルにもNode.jsの12系をインストールしてください。
また、Cloud Funcionsにデプロイするためにgcloudコマンドが必要です。Macを使っている方はHomebrew-caskでインストールできます。

$ brew cask install google-cloud-sdk

Functions Framework + TypeScript の開発環境を作る

リポジトリにFunctions FrameworkでTypeScriptを使う場合のドキュメントがあるので、説明に従って開発環境を作っていきます。

$ cd /path/to/your/workspace
$ npx gts init

package.json を作るかどうか聞かれるので、そのままEnterで作ってもらいましょう。

次に、必要なパッケージをインストールし、

$ npm install @google-cloud/functions-framework
$ npm install @types/express concurrently nodemon --save-dev

npm-scriptsにローカルでFunctions Frameworkを動かすためのコマンドを追記します。

package.json
  "scripts": {
    "start": "functions-framework --source=build/src/ --target=helloWorld",
    "watch": "concurrently \"tsc -w\" \"nodemon --watch ./build/ --exec npm run start\"",
    ...
  }

自動生成された src/index.ts を以下のサンプルの内容で上書きし、

src/index.ts
import type { HttpFunction } from '@google-cloud/functions-framework/build/src/functions';

export const helloWorld: HttpFunction = (req, res) => {
  res.send('Hello, World');
};

起動すると、ローカルのURLにアクセスできるようになります。

$ npm run watch
$ curl http://localhost:8080
実行結果
Hello, World

たったこれだけで、Cloud Functions + TypeScript の開発環境を構築できました :rocket:

Cloud Functionsにデプロイする

gcloudコマンドでデプロイしてみましょう。

$ gcloud functions deploy sample \
    --project YOUT_PROJECT_ID \
    --allow-unauthenticated \
    --runtime nodejs12 \
    --trigger-http \
    --entry-point helloWorld

はい、失敗しましたね :sob:
以下のようなエラーが出ているはずです。

実行結果(抜粋)
ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Build failed: > @0.0.0 prepare /workspace
> npm run compile


> @0.0.0 compile /workspace
> tsc

sh: 1: tsc: not found

Cloud Functionsでは、package.jsonpackage-lock.json を含めてデプロイすると、 npm ci が使用され、prepare スクリプトが常に実行されます。

package.json を見ると、prepare スクリプトとしてtscコマンドが実行されるようになっていますが、npm ci ではdevDependenciesがインストールされないため、tscコマンドが見つからずエラーになってしまいます。

package.json
  "scripts": {
    ...
    "compile": "tsc",
    "fix": "gts fix",
    "prepare": "npm run compile",
    ...
  }

typescript npmをdependenciesとしてインストールすれば解決しそうですが、合わせて他のnpmもdependenciesとしてインストールしなければならず、アプリケーションの実行と関係ないファイルが大量に含まれてしまいます。

そこで、prepare スクリプトを削除し、デプロイする前にコンパイルしておくことで、余計なファイルが含まれないようにします。

package.json
  "scripts": {
    ...
    "compile": "tsc",
    "fix": "gts fix",
-   "prepare": "npm run compile",
    ...
  }
$ npm run compile

コンパイル結果は build ディレクトリに出力されます。

デプロイする際 .gcloudignore というファイルが自動生成されますが、そのままだと余計なファイルが含まれてしまうため、以下の内容で上書きします。

.gcloudignore
*
!build/**
!package*.json
!.

コンパイル結果と package.json package-lock.json があればアプリケーションを実行するには十分、ということです。

デプロイに再チャレンジ

それでは、再度gcloudコマンドでデプロイしてみましょう。

$ gcloud functions deploy sample \
    --project YOUT_PROJECT_ID \
    --allow-unauthenticated \
    --runtime nodejs12 \
    --trigger-http \
    --entry-point helloWorld
実行結果(抜粋)
entryPoint: helloWorld
httpsTrigger:
  securityLevel: SECURE_OPTIONAL
  url: https://us-central1-{YOUT_PROJECT_ID}.cloudfunctions.net/sample
ingressSettings: ALLOW_ALL
labels:
  deployment-tool: cli-gcloud
name: projects/{YOUR_PROJECT_ID}/locations/us-central1/functions/sample
runtime: nodejs12

無事にデプロイできました :tada:

$ curl https://us-central1-{YOUT_PROJECT_ID}.cloudfunctions.net/sample
実行結果
Hello, World

Cloud FunctionsのURLにもアクセスできましたね :sparkles:
作成したFunctionをGCPの管理コンソールで見ると、 以下のように余計なファイルが含まれていないことが分かります。

スクリーンショット 2021-03-20 1.15.10.png

最後に

今回はトリガーとしてHTTPを試しましたが、Cloud StorageやCloud Pub/Sub等のGCPで発生する各種イベントをトリガーとして実行させることもできます。また、Cloud FunctionsだけではなくCloud RunやKnativeで実行させることもできるため、用途に応じて使い分けられるのも良いですね。

なお、Functions FrameworkはNode.js以外の言語でも提供されているので、他の言語で使いたい方はぜひリポジトリを探してみてください。

17
4
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
17
4