Markup languages
前述のように、ミニアプリはプレーンな HTML ではなく、HTML の方言で記述されます。Vue.js のテキスト補間とディレクティブを扱ったことがある方は、すぐに慣れるでしょう。しかし、同様のコンセプトは、XML 変換(XSLT)でずっと以前から存在していました。以下は WeChat の WXML のコードサンプルですが、コンセプトはすべてのミニアプリ プラットフォーム(Alipay の AXML、Baidu の Swan Element、ByteDance の TTML(DevTools では Bxml と呼ばれます)、Quick App の HTML)で同じです。Vue.js と同様に、基盤となるミニアプリのプログラミング コンセプトは Model-View-ViewModel(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",
},
});
テンプレート
WXML テンプレートでは、命令型の HTML テンプレートの content のクローン作成を必要とするのではなく、テンプレート定義にリンクする is 属性を使用して宣言的に使用できます。
<!-- 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 の Google Pixel 3a(デバイスのピクセル比が 2.75)では、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;
}
コンポーネント(後述)はシャドー DOM を使用しないため、ページで宣言されたスタイルはすべてのコンポーネントに適用されます。一般的なスタイルシート ファイルの構成は、グローバル スタイル用のルート スタイルシートと、ミニアプリの各ページに固有のページごとのスタイルシートを個別に用意することです。スタイルは、@import CSS アットルールのように動作する @import ルールを使用してインポートできます。HTML と同様に、スタイルをインラインで宣言することもできます。これには、動的テキストの補間も含まれます(前述を参照)。
<view style="color:{{color}};" />
スクリプト
ミニアプリは、CommonJS や RequireJS を彷彿とさせるさまざまな構文を使用するモジュールのサポートを含む、JavaScript の「安全なサブセット」をサポートしています。JavaScript コードは eval() を介して実行できず、new Function() で関数を作成することもできません。スクリプト実行コンテキストは、デバイスでは V8 または JavaScriptCore、シミュレータでは V8 または NW.js です。ES6 以降の構文でコーディングすることは通常可能です。特定の DevTools は、ビルド ターゲットが古い WebView 実装のオペレーティング システムの場合、コードを自動的に ES5 にトランスパイルするためです(後述を参照)。スーパーアプリ プロバイダのドキュメントには、スクリプト言語は 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() メソッドを提供しており、その名前はウェブサイト caniuse.com に由来しているようです。たとえば、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 は最近使用したミニアプリのアップデートを定期的にチェックします。アップデートが見つかった場合、アップデートがダウンロードされ、ユーザーが次にミニアプリをコールド スタートしたときに同期的に適用されます。ミニアプリのコールド スタートは、ユーザーがミニアプリを開いたときにミニアプリが実行されていなかった場合に発生します(WeChat は、ミニアプリがバックグラウンドで 5 分間実行された後、強制的に閉じます)。
- WeChat は、ミニアプリがコールド スタートされたときにもアップデートを確認します。ユーザーが長期間開いていないミニアプリについては、更新が確認され、同期的にダウンロードされます。アップデートのダウンロード中は、お客様は待機する必要があります。ダウンロードが完了すると、アップデートが適用され、ミニアプリが開きます。ダウンロードが失敗した場合(ネットワーク接続が悪いなど)、ミニアプリは開きます。ユーザーが最近開いたミニアプリについては、潜在的な更新はバックグラウンドで非同期にダウンロードされ、ユーザーが次にミニアプリをコールド スタートしたときに適用されます。
ミニアプリは UpdateManager API を使用して、以前のアップデートをオプトインできます。次の機能を提供します。
- アップデートの確認が行われたときに、ミニアプリに通知します。(
onCheckForUpdate) - 更新プログラムがダウンロードされ、利用可能になったときに、ミニアプリに通知します。(
onUpdateReady) - アップデートをダウンロードできなかった場合に、ミニアプリに通知します。(
onUpdateFailed) - ミニアプリが利用可能なアップデートを強制的にインストールし、アプリを再起動できるようにします。
(
applyUpdate)
WeChat のバックエンド システムでは、ミニアプリ デベロッパー向けにアップデートのカスタマイズ オプションも提供しています。 1. 1 つ目のオプションでは、特定の最小バージョンのミニアプリがすでにインストールされているユーザーに対して、同期更新をオプトアウトし、代わりに非同期更新を強制できます。2. 別のオプションでは、デベロッパーがミニアプリの最小必須バージョンを設定できます。これにより、最小必須バージョンよりも低いバージョンからの非同期アップデートでは、アップデートの適用後にミニアプリが強制的に再読み込みされます。また、アップデートのダウンロードに失敗した場合は、古いバージョンのミニアプリを開くこともブロックされます。
謝辞
この記事は、Joe Medley、Kayce Basques、Milica Mihajlija、Alan Kent、Keith Gu によってレビューされました。