2018年7月12日に Clova Extensions Kit(CEK) がリリースされました。
チュートリアルは既に皆さまやっているようなので置いといて、
公式の Clova SDK を使ってサンプルスキルを heroku にデプロイしてみました。
実装は TypeScript を用いています。
CEK の基礎や CEK の使い方などは @imajoriri さんの以下の記事が詳しいです。
開発環境
$ heroku -v
heroku/7.7.1 darwin-x64 node-v10.6.0
$ node -v
v8.11.2
$ npm -v
6.1.0
$ git --version
git version 2.15.2 (Apple Git-101.1)
事前準備
- git
- heroku CLI
- node
CEK で Extension を作成
詳細は既に皆さまが書かれておりますので割愛します。
-
プロバイダー
を登録 -
チャネル
を作成 -
基本設定
を入力- Extension ID は後ほど使いますのでメモメモ
-
サーバー設定
はとりあえずスルー- 後でやります
-
配布情報
は今回はリリースしないのでスルー -
個人情報の保護および規約同意
も今回はリリースしないのでスルー -
対話モデル
へ
対話モデル
- カスタムインテントには 「KinokoIntent」を1個追加
- サンプル発話にはとりあえず「きのこ」と「キノコ」を設定
テスト
- サーバーの設定はしてないので、応答はありません。
スキルの実装側を作成
基本的に README.md を参照しました。
ゴールは https://github.com/chibi929/hello-clova に置きました。
プロジェクト作成
$ mkdir hello-clova
$ cd hello-clova
# リモートリポジトリはあとで `heroku CLI` が設定してくれるので init だけで OK
$ git init
# `npm init` は適当にスキップなり入力なり
$ npm init
$ npm install --save @line/clova-cek-sdk-nodejs body-parser express
$ npm install --save--dev typescript
# `src/` には後でソースコードを置きます。
$ mkdir src
package.json
{
"name": "hello-clova",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"engines": {
"node": "8.x"
},
"dependencies": {
"@line/clova-cek-sdk-nodejs": "^1.0.1",
"body-parser": "^1.18.3",
"express": "^4.16.3"
},
"devDependencies": {
"typescript": "^2.9.2"
}
}
tsconfig.json
TypeScript 用に tsconfig.json を用意
{
"compileOnSave": false,
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "lib",
"noImplicitReturns": true,
"sourceMap": true,
"lib": ["es6"]
},
"include": [
"src/"
]
}
たしか firebase init
から生まれた tsconfig.json
を使い回していたような。。。
ソースコード
Clova SDK のリポジトリにあった example/echo を参考に TypeScript のコードを書く
import { Client, SpeechBuilder, Middleware } from '@line/clova-cek-sdk-nodejs';
import * as express from 'express';
const app = express();
const launchHandler = async responseHelper => {
responseHelper.setSimpleSpeech(
SpeechBuilder.createSpeechText('おはよう')
);
};
const intentHandler = async responseHelper => {
const intent = responseHelper.getIntentName();
const sessionId = responseHelper.getSessionId();
switch (intent) {
+ case 'KinokoIntent':
+ responseHelper.setSimpleSpeech(
+ SpeechBuilder.createSpeechText('きのこのこのこ元気の子')
+ );
+ break;
case 'Clova.YesIntent':
responseHelper.setSimpleSpeech(
SpeechBuilder.createSpeechText('はいはい')
);
break;
case 'Clova.NoIntent':
responseHelper.setSimpleSpeech(
SpeechBuilder.createSpeechText('いえいえ')
);
break;
default:
responseHelper.setSimpleSpeech(
SpeechBuilder.createSpeechText('なんなん')
);
break;
}
};
const sessionEndedHandler = async responseHelper => { };
- const clovaHandler = Client
+ // TypeScript だと RequestHandler 型にしないと怒られるのでとりあえず any で逃げる
+ const clovaHandler: any = Client
.configureSkill()
.onLaunchRequest(launchHandler)
.onIntentRequest(intentHandler)
.onSessionEndedRequest(sessionEndedHandler)
.handle();
const clovaMiddleware = Middleware({ applicationId: process.env.APPLICATION_ID });
app.post('/clova', clovaMiddleware, clovaHandler);
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Server running on ${port}`);
});
- KinokoIntent のハンドリング
- 型違いで怒られたので修正
ビルド
その前に package.json を修正
{
"name": "hello-clova",
"version": "1.0.0",
"description": "",
- "main": "index.js",
+ "main": "lib/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
+ "build": "tsc"
},
"author": "",
"license": "ISC",
"dependencies": {
"@line/clova-cek-sdk-nodejs": "^1.0.1",
"body-parser": "^1.18.3",
"express": "^4.16.3"
},
"devDependencies": {
"typescript": "^2.9.2"
}
}
-
tsconfig.json
によりlib/
以下にビルドしたものが生成される -
npm run build
を使えるようにする
ビルド
$ npm run build
> hello-clova@1.0.0 build /private/tmp/hello-clova
> tsc
$ ls
lib node_modules package.json src tsconfig.json
- こうなれば OK
トラブルシュート
$ npm run build
> /private/tmp/hello-clova
> tsc
node_modules/@line/clova-cek-sdk-nodejs/dist/types/types.d.ts:1:8 - error TS1192: Module '"/private/tmp/hello-clova/node_modules/@types/express/index"' has no default export.
1 import express from 'express';
~~~~~~~
node_modules/@line/clova-cek-sdk-nodejs/dist/types/verifierMiddleware.d.ts:1:8 - error TS1192: Module '"/private/tmp/hello-clova/node_modules/@types/express/index"' has no default export.
1 import express from 'express';
~~~~~~~
と、怒られたが、
Clova SDK の PR#2 を見て解決。
言われるがまま、以下のように tsconfig.json
を修正
tsconfig.json を修正
{
"compileOnSave": false,
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "lib",
"noImplicitReturns": true,
"sourceMap": true,
+ "allowSyntheticDefaultImports": true,
"lib": ["es6"]
},
"include": [
"src/"
]
}
heroku の準備
ログイン
$ heroku login
# ID(メールアドレス) 入力
# パスワード入力
heroku app 作成
$ heroku create
# ここでリモートリポジトリが設定される
Procfile を準備
web: node lib/index.js
環境変数を準備
# process.env.APPLICATION_ID で取得できるようになる
$ heroku config:set APPLICATION_ID="さっきメモメモしといた Extension ID"
# デプロイ後、devDependencies もインストールしたいので false にする
$ heroku config:set NPM_CONFIG_PRODUCTION=false
デプロイ後のビルドコマンド追加
{
"name": "hello-clova",
"version": "1.0.0",
"description": "",
"main": "lib/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "tsc",
+ "heroku-postbuild": "npm run build"
},
"author": "",
"license": "ISC",
"dependencies": {
"@line/clova-cek-sdk-nodejs": "^1.0.1",
"body-parser": "^1.18.3",
"express": "^4.16.3"
},
"devDependencies": {
"typescript": "^2.9.2"
}
}
-
heroku-prebuild
は heroku 上で npm install が完了したら実行される
heroku へデプロイ
$ git add Procfile package.json src tsconfig.json
$ git commit -m "Add project"
$ git push heroku master
~略~
remote: https://${HEROKU_APP_NAME}.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/${HEROKU_APP_NAME}.git
2433fb3..55d6dfc master -> master
-
remote: https://${HEROKU_APP_NAME}.herokuapp.com/ deployed to Heroku
- こんなの出れば OK
アクセス
https://${HEROKU_APP_NAME}.herokuapp.com/
にブラウザでアクセスすると
Cannot GET /
こんな感じですかね?
できてない場合は heroku logs
とかでログ見ないとだー。
CEK の サーバー設定
-
https://${HEROKU_APP_NAME}.herokuapp.com/clova
を設定- これは
index.ts
でPOST /clova
を作ったため
- これは
最後のテスト!
まとめ
もともと heroku の知識があったため、
サンプルの JS を heroku にデプロイして Clova の繋げるまでは 18分 でできました。
その後、記事書きながら TypeScript に置き換えるのに、時間を取られました…
Clova SDK や CEK は、それなりに理解しやすかったです。
(単純に動かすだけなら簡単!!)