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 trabajaste con la interpolación de texto y las directivas de Vue.js, te sentirás como en casa de inmediato, pero los conceptos similares existían 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 miniaplicaciones, como AXML de Alipay, Swan Element de Baidu, TTML de ByteDance (a pesar de que DevTools lo llama Bxml) y HTML de Quick App. Al igual que con Vue.js, el concepto de programación de apps pequeñas subyacente es modelo-vista-modelo de vista (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 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

La aplicación de diseño se realiza con dialectos de CSS. El de WeChat se llama WXSS. En el caso de Alipay, se llama ACSS, el de Baidu es simplemente CSS y, en el caso de ByteDance, su dialecto se conoce como TTSS. Lo que tienen en común es que extienden el CSS con píxeles responsivos. Cuando se escribe CSS normal, los desarrolladores deben convertir todas las unidades de píxeles para que se adapten a diferentes pantallas de dispositivos móviles con diferentes anchos y relaciones de píxeles. TTSS admite la unidad rpx como su capa subyacente, lo que significa que la app pequeña se hace cargo del trabajo del desarrollador y convierte las unidades en su nombre, según un ancho de pantalla especificado 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), los 200rpx responsivos se vuelven 104px en el dispositivo real cuando se inspecciona con las Herramientas para desarrolladores de Chrome (393 px / 750 rpx * 200 px ≈ 104 px). En Android, el mismo concepto se llama píxel independiente de la densidad.

Si inspeccionas una vista con Chrome DevTools cuyo padding de píxeles responsivo se especificó con &quot;200rpx&quot;, se muestra que en realidad es &quot;104px&quot; en un dispositivo Pixel 3a.
Inspección del 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 de archivos de hojas de estilo común es tener una hoja de estilo raíz para los estilos globales y, también, hojas de estilo individuales por página específicas para cada página de la miniapp. Los diseños se pueden importar con una regla @import que se comporte como la regla at-regla @import de CSS. Al igual que en HTML, los estilos también se pueden declarar intercalados, incluida la interpolación de texto dinámico (consulta antes).

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

Guion

Las apps pequeñas admiten un "subconjunto seguro" de JavaScript que incluye compatibilidad con módulos que usan sintaxis variadas 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 sintaxis ES6 o versiones posteriores, ya que DevTools transpila automáticamente el código a ES5 si el destino de compilación es un sistema operativo con una implementación anterior de WebView (consulta más adelante). En la documentación de los proveedores de super apps, se menciona de forma explícita que sus lenguajes de secuencias de comandos no deben confundirse con JavaScript y que son distintos de este. Sin embargo, esta declaración se refiere más que nada a la forma en que funcionan los módulos, es decir, que aún no son compatibles con los módulos ES estándar.

Como se mencionó antes, el concepto de miniprogramación de apps es el modelo-vista-vista-modelo (MVVM). La capa lógica y la capa de vista se ejecutan en subprocesos diferentes, lo que significa que la interfaz de usuario no se bloquea con operaciones de larga duración. En términos web, puedes pensar en secuencias de comandos que se ejecutan en un trabajador web.

El lenguaje de programación de WeChat se llama WXS, SJS de Alipay y SJS de ByteDance. Baidu habla de JS cuando hace referencia a su código. Estas secuencias de comandos deben incluirse con un tipo especial de etiqueta, por ejemplo, <wxs> en WeChat. En cambio, la app rápida usa etiquetas <script> normales y la sintaxis de 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 importarse 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 puente de JavaScript

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 funciones es sencilla, ya que todas las plataformas proporcionan un método canIUse() (literalmente llamado así) cuyo nombre parece estar inspirado en el sitio web caniuse.com. Por ejemplo, tt.canIUse() de ByteDance permite realizar verificaciones de compatibilidad para APIs, 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 apps pequeñas no tienen un mecanismo de actualización estandarizado (discusión sobre la posible estandarización). Todas las plataformas de miniapps tienen un sistema de backend que les permite a los desarrolladores de apps mini subir versiones nuevas de sus miniapps. Luego, una superapp usa ese sistema de backend para buscar y descargar actualizaciones. Algunas superapps realizan actualizaciones completamente en segundo plano, sin que la miniapp pueda influir en el flujo de actualización. Otras super apps les dan más control a las mini apps.

Como ejemplo de un proceso sofisticado, en los siguientes párrafos se describe con más detalle el mecanismo de actualización de WeChat para miniaplicaciones. WeChat busca actualizaciones disponibles en las siguientes dos situaciones:

  1. WeChat buscará actualizaciones de las miniapps usadas recientemente con regularidad, siempre y cuando WeChat esté en ejecución. Si se encuentra una actualización, esta se descarga y se aplica de forma síncrona la próxima vez que el usuario inicie la app en frío. El inicio en frío de una app ocurre cuando esta no se estaba ejecutando cuando el usuario la abrió (WeChat cierra de forma forzosa las apps en segundo plano después de 5 minutos).
  2. WeChat también busca actualizaciones cuando se inicia una app mini en frío. En el caso de las miniapps que el usuario no abrió durante mucho tiempo, se verifica la actualización y se descarga de forma síncrona. Mientras se descarga la actualización, el usuario debe esperar. Cuando se complete la descarga, se aplicará la actualización y se abrirá la app. Si la descarga falla, p. ej., debido a una mala conectividad de red, la app mini se abrirá de todos modos. En el caso de las miniapps que el usuario abrió recientemente, cualquier actualización potencial 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 apps pequeñas pueden habilitar actualizaciones anteriores con la API de UpdateManager. Proporciona la siguiente funcionalidad:

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

WeChat también proporciona opciones adicionales de personalización de actualizaciones para los desarrolladores de miniapps en su sistema de backend: 1. Una opción permite que los desarrolladores inhabiliten las actualizaciones síncronas para los usuarios que ya tienen instalada una versión mínima determinada de la app mini y, en su lugar, obliguen a que las actualizaciones sean asíncronas. 2. Otra opción permite a los desarrolladores establecer una versión mínima requerida de su miniapp. Esto hará que las actualizaciones asíncronas de una versión inferior a la versión mínima requerida vuelvan a cargar la miniapp de forma forzosa después de aplicar la actualización. También bloqueará la apertura de una versión anterior de la app mini si falla la descarga de la actualización.

Agradecimientos

Este artículo fue revisado por Joe Medley, Kayce Basques, Milica Mihajlija, Alan Kent y Keith Gu.