🔖

Cloud Functions + TypeScript の開発を始める

2022/01/25に公開約4,400字

node.js アプリケーションを作成

npm init
gibo dump node >> .gitignore
echo "build" >> .gitignore

Node.js の Functions Framework をインストール

npm install @google-cloud/functions-framework

参考:3. Install the Functions Framework for Node.js

TypeScript 対応

npx gts init
npm install @types/express concurrently nodemon --save-dev

package.json に以下を追加。

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

scr/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');
};

参考:functions-framework-nodejs/docs/typescript.md

とりあえずローカルで動かしてみる

npm run watch

http://localhost:8080/を開くと、「Hello World」が表示されます。

Cloud Functions にデプロイする

package.json を修正します。

package.json
- "main": "index.js",
+ "main": "build/src/index.js",

- "prepare": "npm run compile",

デプロイコマンドを実行します。

gcloud functions deploy helloWorld \
--runtime nodejs16 \
--trigger-http \
--region asia-northeast1

コンソール上にデプロイされた URL が表示されるので、アクセスすると hello world が表示されます。

関数名をhelloWorld から変更する

ここまでの手順ではsrc/index.tsの関数は helloWorld となっています。

import type { HttpFunction } from "@google-cloud/functions-framework/build/src/functions";

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

関数名を変更してデプロイしてみます。

たとえば getTitles に関数名を変更してみます。

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

export const getTitles: HttpFunction = (req, res) => {
  res.send('タイトルを取得しました。');
};

package.jsonを以下のように修正します。

package.json
-  "start": "functions-framework --source=build/src/ --target=helloWorld",
+  "start": "functions-framework --source=build/src/ --target=getTitles",
npm run clean
npm run compile

gcloud functions deploy getTitles \
--runtime nodejs16 \
--trigger-http

CORS エラーを回避する

Ajax で値を取得しようとすると、がアカン!みたいなエラーが出ると思います。

そういうときは、以下のようにAccess-Control-Allow-Originを設定する方法も使えます。
セキュリティが気になる方は設定しないほうがいいですが。

src/index.ts
export const getTitles: HttpFunction = (req, res) => {
  res.set("Access-Control-Allow-Origin", "*")
  res.send('タイトルを取得しました。');
};

修正して再デプロイしたときに、エラーが出た

ローカルで修正して再度デプロイをしようとしたときにエラーが出ました。

ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Build failed: build/src/index.js does not exist; Error ID: xxx

試したこと

clean → compile の再実施。

npm run clean
npm run compile

gcloud functions deploy getTitles \
--runtime nodejs16 \
--trigger-http

これではうまくいかず、同じエラーが出ました。

以下の記事の方に合わせて tsconfig.jsonoutDirlib にしてみました。
Firebase Cloud Functions の実行ファイルが見つからないときにやったこと

tsconfig.json
{
  "extends": "./node_modules/gts/tsconfig-google.json",
  "compilerOptions": {
    "rootDir": ".",
+    "outDir": "lib",
    "target": "es6",
    "lib": ["esnext", "dom", "dom.iterable"]
  },
  "include": [
    "src/**/*.ts",
    "test/**/*.ts"
  ]
}
package.json
+  "main": "lib/src/index.js",
  "scripts": {
+    "start": "functions-framework --source=lib/src/ --target=getTitles",
+    "watch": "concurrently \"tsc -w\" \"nodemon --watch ./lib/ --exec npm run start\"",
    "lint:gts": "gts lint",

これで再度 clean → compile で再デプロイしたらエラーが出なくなりました。

npm run clean
npm run compile

gcloud functions deploy getTitles \
--runtime nodejs16 \
--trigger-http

後に、以下の記事を読んで、うまくデプロイされない理由は .gitignorebuild を追加してしまっていて、それが .gcloudignoreに読み込まれてしまっていたからだったかな?と思いました。

Google Cloud Function deploy error: provided function is not a loadable module

How to include files in .gcloudignore that are ignored in .gitignore

GitHubで編集を提案

Discussion

ログインするとコメントできます