Lenguaje de marcado, estilo, secuencia de comandos y actualización de miniapps

Markup languages

Como se describió antes, en lugar de con HTML simple, las miniapps se escriben con dialectos de HTML. Si alguna vez abordaste la interpolación y las directivas de texto de Vue.js, te sentirás como en casa de inmediato, pero existen conceptos similares mucho antes en las transformaciones XML (XSLT). A continuación, puedes ver muestras de código de WXML de WeChat, pero el concepto es el mismo para todas las plataformas de miniapps, es decir, AXML de Alipay, Swan Element de Baidu, TTML de ByteDance (a pesar de que Herramientas para desarrolladores lo llama Bxml) y HTML de Quick App. Al igual que con Vue.js, el concepto subyacente de programación de miniapps es model-view-viewmodel (MVVM).

Vinculación de datos

La vinculación de datos corresponde a la interpolación de texto de Vue.js.

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

Renderización de listas

La renderización de listas funciona como la directiva v-for de Vue.js.

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

Renderización condicional

La renderización condicional funciona como la directiva v-if de 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",
  },
});

plantillas

En lugar de requerir la clonación imperativa del content de una plantilla HTML, las plantillas WXML se pueden usar de forma declarativa a través del atributo is que se vincula a una definición de plantilla.

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

Diseño

El estilo se aplica con los dialectos de CSS. WeChat se llama WXSS. En el caso de Alipay, el suyo se llama ACSS, el CSS de Baidu, y, en el caso de ByteDance, su dialecto se denomina TTSS. Lo que tienen en común es que extienden las CSS con píxeles responsivos. Cuando escriben código CSS normal, los desarrolladores deben convertir todas las unidades de píxeles para adaptarlas a diferentes pantallas de dispositivos móviles con diferentes anchos y proporciones de píxeles. TTSS admite la unidad rpx como su capa subyacente, lo que significa que la miniapp toma el control del trabajo del desarrollador y convierte las unidades en su nombre, según un ancho de pantalla específico de 750rpx. Por ejemplo, en un teléfono Pixel 3a con un ancho de pantalla de 393px (y una proporción de píxeles del dispositivo de 2.75), el 200rpx responsivo se convierte en 104px en el dispositivo real cuando se inspecciona con las Herramientas para desarrolladores de Chrome (393 px / 750 rpx * 200 rpx targetSdkVersion 104 px). En Android, el mismo concepto se denomina píxel independiente de la densidad.

