Markup languages
Como se mencionó anteriormente, en lugar de usar HTML simple, las mini apps se escriben con dialectos de HTML. Si alguna vez trabajaste con directivas y con la interpolación de texto de Vue.js, te sentirás como en casa de inmediato, pero conceptos similares existían mucho antes en las transformaciones de 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 mini apps, es decir, AXML de Alipay, Swan Element de Baidu, TTML de ByteDance (a pesar de que las Herramientas para desarrolladores lo llamen Bxml) y HTML de Quick App. Al igual que con Vue.js, el concepto de programación de la mini app subyacente es el 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 de 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
El diseño se realiza con dialectos de CSS. El de WeChat se llama WXSS.
En el caso de Alipay, se llama ACSS, en el de Baidu, simplemente CSS y, en el de ByteDance, se conoce como TTSS.
Lo que tienen en común es que extienden CSS con píxeles responsivos. Cuando escriben CSS normal, los desarrolladores deben convertir todas las unidades de píxeles para adaptarse a las 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 mini app se encarga 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 convierten en 104px en el dispositivo real cuando se inspeccionan con las Herramientas para desarrolladores de Chrome (393 px / 750 rpx * 200 rpx ≈ 104 px). En Android, el mismo concepto se denomina píxel independiente de la densidad.
/* 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 los 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 para cada página de la mini app. Los estilos se pueden importar con una regla @import que se comporta como la 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 before).
<view style="color:{{color}};" />
Escritura de secuencias de comandos
Las mini apps admiten un "subconjunto seguro" de JavaScript que incluye compatibilidad con módulos que usan varias sintaxis que recuerdan a CommonJS o RequireJS.
No se puede ejecutar código JavaScript 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 programar con la sintaxis de ES6 o posterior, ya que las Herramientas para desarrolladores en particular transpilan automáticamente el código a ES5 si el destino de compilación es un sistema operativo con una implementación de WebView anterior (consulta más adelante). En la documentación de los proveedores de súper apps, se menciona explícitamente que sus lenguajes de programación no deben confundirse con JavaScript y son distintos de este. Sin embargo, esta afirmación se refiere principalmente a la forma en que funcionan los módulos, es decir, que aún no admiten los módulos de ES estándar.
Como se mencionó antes, el concepto de programación de la mini app es modelo-vista-ViewModel (MVVM). La capa de lógica y la capa de vista se ejecutan en diferentes subprocesos, lo que significa que la interfaz de usuario no se bloquea por operaciones de larga duración. En términos web, puedes pensar en las secuencias de comandos que se ejecutan en un Web Worker.
El lenguaje de secuencias de comandos de WeChat se llama WXS, el de Alipay SJS y el de ByteDance también SJS.
Baidu habla de JS cuando hace referencia a la suya. Estas secuencias de comandos deben incluirse con un tipo especial de etiqueta, por ejemplo, <wxs> en WeChat. En cambio, 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 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 puente de JavaScript
El puente de JavaScript que conecta las mini apps con el sistema operativo permite usar las capacidades del SO (consulta Acceso a funciones potentes). También ofrece varios métodos convenientes. 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 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 mini apps no tienen un mecanismo de actualización estandarizado (hay una discusión en torno a la posible estandarización). Todas las plataformas de mini apps tienen un sistema de backend que permite a los desarrolladores subir nuevas versiones de sus mini apps. Luego, la superapp usa ese sistema de backend para buscar y descargar actualizaciones. Algunas súper apps realizan actualizaciones completamente en segundo plano, sin que la mini app pueda influir en el flujo de actualización. Otras súper 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 las mini apps. WeChat busca actualizaciones disponibles en las siguientes dos situaciones:
- WeChat verificará periódicamente si hay actualizaciones de las mini apps que se usaron recientemente mientras WeChat esté en ejecución. Si se encuentra una actualización, se descarga y se aplica de forma síncrona la próxima vez que el usuario inicie en frío la mini app. El inicio en frío de una mini app se produce cuando la mini app no se estaba ejecutando cuando el usuario la abrió (WeChat cierra de forma forzosa las mini apps después de estar en segundo plano durante 5 minutos).
- WeChat también busca actualizaciones cuando se inicia en frío una mini app. En el caso de las mini apps que el usuario no abrió durante mucho tiempo, la actualización se verifica y descarga de forma síncrona. Mientras se descarga la actualización, el usuario debe esperar. Cuando finalice la descarga, se aplicará la actualización y se abrirá la mini app. Si falla la descarga, p.ej., debido a una mala conectividad de red, la mini app se abrirá de todos modos. En el caso de las mini apps 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 mini app en frío.
Las mini apps pueden habilitar las actualizaciones anticipadas con la API de UpdateManager. Proporciona las siguientes funciones:
- Notifica a la mini app cuando se realiza una verificación de actualizaciones.
(
onCheckForUpdate) - Notifica a la mini app cuando se descargó una actualización y está disponible.
(
onUpdateReady) - Notifica a la mini app cuando no se pudo descargar una actualización.
(
onUpdateFailed) - Permite que la mini app fuerce la instalación de una actualización disponible, lo que reiniciará la app.
(
applyUpdate)
WeChat también proporciona opciones de personalización de actualizaciones adicionales 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 mini app y, en su lugar, fuerzan las actualizaciones para que sean asíncronas. 2. Otra opción permite a los desarrolladores establecer una versión mínima requerida de su mini app. Esto hará que las actualizaciones asíncronas de una versión inferior a la versión mínima requerida fuercen la recarga de la mini app después de aplicar la actualización. También bloqueará la apertura de una versión anterior de la mini app si falla la descarga de la actualización.
Agradecimientos
Este artículo se revisó por Joe Medley, Kayce Basques, Milica Mihajlija, Alan Kent y Keith Gu.