Un rewrite solo de nombre

Tienes una página web que funciona. Renderiza, hace fetch, guarda un token, escucha el scroll. Para publicarla dentro de un runtime de mini-programas no la tiras: la remapeas. La lógica sobrevive en gran parte; cambia la superficie sobre la que corre. La trampa es asumir que el navegador sigue debajo. No está: no hay document, no hay window, no hay localStorage global y no hay <div> que puedas pinchar. Este es el mapa que mantiene la migración predecible.

Ciclo de vida: los eventos se vuelven callbacks

En la web dependes de DOMContentLoaded, load y visibilitychange. Una página de mini-programa es un objeto Page() cuyo ciclo de vida es un conjunto de callbacks con nombre:

Page({
  onLoad(query) { /* una vez, al crear — lee params de ruta aquí */ },
  onShow() { /* cada vez que aparece, incl. volver de hijo */ },
  onReady() { /* primer render listo, seguro consultar layout */ },
  onHide() { /* a segundo plano o navegó fuera */ },
  onUnload() { /* destruida — limpia timers aquí */ },
})

La mayor diferencia de comportamiento: onShow se dispara al volver de una página hija, así que las listas que deben reflejar una mutación hecha aguas abajo se re-obtienen allí — no solo en onLoad. Los eventos a nivel app (onLaunch, onShow, onHide) viven en App(). No hay aviso beforeunload; si lo necesitas, intercepta la llamada de navegación.

Vista: HTML y CSS se vuelven WXML y WXSS

HTML se vuelve WXML — una plantilla con bindings {{ }} y sin DOM que recorrer. Nunca haces document.querySelector y mutas; llamas this.setData({ key: value }) y la capa de render hace el diff. Esta sola regla elimina toda una categoría de bugs de layout pero también mata cualquier código que asumiera poder alcanzar el árbol de nodos.

WXSS es CSS con dos cambios que muerden: una nueva unidad rpx donde 750rpx equivale al ancho de pantalla (diseño de 375px → 750rpx, auto-escalado por dispositivo), y un set de selectores reducido — sin selectores adyacentes ni de atributo, y muchas menos pseudo-clases (last-child desaparece). Mantén estilos planos y basados en clases.

Red: fetch se vuelve wx.request

Aquí es donde la mayoría de las migraciones se atoran. wx.request no es fetch:

AspectoWeb (fetch)Mini-programa (wx.request)
TransporteHTTP/HTTPS, cualquier hostSolo HTTPS/WSS, host debe estar en allowlist
DominioningunoAllowlist de dominio en consola; localhost/IP bloqueados
Concurrencialímite del navegadorMáx 10 concurrentes para request/upload/download
Timeoutpor llamadaDefault y máx 60s; configurable en app.json
Referrerlo pone el navegadorFormato fijo de plataforma, no customizable
BackgroundcontinúaSi no termina en 5s tras background, fail interrupted

La allowlist es el muro clásico: una request que funciona en DevTools con chequeo de dominio off falla en build de prueba y producción hasta que el dominio se registra y tiene ICP. Envuelve wx.request en una capa Promise para headers, inyección de token y manejo 401 — igual que harías con fetch, pero planifica la cola por el tope de 10 conexiones.

Almacenamiento y estado

localStorage se vuelve wx.setStorageSync / wx.getStorageSync, tope 10MB. sessionStorage no tiene gemelo directo — usa params de ruta o getApp().globalData global para lo efímero. No asumas que la persistencia tras cold start es instantánea; lee async donde la UI lo tolere.

Cuando las Web APIs no tienen gemelo

Algunas capacidades del navegador simplemente no están, y el plan de migración debe nombrarlas:

  • Geolocalización — navigator.geolocation → wx.getLocation (con autorización de scope).
  • Media / live — WebRTC no disponible; usa componentes nativos <live-pusher> / <live-player>.
  • Mapas, cámara, video — componentes nativos <map>, <camera>, <video> reemplazan los elementos HTML y se sitúan sobre la capa de render.
  • Cookies / same-origin — no hay cookie jar compartida con backend como en el navegador; la auth viaja como tokens en headers que tú inyectas.
  • File system — sin FS arbitrario; usa wx.getFileSystemManager para la sandbox que te dan.

Dónde encaja Cross Mini App

Cross Mini App te da un runtime que ya habla esta superficie — paridad wx.*, layout rpx, modelo de 10 conexiones y semántica de allowlist — así un H5 portado se vuelve una entrada del catálogo en lugar de un re-platforming. Conservas tu lógica de negocio, cambias los bordes de forma-navegador por bordes de forma-runtime, y publicas dentro de un host app que tus usuarios ya tienen. La migración es un mapa, no un acantilado.

Fuentes