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

Markup languages

Como descrito anteriormente, em vez de HTML simples, os miniapps são criados 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, como o AXML do Alipay, o Swan Element do Baidu, o TTML do ByteDance (apesar de o DevTools chamar 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 forma declarativa pelo atributo is que vincula 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. No Alipay, o nome é ACSS, no Baidu é simplesmente CSS, e no ByteDance, o dialeto é chamado de TTSS. O que eles têm em comum é que 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 TST oferece suporte à unidade rpx como camada subjacente, o que significa que o mini app assume o job 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 pixels do dispositivo de 2.75), o 200rpx responsivo se torna 104px no dispositivo real quando inspecionado com o Chrome DevTools (393 px / 750 rpx * 200 rpx ≈ 104 px). 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 dos arquivos da folha de estilo é ter uma folha de estilo raiz para estilos globais e folhas de estilo por página específicas, específicas para cada página do mini app. Os estilos podem ser importados com uma regra @import que se comporta como o CSS @import 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 e são diferentes do JavaScript. No entanto, essa declaração se refere principalmente à maneira como os módulos funcionam, ou seja, eles ainda não oferecem suporte a Módulos ES padrão.

Como mencionado antes, o conceito de programação de miniapps é o modelo-visualização-viewmodel (MVVM). A camada 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 de ponte JavaScript

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 é simples, já que todas as plataformas oferecem um método canIUse() (chamado assim) cujo nome parece inspirado no site caniuse.com. Por exemplo, o tt.canIUse() da ByteDance permite verificar o suporte a 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 miniapps têm um sistema de back-end, que permite que os desenvolvedores de mini apps façam upload de novas versões dos miniapps. 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 a seguir descrevem o mecanismo de atualização do WeChat para miniapps com mais detalhes. O WeChat verifica se há 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 mini app é inicializado a frio. Para mini apps que o usuário não abre por muito tempo, a atualização é verificada e transferida por download de maneira síncrona. Durante o download da atualização, 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 miniapp será aberto de qualquer maneira. 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 a seguinte funcionalidade:

  • 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 mini app quando não é possível fazer o download de uma atualização. (onUpdateFailed)
  • Permite que o miniapp force a instalação de uma atualização disponível, o que reiniciará 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 versão mínima do miniapp instalada e forçam as atualizações a serem assíncronas. 2. Outra opção permite que os desenvolvedores definam uma versão mínima necessária do miniapp. Isso fará com que as atualizações assíncronas de uma versão inferior à versão mínima necessária recarreguem o miniapp após a aplicação da 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.