Um rewrite só de nome

Você tem uma página web que funciona. Renderiza, faz fetch, guarda um token, escuta o scroll. Para publicá-la dentro de um runtime de mini-programas você não a joga fora: você a remapeia. A lógica sobrevive na maior parte; muda a superfície sobre a qual roda. A armadilha é assumir que o navegador ainda está embaixo. Não está: não há document, não há window, não há localStorage global e não há <div> que você possa cutucar. Este é o mapa que mantém a migração previsível.

Ciclo de vida: os eventos viram callbacks

Na web você depende de DOMContentLoaded, load e visibilitychange. Uma página de mini-programa é um objeto Page() cujo ciclo de vida é um conjunto de callbacks nomeados:

Page({
  onLoad(query) { /* uma vez, ao criar — leia params de rota aqui */ },
  onShow() { /* cada vez que aparece, incl. voltar do filho */ },
  onReady() { /* primeiro render pronto, seguro consultar layout */ },
  onHide() { /* para segundo plano ou navegou para fora */ },
  onUnload() { /* destruída — limpe timers aqui */ },
})

A maior diferença de comportamento: onShow dispara ao voltar de uma página filha, então as listas que precisam refletir uma mutação feita a jusante são re-buscadas ali — não só em onLoad. Os eventos de nível app (onLaunch, onShow, onHide) vivem em App(). Não há aviso beforeunload; se precisar, intercepte a chamada de navegação.

Vista: HTML e CSS viram WXML e WXSS

HTML vira WXML — um template com bindings {{ }} e sem DOM para percorrer. Você nunca faz document.querySelector e muta; chama this.setData({ key: value }) e a camada de render faz o diff. Esta única regra elimina toda uma categoria de bugs de layout mas também mata qualquer código que assumisse poder alcançar a árvore de nós.

WXSS é CSS com duas mudanças que mordem: uma nova unidade rpx onde 750rpx equivale à largura da tela (design de 375px → 750rpx, auto-escalado por dispositivo), e um conjunto de seletores reduzido — sem seletores adjacentes nem de atributo, e bem menos pseudo-classes (last-child some). Mantenha estilos planos e baseados em classe.

Rede: fetch vira wx.request

É aqui que a maioria das migrações trava. wx.request não é fetch:

AspectoWeb (fetch)Mini-programa (wx.request)
TransporteHTTP/HTTPS, qualquer hostSó HTTPS/WSS, host deve estar na allowlist
DomínionenhumAllowlist de domínio no console; localhost/IP bloqueados
Concorrêncialimite do navegadorMáx 10 concurrentes para request/upload/download
Timeoutpor chamadaPadrão e máx 60s; configurável em app.json
Referrerdefine o navegadorFormato fixo de plataforma, não customizável
BackgroundcontinuaSe não terminar em 5s após background, fail interrupted

A allowlist é o muro clássico: uma request que funciona no DevTools com checagem de domínio off falha no build de trial e produção até o domínio ser registrado e ter ICP. Envolva wx.request em uma camada Promise para headers, injeção de token e tratamento 401 — igual ao que faria com fetch, mas planeje a fila pelo teto de 10 conexões.

Armazenamento e estado

localStorage vira wx.setStorageSync / wx.getStorageSync, teto 10MB. sessionStorage não tem gêmeo direto — use params de rota ou getApp().globalData global para o efêmero. Não assuma que a persistência após cold start é instantânea; leia async onde a UI tolerar.

Quando as Web APIs não têm gêmeo

Algumas capacidades do navegador simplesmente não existem, e o plano de migração deve nomeá-las:

  • Geolocalização — navigator.geolocation → wx.getLocation (com autorização de scope).
  • Mídia / live — WebRTC indisponível; use componentes nativos <live-pusher> / <live-player>.
  • Mapas, câmera, vídeo — componentes nativos <map>, <camera>, <video> substituem os elementos HTML e ficam acima da camada de render.
  • Cookies / same-origin — não há cookie jar compartilhado com backend como no navegador; a auth viaja como tokens em headers que você injeta.
  • File system — sem FS arbitrário; use wx.getFileSystemManager para a sandbox que lhe dão.

Onde entra o Cross Mini App

O Cross Mini App te dá um runtime que já fala esta superfície — paridade wx.*, layout rpx, modelo de 10 conexões e semântica de allowlist — assim um H5 portado vira uma entrada do catálogo em vez de um re-platforming. Você mantém sua lógica de negócio, troca as bordas em forma-de-navegador por bordas em forma-de-runtime, e publica dentro de um host app que seus usuários já têm. A migração é um mapa, não um penhasco.

Fontes