Marcação, estilo, script e atualização de mini apps

Conforme descrito anteriormente, ao invés de HTML simples, os miniaplicativos são escritos com dialetos de HTML. Se você já trabalhou com interpolação e diretivas de texto do Vue.js, vai se sentir em casa imediatamente, mas conceitos semelhantes já existiam antes disso nas transformações de XML (XSLT). Confira abaixo exemplos de código do WXML do WeChat, mas o conceito é o mesmo para todas as plataformas de miniapps, ou seja, o AXML do Alipay, o Swan Element do Baidu, o TTML da ByteDance (apesar de as Ferramentas do desenvolvedor chamarem de Bxml) e o HTML do Quick App. Assim como no Vue.js, o conceito de programação de miniapp subjacente é o model-view-viewmodel (MVVM).

Vinculação de dados

A vinculação de dados corresponde à interpolação de texto do Vue.js.

<!-- wxml -->
<view>{{message}}</view>
// page.js
Page({
  data: {
    message: "Hello World!",
  },
});

Renderização de lista

A renderização de listas funciona como a diretiva v-for do Vue.js.

<!-- wxml -->
<view wx:for="{{array}}">{{item}}</view>
// page.js
Page({
  data: {
    array: [1, 2, 3, 4, 5],
  },
});

Renderização condicional

A renderização condicional funciona como a diretiva v-if do Vue.js.

<!-- 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",
  },
});

Modelos

Em vez de exigir a clonagem imperativa do content de um modelo HTML, os modelos WXML podem ser usados de maneira declarativa por meio do atributo is, vinculado a uma definição de modelo.

<!-- 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" },
  },
});

Estilo

A estilização acontece com dialetos do CSS. O do WeChat é chamado de WXSS. Para o Alipay, o dialeto é chamado ACSS, o Baidu é simplesmente CSS, e para a ByteDance, o dialeto é chamado de TSTS. O que eles têm em comum é que eles estendem o CSS com pixels responsivos. Ao escrever CSS comum, os desenvolvedores precisam converter todas as unidades de pixel para se adaptar a diferentes telas de dispositivos móveis com larguras e proporções de pixels diferentes. O TTSS oferece suporte à unidade rpx como camada de base, o que significa que o miniapp assume o trabalho do desenvolvedor e converte as unidades em nome dele, com base em uma largura de tela especificada de 750rpx. Por exemplo, em um smartphone Pixel 3a com uma largura de tela de 393px (e uma proporção de pixel de dispositivo de 2.75), o 200rpx responsivo se torna 104px no dispositivo real quando inspecionado com o Chrome DevTools (393 px / 750rpx * 200rpx ☰ 104px). No Android, o mesmo conceito é chamado de pixel independente de densidade.

