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. WeChat se llama WXSS.
En el caso de Alipay, el dialecto se llama ACSS, CSS de Baidu y, en el caso de ByteDance, su dialecto se denomina TTSS.
Lo que tienen en común es que extienden el CSS con píxeles responsivos. Cuando escriben código CSS normal, los desarrolladores deben convertir todas las unidades de píxeles para adaptarlas a las diferentes pantallas de dispositivos móviles con anchos y proporciones de píxeles diferentes. 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 relació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 ≈ 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 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 miniapp. Los estilos se pueden importar con una regla @import
que se comporta como la regla de at de CSS @import
. Al igual que en HTML, los diseños también se pueden declarar intercalados, incluida la interpolación de texto dinámica (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()
ni 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 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ó anteriormente, el concepto de programación de miniaplicaciones es el modelo-vista-modelo de vista (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 de JavaScript que conecta las miniapps con el sistema operativo permite usar las funciones 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 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 miniapps no tienen un mecanismo de actualización estandarizado (debate sobre una posible estandarización). Todas las plataformas de miniaplicaciones tienen un sistema de backend, que permite a los desarrolladores subir versiones nuevas de sus miniaplicaciones. Luego, una superapp usa ese sistema de backend para buscar y descargar actualizaciones. Algunas super apps realizan actualizaciones por completo en segundo plano, sin que la mini app 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 el mecanismo de actualización de WeChat para miniapps con más detalle. WeChat busca actualizaciones disponibles en las siguientes dos situaciones:
- 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).
- WeChat también busca actualizaciones cuando se inicia una miniapp en frío. En el caso de las miniapps que el usuario no abrió durante mucho tiempo, se busca 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 mini pueden habilitar actualizaciones anteriores a través de la API de UpdateManager
. Proporciona la siguiente funcionalidad:
- Notifica a la app mini cuando se realiza una verificación de actualizaciones.
(
onCheckForUpdate
) - Notifica a la miniapp cuando se descarga una actualización y está disponible.
(
onUpdateReady
) - Notifica a la app mini cuando no se pudo 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 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 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 anterior a la mínima requerida vuelvan a cargar la miniapp de manera 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.