やってみた。実用に耐えうるかはわからないけどメモ。
環境構築
- node.js 8.11.x(LTS)
- Azure Function Core Tools v2(preview)
- VSCode
- TypeScript 3.0
npm install -g typescript
やってみよう
Visual Studio Code の左のメニューから Azure のアイコンを選択。自分の Azure のアカウントでログインしてたら使えるはずです。(ログインしてない状態だとどうなってるのか把握できていない)
FUNCTIONS の部分にある Create New Project...
を選択します。
フォルダを選択して言語は JavaScript を選択します。
ターミナルを出して以下のコマンドを打ちます。(Windows だと Ctrl + Shift + ` で出せます)
npm init -y npm i express npm i @line/clova-cek-sdk-nodejs npm i azure-function-express npm i -D @types/node tsc -init
azure-function-express は、型定義がないので追加します。とりあえず、使う関数は1つなのでさくっと自作しちゃいます。
@types/azure-function-express/index.d.ts
をプロジェクトの下に作成して以下の内容を定義します。
import express from'express';declaremodule'azure-function-express'{exportfunction createHandler(app: express.Express): Function;}
次に tsconfig.json
を以下のように編集しておきます。
{"compilerOptions": {"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */"lib": ["es2015"], "strict": true, /* Enable all strict type-checking options. */"sourceMap": true, "baseUrl": "./", /* Base directory to resolve non-absolute module names. */"paths": {"*": ["@types/*"]}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */"esModuleInterop": true/* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */}}
tsconfig.json
を編集したら Visual Studio Code を再起動しておきましょう。
続けて関数を作ります。プロジェクトを作成したときのボタンの横の方に Create Function...
というボタンがあるので押します。
自分のプロジェクトのフォルダを選択して Http trigger を選択して名前に clova
と入力して Enter を押します。認証は Function あたりを選んでおきましょう。Anonymous にするとインターネットにさらけ出す感じになります。Function を選ぶと URL のクエリに関数を呼び出すために必要なキー文字列が必要になります。(まぁ Clova のライブラリをちゃんと使ってれば不正なリクエストは弾いてくれるので構わないといえば構わない)
clova フォルダが作成されるので、その中の index.js
を削除して index.ts
を作成します。中身はこんな感じです。
import{ createHandler }from'azure-function-express';import * as clova from'@line/clova-cek-sdk-nodejs';import express from'express';const skillHandler =<express.RequestHandler>clova.Client .configureSkill() .onLaunchRequest((responseHelper: clova.Context)=>{ responseHelper.setSimpleSpeech( clova.SpeechBuilder.createSpeechText('おはよう'));}) .onIntentRequest((responseHelper: clova.Context)=>{const intent = responseHelper.getIntentName();switch(intent){case'ThrowDiceIntent': responseHelper.setSimpleSpeech( clova.SpeechBuilder.createSpeechText('サイコロをふるね'));break;default: responseHelper.setSimpleSpeech( clova.SpeechBuilder.createSpeechText('何かインテントが来たよ'));break;}}) .onSessionEndedRequest((responseHelper: clova.Context)=>{// do something on session end}) .handle();const app = express();const clovaMiddleware = clova.Middleware({ applicationId: "YOUR_APPLICATION_ID"}); app.post('/api/clova',(req, res, next)=>{ req.body =(<any>req).rawBody;// Clova のミドルウェアを azure-function-express で動かすためのおまじない next();}, clovaMiddleware, skillHandler);export= createHandler(app);
インテリセンス(MS 用語、コードの補間のこと)も出るよ!
tsc コマンドあたりでコンパイルしてみましょう。VSCode で Ctrl + Shift + B
でもコンパイルするタスクが出てきます。
実行して動作確認
ローカル実行
F5 を押すとデバッグ実行になります。ngrok http 7071
を実行してインターネットからアクセスできるようにしましょう。
Azure Functions v1 の場合の ngrok について
オプションが必要なので、これを見てね。
LINE Clova の Extension から動かしてみて動作確認
サーバーの URL を ngrok で取得した URL に対して /api/clova
を追加したものを設定して動かします。
index.ts.js
の 33 行目の YOUR_APPLCIATION_ID
のところは自分の値に書き換えてから実行してください。
うまくいけば動きます。またソースマップも出すように tsconfig.json
を構成しているので、ちゃんと index.ts
に対してブレークポイントをはれば以下のようにデバッグも出来ます。
Azure にデプロイ
‘Deploy to Function App...` からデプロイ出来ます。
既存のものにデプロイしたり、新しいものにデプロイすることも出来ます。
デプロイしたら、関数を選んで </> 関数の URL の取得
を押したら出てくる画面で関数の URL をゲットしましょう。
この URL を LINE の Clova の Extension のサーバー設定に入力します。
まとめ
なるべくタイプセーフになるように TypeScript を使って Azure Functions にデプロイして試してみました。 意外と簡単だったのでいいかもしれない。
コードは以下のリポジトリにあげてます。clone してから local.settings.json
ファイルを以下の内容で作成すると動くと思います。
{"IsEncrypted": false, "Values": {"AzureWebJobsStorage": "", "FUNCTIONS_WORKER_RUNTIME": "node"}}