Inspecionar uma visualização com o Chrome DevTools, em que o padding de pixel responsivo foi especificado com &quot;200rpx&quot;, mostra que ele é &quot;104px&quot; em um dispositivo Pixel 3a.
Inspeção do padding real em um dispositivo Pixel 3a com o Chrome DevTools.
/* 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;
}

Como os componentes (consulte mais tarde) não usam o shadow DOM, os estilos declarados em uma página são aplicados em todos os componentes. A organização comum de arquivos de folha de estilo é ter uma folha de estilo raiz para estilos globais e folhas de estilo individuais por página específicas para cada página do miniapp. Os estilos podem ser importados com uma regra @import que se comporta como a @import CSS at-rule. Assim como no HTML, os estilos também podem ser declarados inline, incluindo a interpolação de texto dinâmica (consulte antes).

<view style="color:{{color}};" />

Roteiro

Os miniapps oferecem suporte a um "subconjunto seguro" de JavaScript que inclui suporte a módulos com sintaxes variadas que lembram CommonJS ou RequireJS. Não é possível executar o código JavaScript com eval(), e nenhuma função pode ser criada com new Function(). O contexto de execução de script é V8 ou JavaScriptCore nos dispositivos e V8 ou NW.js no simulador. Normalmente, é possível programar com a sintaxe ES6 ou mais recente, já que as DevTools específicas transpilam automaticamente o código para ES5 se o destino do build for um sistema operacional com uma implementação mais antiga da WebView (consulte mais tarde). A documentação dos provedores de superapps menciona explicitamente que as linguagens de script deles não devem ser confundidas com o JavaScript e são diferentes dele. No entanto, essa instrução se refere principalmente apenas à forma como os módulos funcionam, ou seja, eles ainda não são compatíveis com módulos ES padrão.

Como mencionado antes, o conceito de programação de mini app é o model-view-viewmodel (MVVM). A camada de lógica e a camada de visualização são executadas em linhas de execução diferentes, o que significa que a interface do usuário não é bloqueada por operações de longa duração. Em termos da Web, pense em scripts executados em um service worker.

A linguagem de script do WeChat é chamada de WXS, a do Alipay é SJS e a do ByteDance é SJS. O Baidu fala em JS ao se referir ao dele. Esses scripts precisam ser incluídos usando um tipo especial de tag, por exemplo, <wxs> no WeChat. Em contraste, o Quick App usa tags <script> regulares e a sintaxe JS ES6.

<wxs module="m1">
  var msg = "hello world";
  module.exports.message = msg;
</wxs>

<view>{{m1.message}}</view>

Os módulos também podem ser carregados por um atributo src ou importados por 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);

API JavaScript Bridge

A ponte JavaScript que conecta miniapps ao sistema operacional permite usar os recursos do SO (consulte Acesso a recursos avançados). Ele também oferece vários métodos de conveniência. Para ter uma visão geral, confira as diferentes APIs do WeChat, Alipay, Baidu, ByteDance e Quick App.

A detecção de recursos é direta, já que todas as plataformas oferecem um método canIUse() (chamado literalmente assim) com nome inspirado no site caniuse.com. Por exemplo, o tt.canIUse() da ByteDance permite verificações de suporte para APIs, métodos, parâmetros, opções, componentes e atributos.

// Testing if the `<swiper>` component is supported.
tt.canIUse("swiper");
// Testing if a particular field is supported.
tt.canIUse("request.success.data");

Atualizações

Os miniapps não têm um mecanismo de atualização padronizado (discussão sobre uma possível padronização). Todas as plataformas de miniaplicativos têm um sistema de back-end, que permite que os desenvolvedores façam upload de novas versões dos miniaplicativos. Um superapp usa esse sistema de back-end para verificar e fazer o download de atualizações. Alguns superapps realizam atualizações inteiramente em segundo plano, sem que o próprio miniapp influencie o fluxo de atualização. Outros superapps dão mais controle aos miniapps.

Como exemplo de um processo sofisticado, os parágrafos abaixo descrevem o mecanismo de atualização do WeChat para miniapps em mais detalhes. O WeChat verifica as atualizações disponíveis nos dois cenários a seguir:

  1. O WeChat vai verificar regularmente as atualizações dos miniapps usados recentemente, desde que esteja em execução. Se uma atualização for encontrada, ela será transferida por download e aplicada de forma síncrona na próxima vez que o usuário fizer a inicialização a frio do miniapp. A inicialização a frio de miniapps ocorre quando o miniapp não estava em execução quando o usuário o abriu. O WeChat fecha os miniapps à força depois de ficar em segundo plano por 5 minutos.
  2. O WeChat também verifica se há atualizações quando um miniapp é inicializado a frio. Para miniapps que o usuário não abriu há muito tempo, a atualização é verificada e transferida de forma síncrona. Enquanto a atualização é transferida, o usuário precisa esperar. Quando o download for concluído, a atualização será aplicada e o miniapp será aberto. Se o download falhar, por exemplo, devido a uma conectividade de rede ruim, o mini app será aberto mesmo assim. Para miniapps que o usuário abriu recentemente, qualquer atualização em potencial é feita por download de forma assíncrona em segundo plano e será aplicada na próxima vez que o usuário iniciar o miniapp.

Os miniapps podem ativar atualizações anteriores usando a API UpdateManager. Ele oferece as seguintes funcionalidades:

  • Notifica o miniapp quando uma verificação de atualizações é feita. (onCheckForUpdate)
  • Notifica o miniapp quando uma atualização é feita e está disponível. (onUpdateReady)
  • Notifica o miniapp quando não é possível fazer o download de uma atualização. (onUpdateFailed)
  • Permite que o miniapp instale uma atualização disponível, o que reinicia o app. (applyUpdate)

O WeChat também oferece outras opções de personalização de atualização para desenvolvedores de miniapps no sistema de back-end: 1. Uma opção permite que os desenvolvedores desativem as atualizações síncronas para usuários que já têm uma determinada versão mínima do mini app instalada e força as atualizações a serem assíncronas. 2. Outra opção permite que os desenvolvedores definam uma versão mínima necessária do mini app. Isso fará com que as atualizações assíncronas de uma versão anterior à mínima necessária forcem o recarregamento do mini app após a atualização. Ele também vai bloquear a abertura de uma versão mais antiga do miniapp se o download da atualização falhar.

Agradecimentos

Este artigo foi revisado por Joe Medley, Kayce Basques, Milica Mihajlija, Alan Kent e Keith Gu.