APLドキュメントのレイテンシーを短縮する
ユーザーは、スキルが遅延なくリクエストに応答することを期待しています。スキルに視覚コンポーネントが含まれている場合、コンテンツを表示する際のレイテンシーによってユーザーエクスペリエンスが低下する可能性があります。
Alexa Presentation Language(APL)ドキュメントのパフォーマンスを高め、ユーザーに認識される可能性のあるレイテンシーを低減するには、以下のベストプラクティスを使用してください。
画像の代わりにAlexa Vector Graphics(AVG)を使用する
画像はコンテンツの魅力を高めますが、同時にレイテンシーの増加の原因となる可能性もあります。APLドキュメントで画像を表示する場合、デバイスは指定されたソースURLから画像を読み込む必要があります。
画像の代わりにベクターグラフィックを表示すると、レイテンシーを低減することができます。Alexa Vector Graphics(AVG)形式では、JSONコードでグラフィックを定義できます。定義したグラフィックは、ドキュメントにVectorGraphicコンポーネントを配置することで表示できます。
AVG形式の詳細については、Alexa Vector Graphics形式を参照してください。
VectorGraphicコンポーネントの詳細については、VectorGraphicを参照してください。
長いスクロールリストに動的データソースを使用する
長いスクロールリストを表示する場合は、動的データソースを使用して、データを小さいバッチとしてデバイスに送信します。ユーザーがリストをスクロールすると、Alexaはスキルに追加データをリクエストします。スキルは、表示する新しいデータを含む更新されたデータソースで応答します。
プログレッシブ読み込み(遅延読み込み)は、リストを表示する以下のレスポンシブ対応テンプレートで使用できます。
独自のドキュメントを作成する場合は、以下のコンポーネントでプログレッシブ読み込みを使用できます。
リストでプログレッシブ読み込みを使用するには
- リスト項目を含むデータソースを、
dynamicIndexListデータソースとして定義します。詳細については、dynamicIndexListデータソースを参照してください。 - APLドキュメントで、リストを表示するコンポーネントにデータソースをバインドします。
- レスポンシブ対応テンプレートを使用する場合は、データソースを
listItemsプロパティにバインドします。 Sequenceなどのプリミティブコンポーネントから独自のリストを作成する場合は、データソースをdataプロパティにバインドします。
詳細については、APLドキュメントに動的なデータソースをバインドするを参照してください。
- レスポンシブ対応テンプレートを使用する場合は、データソースを
- スキルコードで、ユーザーのスクロールに応じてディレクティブを使用してリストを管理します。詳細については、ディレクティブとリクエストを使用してリストを管理するを参照してください。
動的データソースの例については、APLの遅延読み込みリストのデモを参照してください。
URLベースのパッケージのインポート数を制限する
APLパッケージを使用すると、共通のレイアウトをリソースとして別のファイルに定義し、importプロパティによってドキュメントにインポートすることができます。パッケージは、管理しやすいモジュール式のAPLドキュメントを作成するための重要な要素です。ただし、パッケージのインポートにはコストがかかります。これは、デバイスでドキュメントをレンダリングする前に、URLまたはキャッシュからパッケージを取得する必要があるためです。さらに、パッケージがほかのパッケージをインポートすることもあるため、負荷が増大する可能性もあります。
パッケージをインポートするときは、以下のガイドラインに従ってください。
- インポートするパッケージがすべて必要なものであることを確認してください。APLドキュメント内で参照していないパッケージは、すべて削除してください。
- 接続を開いてパッケージをダウンロードする時間がかかるため、複数の小さいパッケージをインポートするよりも、単一の大きいパッケージをインポートする方が効率的です。
有効な方針として、レスポンシブ対応コンポーネントとレイアウトを提供するalexa-layoutsをインポートし、必要に応じて、独自のカスタムレイアウトを含むカスタムパッケージを1つ追加で読み込むことをお勧めします。
前のドキュメントに戻るにはバックスタックを使用する
バックスタック拡張機能を使用すると、ユーザーが以前に表示したAPLドキュメントに移動することができます。バックスタックを使用して前のドキュメントに戻るときは、ドキュメントが既にインフレートされているため、デバイスによるドキュメントのレンダリングが高速になります。
バックスタックを使用すれば、スキルにリクエストを送信する必要も、スキルから前のドキュメントを含むRenderDocumentディレクティブが返されるまで待機する必要もなくなります。
バックスタック拡張機能の詳細については、APLバックスタック拡張機能を参照してください。
可能な限りレイアウトを使用する
レイアウトは、プリミティブコンポーネントとレイアウトで構成されたカスタムコンポーネントとして機能します。レイアウトを使用すると、よりモジュール化された管理しやすいドキュメントを作成できます。レイアウトはドキュメント内で再利用できるため、コードの簡素化にもつながります。
レイアウトを使用することで、レイテンシーも低減されます。デバイスは、ドキュメントのインフレート時にレイアウトをキャッシュします。このため、デバイスでドキュメントを表示するにつれて、レイアウトの読み込み速度は速くなります。
カスタムレイアウトの作成方法の詳細については、APLレイアウトを参照してください。
スキルコードへのラウンドトリップではなくオンデバイスで更新を行う
APLドキュメントでSendEventコマンドを使用すると、スキルにUserEventリクエストを送信できます。コードでこのイベントを処理し、応答を返します。応答には、読み上げるコンテンツ、更新されたAPLドキュメントを表示するRenderDocumentディレクティブ、既存のドキュメントを更新するコマンドを実行するExecuteCommandsディレクティブが含まれる場合があります。
SendEventコマンドは、デバイス上で行われた更新をスキルに通知し、Alexaの音声応答をトリガーする場合に便利です。ただし、デバイスとスキル間のこの「ラウンドトリップ」に依存すると、レイテンシーは長くなります。UserEventリクエストからRenderDocumentディレクティブを再送信して、更新されたAPLドキュメントをレンダリングするという処理にも、多くの時間とコストがかかります。
代わりに、APLコマンドを使用して視覚表示を直接更新すれば、スキルにリクエストを送り返して応答を待機する必要はなくなります。可能な限り、RenderDocumentディレクティブを使用してドキュメント全体を再送信することは避けてください。
必要な場合は、視覚的な変更を行った後で、SendEventコマンドを使用してスキルに変更を通知できます。この方法であれば、ユーザーはスキルへのラウンドトリップを待つことなく、視覚的な更新をすぐに確認できます。
たとえば、以下のコマンドの配列は、PressCountというバインドされたプロパティを更新し、アニメーションを実行してTextコンポーネントをフェードインさせてから、バインドされたプロパティの最新の値を含むUserEventをスキルに送信します。ユーザーから見ると、この画面はレイテンシーなしですぐに更新されます。
[
{
"type": "SetValue",
"property": "PressCount",
"value": "${PressCount + 1}"
},
{
"when": "${PressCount == 1}",
"type": "AnimateItem",
"duration": 2000,
"componentId": "buttonPressCount",
"value": {
"property": "opacity",
"to": 1
}
},
{
"type": "SendEvent",
"arguments": [
{
"buttonPressed": "pressCountButton",
"pressCount": "${PressCount}"
}
]
}
]
以下は、APLドキュメント全体の例を示しています。押した回数をカウントボタンを押すと、カウンターの値が増え、ボタンを押した合計回数が画面に表示されます。カウントをリセットボタンを押すと、カウンターが0にリセットされ、ボタンを押した回数を示すテキストが非表示になります。どちらのボタンも、ほかのコマンドが終了した後でSendEventを呼び出して、現在のボタン押下のカウント数をスキルに通知します。
以下は、2つのボタンによって生成されるUserEventのリクエストハンドラーの例です。SendEventは視覚的な更新が行われた後に実行されるため、スキルへのラウンドトリップ中の遅延は認識されにくくなります。
このサンプルコードはAlexa Skills Kit SDK for Node.js(v2)を使用しています。
const ButtonPressEventHandler = {
canHandle(handlerInput){
// このハンドラーを両方のボタンに使用します。
const requestEnvelope = handlerInput.requestEnvelope;
return Alexa.getRequestType(requestEnvelope) === 'Alexa.Presentation.APL.UserEvent'
&& (requestEnvelope.request.source.id === 'pressCountButton'
|| requestEnvelope.request.source.id === 'resetButton');
},
handle(handlerInput){
console.log("In the ButtonPressEventHandler");
// 引数からボタンデータを取得してログに記録します。実際の
// スキルでは、これらの値を永続ストレージに保存したり、
// 入力に固有の音声応答を作成したりできます。
const buttonData = handlerInput.requestEnvelope.request.arguments[0];
console.log("デバイスからボタンの押下に関するデータを取得しました。");
console.log("報告されたボタン押下:" + buttonData.buttonPressed);
console.log("最新のボタン押下カウント:" + buttonData.pressCount);
// リセットボタンの場合にのみ音声応答を返します。
if (buttonData.buttonPressed === 'resetButton'){
return handlerInput
.responseBuilder
.speak("ボタンのカウント数をゼロにリセットしました。")
.getResponse();
}
}
};
APLコマンドの動作の詳細については、APLコマンドを参照してください。使用可能なコマンドのセットについては、標準コマンドを参照してください。
RenderDocumentディレクティブとUserEventリクエストの詳細については、Alexa.Presentation.APLインターフェースのリファレンスを参照してください。
関連トピック
最終更新日: 2025 年 12 月 17 日