Inspeccionar una vista con las Herramientas para desarrolladores de Chrome cuyo relleno de píxeles responsivo se especificó con `200rpx` muestra que, en realidad, es de `104px` en un dispositivo Pixel 3a.
Cómo inspeccionar el padding real en un dispositivo Pixel 3a con las Herramientas para desarrolladores de Chrome
/* 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;
}

Dado que los componentes (consulta más adelante) no usan shadow DOM, los estilos declarados en una página llegan a todos los componentes. La organización común de archivos de hojas de estilo consiste en tener una hoja de estilo raíz para los estilos globales y hojas de estilo individuales por página específicas de cada página de la miniapp. Los estilos se pueden importar con una regla @import que se comporte como la regla a nivel de CSS @import. Al igual que en HTML, los estilos también se pueden declarar intercalados, incluida la interpolación dinámica del texto (consulta antes).

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

Guion

Las miniapps admiten un "subconjunto seguro" de JavaScript que incluye compatibilidad con módulos que usan distintas sintaxis que recuerdan a CommonJS o RequireJS. El código JavaScript no se puede ejecutar a través de eval() y no se pueden crear funciones con new Function(). El contexto de ejecución de secuencias de comandos es V8 o JavaScriptCore en los dispositivos, y V8 o NW.js en el simulador. Por lo general, es posible codificar con ES6 o sintaxis más reciente, ya que las Herramientas para desarrolladores específicas transpilan automáticamente el código a ES5 si el destino de compilación es un sistema operativo con una implementación de WebView más antigua (consulta más adelante). En la documentación de los proveedores de superapps, se menciona de forma explícita que sus lenguajes de programación no deben confundirse con JavaScript y que son distintos de ellos. Sin embargo, esta declaración se refiere principalmente a la forma en que funcionan los módulos, es decir, que aún no son compatibles con los módulos de ES estándar.

Como se mencionó antes, el concepto de programación de la miniapp es model-view-viewmodel (MVVM). Las capas lógicas y de vista se ejecutan en diferentes subprocesos, lo que significa que las operaciones de larga duración no bloquean la interfaz de usuario. En términos web, puedes pensar en las secuencias de comandos que se ejecutan en un Web Worker.

El lenguaje de programación de WeChat se llama WXS, SJS de Alipay y SJS de ByteDance. Baidu habla de JS cuando hace referencia al suyo. Estas secuencias de comandos deben incluirse con un tipo especial de etiqueta, por ejemplo, <wxs> en WeChat. Por el contrario, Quick App usa etiquetas <script> normales y la sintaxis JS de ES6.

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

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

Los módulos también se pueden cargar a través de un atributo src o se pueden importar a través de 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 JavaScript Bridge

El puente JavaScript que conecta las miniapps con el sistema operativo permite usar las capacidades del SO (consulta Acceso a funciones potentes). También ofrece varios métodos de conveniencia. Para obtener una descripción general, puedes consultar las diferentes APIs de WeChat, Alipay, Baidu, ByteDance y Quick App.

La detección de características es sencilla, ya que todas las plataformas proporcionan un método canIUse() (literalmente llamado así) cuyo nombre parece inspirado en el sitio web caniuse.com. Por ejemplo, tt.canIUse() de ByteDance permite verificaciones de compatibilidad para API, métodos, parámetros, opciones, componentes y atributos.

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

Actualizaciones

Las miniapps no tienen un mecanismo de actualización estandarizado (debate sobre una posible estandarización). Todas las plataformas de miniapps tienen un sistema de backend, lo que permite a los desarrolladores de miniapps subir nuevas versiones de sus miniapps. Luego, una superapp usa ese sistema de backend para buscar actualizaciones y descargarlas. Algunas superapps realizan actualizaciones por completo en segundo plano, sin que la miniapp pueda influir en el flujo de actualización de ninguna manera. Otras superapps le brindan más control a las miniapps en sí.

Para ejemplificar un proceso sofisticado, en los siguientes párrafos se describe con más detalle el mecanismo de actualización de WeChat para miniapps. WeChat verifica si hay actualizaciones disponibles en los siguientes dos casos:

  1. WeChat comprobará con regularidad si hay actualizaciones de las miniapps que se usaron recientemente, siempre que WeChat esté en funcionamiento. Si se encuentra una actualización, esta se descarga y se aplica de forma síncrona la próxima vez que el usuario inicie en frío la miniapp. El inicio en frío de una miniapp no se estaba ejecutando cuando el usuario la abrió (WeChat fuerza la cierre de las miniapps después de estar en segundo plano durante 5 minutos).
  2. WeChat también busca actualizaciones cuando se inicia en frío una miniapp. En el caso de las miniapps que el usuario no ha abierto durante mucho tiempo, se comprueba y se descarga la actualización de forma síncrona. Mientras se descarga la actualización, el usuario tiene que esperar. Una vez que finaliza la descarga, se aplica la actualización y se abre la miniapp. Si la descarga falla, p.ej., debido a una mala conectividad de red, la miniapp se abrirá de todos modos. En el caso de las miniapps que el usuario abrió recientemente, cualquier posible actualización se descarga de forma asíncrona en segundo plano y se aplicará la próxima vez que el usuario inicie la miniapp en frío.

Las miniapps pueden habilitar las actualizaciones anteriores con la API de UpdateManager. Proporciona las siguientes funciones:

  • Notifica a la miniapp cuando se realiza una búsqueda de actualizaciones. (onCheckForUpdate)
  • Notifica a la miniapp cuando se descarga y está disponible una actualización. (onUpdateReady)
  • Notifica a la miniapp cuando no se pudo descargar una actualización. (onUpdateFailed)
  • Permite que la miniapp instale de manera automática una actualización disponible, lo que reiniciará la app (applyUpdate).

WeChat también proporciona opciones adicionales de personalización de actualizaciones para desarrolladores de miniapps en su sistema de backend: 1. Una opción permite a los desarrolladores inhabilitar las actualizaciones síncronas para los usuarios que ya tienen instalada una versión mínima determinada de la miniapp y, en su lugar, fuerza las actualizaciones a ser asíncronas. 2. Otra opción permite a los desarrolladores establecer una versión mínima requerida de su miniapp. De esta manera, las actualizaciones asíncronas de una versión inferior a la versión mínima requerida forzarán una nueva carga de la miniapp después de aplicar la actualización. También bloqueará la apertura de una versión anterior de la miniapp si falla la descarga de la actualización.

Agradecimientos

Joe Medley, Kayce Vasques, Milica Mihajlija, Alan Kent y Keith Gu revisaron este artículo.