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

Markup languages

Conforme descrito anteriormente, em vez de HTML simples, os miniaplicativos são desenvolvidos com dialetos de HTML. Se você já lidou com a interpolação e as diretivas de texto do Vue.js, vai se sentir em casa imediatamente, mas conceitos semelhantes existiam antes disso em Transformações XML (XSLT). Abaixo, você pode conferir exemplos de código do WXML do WeChat, mas o conceito é o mesmo para todas as plataformas de miniapps, ou seja, AXML do Alipay, Elemento Swan do Baidu, TTML do ByteDance (apesar do DevTools chamá-lo de Bxml) e HTML do rápido App. Assim como no Vue.js, o conceito de programação de miniapps subjacente é o modelo-de-visualização-visualização (MVVM).

Vinculação de dados

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

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

Renderização de lista

A renderização de lista funciona como a diretiva v-for da 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 da 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 com o atributo is que direciona 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

O estilo acontece com dialetos do CSS. O WeChat é chamado de WXSS. No Alipay, o dialeto deles é chamado de ACSS, do Baidu, simplesmente CSS, e no ByteDance, o dialeto dele é chamado de TTSS. O que eles têm em comum é que estendem o CSS com pixels responsivos. Ao escrever um CSS normal, os desenvolvedores precisam converter todas as unidades de pixels para que se adaptem a diferentes telas de dispositivos móveis com diferentes larguras e proporções de pixels. O TTSS oferece suporte à unidade rpx como camada subjacente, o que significa que o miniapp 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), a 200rpx responsiva se torna 104px no dispositivo real quando inspecionada com o Chrome DevTools (393 px / 750 rpx * 200 px ≤ 104 px). No Android, o mesmo conceito é chamado de pixel independente de densidade.

A inspeção de uma visualização com o Chrome DevTools cujo preenchimento de pixel responsivo foi especificado com &quot;200 rpx&quot; mostra que, na verdade, ela se refere a &quot;104 px&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 (veja mais tarde) não usam o shadow DOM, os estilos declarados em uma página alcançam todos os componentes. A organização comum dos arquivos de folha de estilo é ter uma folha de estilo raiz para estilos globais e folhas de estilo por página individuais específicas para cada página do miniapp. Os estilos podem ser importados com uma regra @import que se comporta como uma regra de CSS @import. Assim como no HTML, os estilos também podem ser declarados inline, incluindo interpolação de texto dinâmico (consulte antes).

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

Criação dos roteiros

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

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

A linguagem de script do WeChat é chamada WXS, SJS do Alipay e ByteDance como SJS da ByteDance. O Baidu fala de JS ao fazer referência ao dele. Esses scripts precisam ser incluídos usando um tipo especial de tag, por exemplo, <wxs> no WeChat. Por outro lado, o Quick App usa tags <script> regulares e a sintaxe JS do 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 usando 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 possibilita usar os recursos do SO. Consulte Acesso a recursos avançados. Ele também oferece vários métodos de conveniência. Para 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 fornecem um método canIUse() (literalmente chamado assim) com um nome inspirado no site caniuse.com. Por exemplo, o tt.canIUse() do 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 possível padronização). Todas as plataformas de miniapps têm um sistema de back-end, que permite que os desenvolvedores façam upload de novas versões dos miniapps. Um superapp usa esse sistema de back-end para procurar e fazer o download de atualizações. Alguns superapps executam as 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 próprios miniapps.

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

  1. O WeChat verifica regularmente se há atualizações de miniapps usados recentemente, desde que o serviço esteja em execução. Se uma atualização for encontrada, ela será transferida por download e aplicada de maneira síncrona na próxima vez que o usuário inicializar o mini app. A inicialização a frio ocorre quando o miniapp não está em execução quando o usuário o abre (o WeChat força o fechamento dos miniapps depois de ficar em segundo plano por cinco 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 abre há muito tempo, a atualização é verificada e transferida por download de forma síncrona. Enquanto a atualização é baixada, o usuário tem que esperar. Quando o download terminar, 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 mesmo assim. No caso de miniapps abertos recentemente, o download de qualquer atualização em potencial é feito de forma assíncrona em segundo plano e será aplicado na próxima vez que o usuário iniciar o miniapp a frio.

Os miniapps podem ativar as 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 é transferida por download e está disponível. (onUpdateReady)
  • Notifica o miniapp quando não foi possível fazer o download de uma atualização. (onUpdateFailed)
  • Permite que o miniapp force a instalação de uma atualização disponível, que o reiniciará. (applyUpdate)

O WeChat também oferece outras opções de personalização de atualizações 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 miniapp instalada, forçando 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 atualizações assíncronas sejam feitas de uma versão anterior à mínima necessária para forçar a atualização do miniapp depois da atualização. Ela também 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.