PDFユーザーインターフェイスOutSystemsコンポーネントを見つけて利用するコンテンツ取得時の空の状態を設計する画面コンテンツの描画の優先順位を指定するImageウィジェットの幅と高さを設定するパフォーマンスパフォーマンスに関する警告を修正する軽量なローカルストレージを設計するスプラッシュ画面をシンプルかつ高速に保つ画面のサーバーデータ取得を最適化するリストの読み込みを最適化する画像のファイルサイズを最適化するJavaScript業界のJavaScriptに関するベストプラクティスに従う外部JavaScriptライブラリの使用を避けるJavaScriptコードをクライアントアクションでリファクタリングするDOMの操作を避けるグローバルオブジェクトの使用を避けるOutSystemsのローコードを使用してウィジェットのスタイルを変更するアニメーションにJavaScriptではなくCSSを使用するトラブルシューティングネイティブプラグインのフォールバックを定義するシンプルなクライアント側のロギングシステムを作成するモバイルアプリはまったく新しい考え方を開発モデルにもたらします。ユーザーは、モバイルアプリのエクスペリエンスに対して大きな期待を持っています。一方で、デバイスの制約とネットワークの制約がそのエクスペリエンスに大きく影響を及ぼすことがあります。ユーザーはそういった状況や制約にかかわらず、モバイルアプリに魔法のような機能を期待しています。ユーザーに最高のモバイルエクスペリエンスを提供するモバイルアプリを開発するために、常に念頭に置くべき重要なルールがいくつかあります。モバイルユースケースを対象にして開発を進める優れたモバイルエクスペリエンスを実現するために最適なユースケースを選択します。簡単なことから始め、繰り返します。最適化した少数のコンテンツを使用します。重要なものを先に表示します。UIフレームワークで提供されているものなど、一般的なモバイルパターンを使用します。負荷が大きいロジックはサーバー側で実行するクライアント側の情報はできるだけシンプルに保ちます。複雑なデータ処理や計算は、できるだけ少ないサーバーリクエストを使用してサーバー側で実行します。クライアント側では実行結果をキャッシュします。JavaScriptよりもOutSystemsのローコードを選択する実行時に最適なパフォーマンスを提供するため、OutSystemsは自動的にコードを最適化します。JavaScriptは、OutSystemsのローコード言語ではできない操作や高度な拡張シナリオでのみ使用してください。実際のシナリオでアプリをテストするモバイルアプリが使用される状況を把握し、本番環境へのデプロイ前に十分にテストします。デバイスの制約、ネットワークの制約、オフライン時間が優れたユーザーエクスペリエンスの妨げにならないことを確認します。この記事では、これらの基本ルールに重点を置きながら、OutSystemsのモバイルアプリのユーザーエクスペリエンスとパフォーマンスに影響を及ぼす一般的なリスクの回避に役立つベストプラクティスについて説明します。Developer」をまだ受けていない場合は、まずこのトレーニングで高品質なモバイルアプリの開発方法について学習してください。この記事は今後も更新し、新しい内容を追加する予定です。ユーザーインターフェイス優れたUIエクスペリエンスにより、ユーザーはモバイルアプリが高速で操作しやすいように感じます。このセクションでは、OutSystemsのモバイルアプリのUIエクスペリエンスを向上させるためのベストプラクティスを示します。Forgeコンポーネントを使用します。改良された最新版のメリットを得るため、必ず最新のものを使用します。コンテンツ取得時の空の状態を設計するユーザーが画面を遷移すると、通常は静的コンテンツが最初に描画されます。動的コンテンツは非同期的に取得されるため時間がかかります。このため、動的データの描画中はコンテンツが不完全な状態で画面が表示され、UIエクスペリエンスが低下します。動的コンテンツの取得中に表示される空の状態の画像を設計することで、ユーザーエクスペリエンスを向上させます。FacebookやLinkedInがよい例です。この方法は、ブロック、カード、リストアイテムといった画面のあらゆる動的コンテンツで有効です。空の状態から取得したコンテンツに切り替わるときに、ちらつきを感じる場合があります。このちらつきを防ぐには、ぼやけた灰色の線やスピナーなどの画像を1つ選択し、スムーズに画面が遷移できるようにします。画面コンテンツの描画の優先順位を指定するOutSystemsのデフォルトでは、モバイルアプリの画面データの取得に特定の優先順位はありません。関連性が高く、最初に描画すべきコンテンツが画面に含まれているにもかかわらず描画の優先順位を指定していない場合、ユーザーエクスペリエンスが低下することになります。コンテンツの描画を遅らせ、主要なコンテンツが先に描画されるようにします。そのためには、以下の手順を実行します。二次的なコンテンツをIfウィジェットのTrueブランチ内のブロックに配置します。このブロックに二次的なコンテンツを取得するためのロジックをすべて含め、ブロックが描画されたときにのみ二次的なコンテンツのデータ取得が実行されるようにします。IfウィジェットのFalseブランチに空の状態を配置し、二次的なコンテンツの取得時にコンテンツが移動するのを防ぎます。If条件をデフォルトでFalseとなる変数に設定します。Renderイベントに追加し、二次的なコンテンツの描画が開始するようにします。Imageウィジェットの幅と高さを設定するImageウィジェットの幅と高さを設定していない場合、最後の画像のダウンロード中にユーザーがちらつきを感じることがあります。画像の高さが設定されていないと、ウィジェットの高さが0pxから最後の画像の高さに変化するため、画像の読み込みが完了するまでの間に画面全体の高さが変化する場合があります。推奨事項Imageウィジェットの幅と高さを予測される最後の画像のサイズに設定します。パフォーマンス特にモバイルシナリオにおけるデータの処理やロジックの実装は、モバイルアプリのパフォーマンスに大きく影響を及ぼすことがあります。パフォーマンスに優れたモバイルアプリを開発するには、このセクションのベストプラクティスに従ってください。他のセクションのベストプラクティスもご覧ください。パフォーマンスに直接関係はしないものの、パフォーマンスの向上につながる場合があります。パフォーマンスに関する警告を修正するOutSystemsでは、Development環境でのモバイルアプリの開発中に、潜在的なパフォーマンス上の問題が自動的に検出されます。した問題に注意を払わないと、アプリケーションのパフォーマンス低下につながるおそれがあります。推奨事項[TrueChangeTM]タブに表示されるパフォーマンスに関する警告を確認して修正します。軽量なローカルストレージを設計するオフラインシナリオやキャッシュシナリオなどでデバイスのローカルストレージに大量のデータをため込むと、ローエンドデバイスのパフォーマンス低下の原因になる場合があります。以下の手法を使用して軽量なローカルストレージを設計します。対応するサーバーエンティティのすべてのアトリビュートを使用するのではなく、必要なアトリビュートのみを使用して、ローカルストレージのデータモデルを設計します。複数の結合を含むなどのクエリの複雑化を避けるため、ローカルデータモデルの非正規化を検討します。ユースケースに最適なデータ同期パターンを特定し、必要なときに実行されるように設計します。ローカルストレージにすべてのレコードを保存するのではなく、ユースケースに必要なエンティティレコードのみを保存します。すべてのタスクを取得するのではなく、特定の期間内に開かれたタスクのみを取得します。データを小さなグループに分け、最も関連性の高いデータから順番に同期することを検討します(たとえば、テキスト情報のみを先に同期し、写真やその他の画像は後で同期することができます)。スプラッシュ画面をシンプルかつ高速に保つモバイルアプリを起動すると、内部オペレーションが実行される間、スプラッシュ画面が表示されます。スプラッシュ画面に負荷の高いオペレーションや時間がかかるオペレーションを追加すると、アプリを使用するまでのユーザーの待機時間が長くなります。スプラッシュ画面内に複雑なUIがある場合、スプラッシュ画面が描画されるまで空白の画面が表示されることがあります。推奨事項シンプルで読み込みが速いスプラッシュ画面を保つには、以下のようなものを避ける必要があります。サーバーへのリクエスト重いロジック複雑なUI(ブロックが多すぎるUI)たとえば、以下のようなアプローチを検討します。Readyなどのイベントハンドラ内で行います。アプリの初期化段階でサーバーデータを取得する必要がある場合は、サーバー呼び出し数を最小限にします(たとえば、読み込み段階用に設計された単一のサーバーアクションを使用してデータを取得するなどします)。モバイルアプリの起動時に時間のかかるオペレーションを実行しないようにします。アプリの最初の画面で使用されるデータを同期する必要がある場合、データの転送を最小限に保ち、二次的なデータの転送は後回しにします。優れたユーザーエクスペリエンスを提供するため、ネイティブのスプラッシュ画面をカスタマイズすることも推奨しています。Fetchを使用して他のAggregateを連続して実行すると、複数のサーバーリクエストが生成され、アプリケーションが遅くなります。適切な順序でAggregateを含むデータアクションを作成します。このアクションはサーバーで単一のリクエストで実行され、すべてのデータを返します。リストの読み込みを最適化するリストでは複数のレコードの取得と描画が同時に実行されます。慎重に使用しないと、特にローエンドデバイスの場合やネットワーク接続が良好ではない場合に、エクスペリエンスが悪化する可能性があります。推奨事項リストを最大限に活用して優れたエクスペリエンスを実現するには、以下のルールに従います。データをオンデマンドで取得するすべてのレコードを一度に取得するのではなく、必要に応じて取得します。最初は最小限のレコード(たとえば、10レコード)を取得します。Endingイベントを使用して次のレコード(たとえば、続きの10レコード)を取得します。この動作を理解するには、画面のリストをスキャフォールディングします。このメカニズムはデフォルトで用意されています。Mapsなどのマップを読み込むJavaScriptのような複雑なロジックやウィジェットを使用するリストアイテムを設計しないようにします。リストに描画されるアイテムの数に応じて複雑さが増大します。All...]リンクがある説明のように展開可能なコンテンツを含むリストアイテムを設計しないようにします。これにより、リストの描画中の動作が影響を受けます。UIパターンを代わりに使用します。Endingイベントをトリガーするスクロールしきい値を調整します。これにより、表示に関する問題やリストのスクロール速度の低下を避けることができ、リスト使用時のユーザーエクスペリエンスが向上します。使用する値は、レコードのサイズに依存します。最初の取得アイテム数は、データ取得速度と追加レコードのリクエストが行われるまでの実用的なスクロール量のバランスがとれるようにします。スクロールによってトリガーされる取得アイテムの増加数は、通常は最初の取得アイテム数に近い数にしますが、アプリの使用状況に基づいて調整する必要がある場合があります。ユーザーが頻繁にリストを使用してエントリを検索する場合、アプリがデータの取得を高速化し、多くのアイテムを一度に読み込むことができるようにする必要があります。新しいアイテムの取得をトリガーするスクロールしきい値は、スクロールがリストの最後に達するまでの距離(ピクセル単位)であり、2,000ピクセルに設定する必要があります。アプリケーションの使いやすさを改善するためにこのしきい値を調整する必要がある場合は、リストウィジェットにinfinite-scroll-thresholdアトリビュートを追加してInteger値(ピクセル単位)を設定します。以下の図は様々な状況で使用する値の例を示しています。これらを最初のガイドラインとして使用し、テストした後、個別のケースに応じて調整します。オンデマンドでのデータ取得中に視覚的なフィードバックを提供する表示すべきリストアイテムがほかにもあり、実際に何らかの処理が行われていることを、明確にユーザーに示す必要があります。アニメーション付き画像を使用すると、このメッセージがユーザーに十分に伝わります。パフォーマンスの目標として、一般的なアプリケーションの使用状況において、ユーザーがリストの最後で読み込みができなくなることがないようにする必要があるということに留意します。画像のファイルサイズを最適化する特に旧型のデバイスの使用時や低速な接続環境のシナリオでは、モバイルアプリで大きなイメージファイルを使用すると、ダウンロード時間の延長やダウンロード妨害につながり、パフォーマンスの低下を引き起こす可能性があります。これらはストレージ領域を消費し、高解像度モデルのモバイルデバイスの画面に対しても大きすぎる可能性があります。目標とするユーザーエクスペリエンスを考慮して、(バイトでの)イメージサイズを削減し、面積(高さ/幅)を調節します。Googleの画像の最適化に関する推奨事項に従います。画像の取得を後の段階に遅らせることも検討してください。ベストプラクティス「画面コンテンツの描画の優先順位を指定する」をご覧ください。JavaScriptOutSystemsは、高速かつ最適化されたJavaScriptコードによるモバイルアプリを生成します。独自のJavaScriptコードを追加するかどうかは慎重に検討する必要があります。これを適切に行うことができるようにするには、以下のガイドラインに従います。Forgeでは、モバイルアプリの実装でよく使用されるコンポーネントが提供されています。シナリオに必要なコンポーネントをほとんど見つけることができ、必要に応じてカスタマイズできます。JavaScriptは本当に必要なときに使用し、ベストプラクティスに従うOutSystemsのローコードはよりパフォーマンスに優れています。独自のJavaScriptを使用する場合はこのセクションのベストプラクティスを読み、これらに従うことが重要でありことに留意します。APIを使用する内部APIはサポートされず、アップグレード時に変更されてJavaScriptコードが使用できなくなる可能性があります。業界のJavaScriptに関するベストプラクティスに従うJavaScriptを作成する場合は、必ず実装しているコードの内容とアプリへの影響を把握するようにします。推奨事項W3SchoolsやこれらのJavaScriptのコーディング標準およびベストプラクティスの説明にあるような、JavaScript開発に関するベストプラクティスに従います。パフォーマンスに優れたJavaScriptセレクタを使用してDOMから要素を取得したり、要素の幾何学的情報の再計算(レイアウトまたはリフロー)をブラウザでトリガーするプロパティおよびメソッドを避けたりします。外部JavaScriptライブラリの使用を避ける外部JavaScriptライブラリは、モバイルデバイス上で起動するには複雑すぎる可能性があります。ForgeでOutSystemsコンポーネントを探して、これらを外部JavaScriptライブラリの代わりに使用します。明らかにJavaScriptライブラリを使用する必要に迫られている場合、JavaScriptノード内ではなく、Script要素内で使用します。Script要素内でJavaScriptコードを使用すると、以下のことが可能になります。JavaScriptライブラリをアプリによりクリーンな状態で実装できます。JavaScriptライブラリごとに単一のソースを持つようになり、同じJavaScriptコードを複数回解析することを回避できます。JavaScriptコードをクライアントアクションでリファクタリングする同じJavaScriptコードを複数のJavaScriptノードで繰り返すと、メンテナンスの手間が増え、アプリのエラーが発生しやすくなります。推奨事項JavaScriptノード内で繰り返されるJavaScriptコードは、クライアントアクション内でカプセル化します。そのJavaScriptを実行する必要があるたびに、このクライアントアクションを呼び出します。することでJavaScriptコードが1箇所になり、アプリのメンテナンスの手間が少なくなります。console.log()、console.error()、alert()などのトラブルシューティングに関するJavaScript関数をクライアントアクションでカプセル化します。DOMの操作を避けるOutSystemsのモバイルアプリはReactを使用しており、JavaScriptでDOMを操作すると予期しない動作や望ましくない動作が発生する場合があります。推奨事項DOMを操作するJavaScriptは使用しないようにします。これは高度なユースケースの場合のみです。Forgeで検索してください。グローバルオブジェクトの使用を避けるOutSystemsでは、モバイルアプリのランタイム実行を最適化するためにシングルページアプリケーションを使用しています。このため、ナビゲーションの間にウィンドウオブジェクトがクリアされず、グローバルオブジェクトが破棄されないため、長時間実行するとメモリ使用量が増大します。推奨事項グローバル変数、キャッシュオブジェクト、リスナーなど、ウィンドウオブジェクトにアタッチされたオブジェクトの使用を避けます。代わりに以下の手順を実行します。localStorageおよびsessionStorageオブジェクトなどのブラウザ機能を使用します。JavaScript変数の宣言時に「var」キーワードを使用してスコープを限定します。OutSystemsのローコードを使用してウィジェットのスタイルを変更するJavaScriptを使用してCSSクラスを追加/削除し、ウィジェットのスタイルを変更すると、コードの見やすさと整合性の低下や、描画中のちらつきの発生などの問題の原因になる場合があります。Classesプロパティを使用して、ウィジェットに適用されるCSSクラスを変更します。このプロパティで実行時に評価される式を使用し、スタイルを動的に変更できます。アニメーションにJavaScriptではなくCSSを使用する通常、JavaScriptアニメーションはデバイスのCPU(中央処理装置)上で実行され、モバイルアプリのパフォーマンスに直接影響を及ぼします。推奨事項OutSystemsのローコードとスタイルクラスを使用して、デバイスのGPU(グラフィックスプロセッシングユニット)上でアニメーションを実行し、CPUに負荷がかからないようにします。CSS3(WebソケットとCSS3を使用してマジックを作成する)」では、カードのアニメーションにCSSを使用しています。FPSアニメーションをフリップする、うまくフリップする」をご覧ください。本当にJavaScriptを使用する必要がある場合はwindow.requestAnimationFrame()メソッドを使用し、GPUでアニメーションを実行します。トラブルシューティングモバイルアプリのバグを把握することは難しいタスクとなる場合もありますが、トラブルシューティングプロセスを円滑に進めるためのテクニックがいくつかあります。以下に示す開発のガイドラインに従うと、モバイルアプリにおける問題の再現と修正がさらにしやすくなります。ネイティブプラグインのフォールバックを定義するデスクトップブラウザでアプリのトラブルシューティングを行っているときは、ネイティブプラグインを使用できません。このため、実際のモバイルデバイスで検出された問題のトラブルシューティングができない場合があります。推奨事項プラグインがなくなった時期や機能しなくなった時期を把握するために、適切なフォールバックをアプリに含めます。これにより、確実にデスクトップブラウザでアプリをテストできるようになります。これを行うには、特定のプラグインが利用できない場合にエラー(または、その代わりのテスト用のモックデータ)を返すクライアントアクションに、プラグインの呼び出しをラップします。以下の例では、ContactsネイティブプラグインのAddToContactsアクションが、プラグインが利用可能かどうかを最初に検証するAddToContacts_Safeという名前のクライアントアクションにラップされています。これらのフォールバックの配置することで、特定のプラグインをサポートしないデバイスで実行されているアプリの問題の回避にも役立ちます。シンプルなクライアント側のロギングシステムを作成するクライアント側の問題はトラブルシューティングが難しい場合があり、特に、本番の1人のユーザーのデバイスで問題が発生していると思われる場合は困難です。問題を再現できないと、問題の特定と修正が非常に難しくなります。推奨事項OutSystemsには、モバイルアプリの情報をログに記録する方法があります。クライアント側のロギングシステムを作成し、ローカルストレージにログエントリを保存することもできます。これにより、ユーザーはエラー発生時にこれらのログをアップロードできます。これを利用して、特定のユーザーのデバイスで発生した問題の原因を分析できます。