Markup languages
前述のように、ミニアプリは単純な HTML ではなく、HTML のディレクトリで記述します。Vue.js のテキスト インターポレーションとディレクティブを扱ったことがある場合は、すぐに使いこなせるでしょう。しかし、同様のコンセプトは、それよりずっと前に XML 変換(XSLT)に存在していました。以下では、WeChat の WXML のコードサンプルを示しますが、Alipay の AXML、Baidu の Swan Element、ByteDance の TTML(DevTools では Bxml と表記されているにもかかわらず)、Quick App の HTML など、すべてのミニアプリ プラットフォームでコンセプトは同じです。Vue.js と同様に、基盤となるミニアプリ プログラミングのコンセプトは モデルビュービューモデル(MVVM)です。
データ バインディング
データ バインディングは、Vue.js のテキスト補間に対応しています。
<!-- wxml -->
<view>{{message}}</view>
// page.js
Page({
data: {
message: "Hello World!",
},
});
リストのレンダリング
リスト レンダリングは Vue.js の v-for
ディレクティブと同様に機能します。
<!-- wxml -->
<view wx:for="{{array}}">{{item}}</view>
// page.js
Page({
data: {
array: [1, 2, 3, 4, 5],
},
});
条件付きレンダリング
条件付きレンダリングは、Vue.js の v-if
ディレクティブと同様に機能します。
<!-- wxml -->
<view wx:if="{{view == 'one'}}">One</view>
<view wx:elif="{{view == 'two'}}">Two</view>
<view wx:else="{{view == 'three'}}">Three</view>
// page.js
Page({
data: {
view: "three",
},
});
テンプレート
命令的に HTML テンプレートの content
をクローニングする必要はなく、テンプレート定義にリンクする is
属性によって WXML テンプレートを宣言的に使用できます。
<!-- wxml -->
<template name="person">
<view>
First Name: {{firstName}}, Last Name: {{lastName}}
</view>
</template>
<template is="person" data="{{...personA}}"></template>
<template is="person" data="{{...personB}}"></template>
<template is="person" data="{{...personC}}"></template>
// page.js
Page({
data: {
personA: { firstName: "Alice", lastName: "Foo" },
personB: { firstName: "Bob", lastName: "Bar" },
personC: { firstName: "Charly", lastName: "Baz" },
},
});
スタイル設定
スタイル設定は CSS の各言語で行われます。WeChat の場合は WXSS です。Alipay では ACSS、Baidu では単に CSS、ByteDance では TTSS と呼ばれます。共通点は、レスポンシブ ピクセルで CSS を拡張することです。通常の CSS を記述する場合、デベロッパーは、幅とピクセル比が異なるさまざまなモバイル デバイスの画面に合わせて、すべてのピクセル単位を変換する必要があります。TTSS は、基盤となるレイヤとして rpx
単位をサポートしています。つまり、ミニアプリがデベロッパーからジョブを引き継ぎ、指定された画面幅 750rpx
に基づいてデベロッパーに代わって単位を変換します。たとえば、画面幅が 393px
(デバイスのピクセル比が 2.75
)の Google Pixel 3a で、Chrome DevTools で検査すると、レスポンシブ 200rpx
は実際のデバイスで 104px
になります(393px / 750rpx * 200rpx ≈ 104px)。Android では、同じコンセプトが密度非依存ピクセルと呼ばれます。
/* app.wxss */
.container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 200rpx 0; /* ← responsive pixels */
box-sizing: border-box;
}
コンポーネント(後述)は Shadow DOM を使用しないため、ページで宣言されたスタイルはすべてのコンポーネントに適用されます。一般的なスタイルシート ファイルの構成は、グローバル スタイル用のルート スタイルシートと、ミニアプリの各ページに固有の個別のページごとのスタイルシートです。スタイルは、@import
CSS アットルールのように動作する @import
ルールを使用してインポートできます。HTML と同様に、スタイルはインラインで宣言することもできます(動的テキスト補間を含む)。before をご覧ください。
<view style="color:{{color}};" />
スクリプト
ミニアプリは、CommonJS や RequireJS を彷彿とさせるさまざまな構文を使用するモジュールのサポートを含む、JavaScript の「安全なサブセット」をサポートしています。JavaScript コードは eval()
経由で実行できず、new Function()
で関数を作成することもできません。スクリプト実行コンテキストは、デバイスでは V8 または JavaScriptCore、シミュレータでは V8 または NW.js です。ビルド ターゲットが古い WebView 実装を使用するオペレーティング システム(後述を参照)の場合、特定の DevTools でコードが自動的に ES5 にトランスパイルされるため、通常は ES6 以降の構文でのコーディングが可能です。スーパーアプリ プロバイダのドキュメントでは、スクリプト言語は JavaScript と混同せず、JavaScript とは異なることが明記されています。ただし、この説明は主にモジュールの仕組み、つまり標準の ES モジュールをまだサポートしていないことを示しています。
前述のように、ミニアプリ プログラミングのコンセプトは model-view-viewmodel(MVVM)です。ロジックレイヤとビューレイヤは異なるスレッドで実行されるため、ユーザー インターフェースは長時間実行オペレーションによってブロックされません。ウェブ用語では、ウェブワーカーで実行されるスクリプトと考えることができます。
WeChat のスクリプト言語は WXS、Alipay の SJS、ByteDance の SJS と呼ばれます。Baidu は、自社のサービスを参照する際に JS と表現しています。これらのスクリプトは、WeChat の <wxs>
など、特別な種類のタグを使用して含める必要があります。一方、クイックアプリでは、通常の <script>
タグと ES6 JS 構文が使用されます。
<wxs module="m1">
var msg = "hello world";
module.exports.message = msg;
</wxs>
<view>{{m1.message}}</view>
モジュールは、src
属性を介して読み込むことも、require()
を介してインポートすることもできます。
// /pages/tools.wxs
var foo = "'hello world' from tools.wxs";
var bar = function (d) {
return d;
};
module.exports = {
FOO: foo,
bar: bar,
};
module.exports.msg = "some msg";
<!-- page/index/index.wxml -->
<wxs src="./../tools.wxs" module="tools" />
<view>{{tools.msg}}</view>
<view>{{tools.bar(tools.FOO)}}</view>
// /pages/logic.wxs
var tools = require("./tools.wxs");
console.log(tools.FOO);
console.log(tools.bar("logic.wxs"));
console.log(tools.msg);
JavaScript ブリッジ API
ミニアプリをオペレーティング システムに接続する JavaScript ブリッジにより、OS 機能を使用できるようになります(強力な機能へのアクセスをご覧ください)。また、便利なメソッドもいくつか用意されています。概要については、WeChat、Alipay、Baidu、ByteDance、Quick App のさまざまな API をご覧ください。
すべてのプラットフォームが、ウェブサイト caniuse.com にインスパイアされた名前の canIUse()
メソッドを提供しているため、機能の検出は簡単です。たとえば、ByteDance の tt.canIUse()
を使用すると、API、メソッド、パラメータ、オプション、コンポーネント、属性のサポート チェックを行うことができます。
// Testing if the `<swiper>` component is supported.
tt.canIUse("swiper");
// Testing if a particular field is supported.
tt.canIUse("request.success.data");
更新
ミニアプリには標準化された更新メカニズムがありません(標準化の可能性に関するディスカッション)。すべてのミニアプリ プラットフォームにはバックエンド システムがあり、ミニアプリ デベロッパーはミニアプリの新しいバージョンをアップロードできます。スーパーアプリは、そのバックエンド システムを使用してアップデートを確認してダウンロードします。一部のスーパーアプリでは、更新フローにミニアプリ自体が影響を与えることなく、更新がすべてバックグラウンドで実行されます。他のスーパーアプリでは、ミニアプリ自体をより細かく制御できます。
高度なプロセスの例として、以下の段落で WeChat のミニアプリ用アップデート メカニズムについて詳しく説明します。WeChat は、次の 2 つのシナリオで利用可能なアップデートを確認します。
- WeChat は、WeChat が実行されている限り、最近使用したミニアプリのアップデートを定期的にチェックします。アップデートが見つかると、アップデートがダウンロードされ、ユーザーがミニアプリを次にコールド スタートしたときに同期的に適用されます。ミニアプリのコールド スタートは、ミニアプリが開いたときに実行されていない場合に行われます(バックグラウンドでミニアプリを 5 分間開いた後、WeChat は強制的に終了します)。
- WeChat は、ミニアプリのコールド スタート時にも更新を確認します。ユーザーが長時間開いたミニアプリの場合は、アップデートがチェックされ、同期的にダウンロードされます。アップデートのダウンロード中は、ユーザーは待機する必要があります。ダウンロードが完了すると、アップデートが適用されてミニアプリが開きます。ネットワーク接続が不安定ななどの理由でダウンロードに失敗した場合でも、ミニアプリは開きます。ユーザーが最近開いたミニアプリの場合、更新はバックグラウンドで非同期にダウンロードされ、ユーザーが次回ミニアプリをコールド スタートしたときに適用されます。
ミニアプリでは、UpdateManager
API を使用して、以前のアップデートをオプトインできます。次の機能を提供します。
- 更新の確認が完了すると、ミニアプリに通知します。
(
onCheckForUpdate
) - アップデートがダウンロードされて利用可能になると、ミニアプリに通知します。(
onUpdateReady
) - アップデートをダウンロードできなかった場合、ミニアプリに通知します。
(
onUpdateFailed
) - 利用可能なアップデートをミニアプリが強制的にインストールできるようにします。これにより、アプリが再起動します。
applyUpdate
WeChat は、バックエンド システムでミニアプリ デベロッパー向けに、追加のアップデート カスタマイズ オプションを提供しています。 1. 1 つの方法では、デベロッパーは、特定の最小バージョンのミニアプリがすでにインストールされているユーザーに対して同期アップデートをオプトアウトし、代わりにアップデートを非同期に強制できます。2. デベロッパーは、ミニアプリの最小バージョンを設定することもできます。これにより、最小バージョンより低いバージョンからの非同期アップデートでは、アップデートの適用後にミニアプリが強制的に再読み込みされます。また、アップデートのダウンロードに失敗した場合、古いバージョンのミニアプリを開くこともブロックされます。
謝辞
この記事は、Joe Medley、Kayce Basques、Milica Mihajlija、Alan Kent、Keith Gu が確認しました。