Extensão de UI
Objetivo: entender que UI é uma extensão de compilador (não core): arquivos
.mkoui, reatividade por decorator, modelo de ilhas, e a fronteira servidor/cliente como channel de rede.
UI é extensão, e por quê
Seção intitulada “UI é extensão, e por quê”O core de Makoto não sabe o que é uma <div>. A UI é a primeira extensão oficial de compilador: ela
registra um tipo de arquivo (.mkoui, com sua gramática de markup), decoradores
(@state/@component/…) e alvos de codegen (JS/WASM/SSR). Um arquivo .mko nunca vê markup; quem
não faz UI nem encosta. A reatividade é volátil por natureza (paradigmas reativos giram a cada poucos
anos), e isolá-la numa extensão deixa ela envelhecer e ser trocada sem tocar o core.
A extensão liga por flag/manifesto; markup mora só em .mkoui.
Componente = função que retorna markup
Seção intitulada “Componente = função que retorna markup”Props são os parâmetros; o markup vai no return {} (não há retorno implícito: markup é o conteúdo
de um return block):
@componentfn Greeting(name: string, count: int) { return { <div class="card"> <h1>Olá, {{name}}</h1> <p>Você tem {{count}} mensagens</p> </div> }}Binding no markup, por posição: {{ }} interpola conteúdo (texto via Display, capítulo 05); { }
liga uma expressão depois de um = (prop, atributo dinâmico, handler).
Reatividade por decorator
Seção intitulada “Reatividade por decorator”@state count := 0 // estado reativo: mudou → re-renderiza quem depende@derived doubled := count * 2 // recomputa quando 'count' muda@effect { log("count = {{count}}") } // roda quando suas dependências mudamCada decorator é o construto do core mais a plumbing reativa que o compilador injeta. O modelo é de granularidade fina (estilo SolidJS): cada pedaço de estado sabe exatamente quem depende dele. Não há re-execução de componente inteiro nem Virtual DOM; o diff é direto no DOM real.
Onde o código roda: @server / @client
Seção intitulada “Onde o código roda: @server / @client”Você marca só o que é preso a um lado; o resto atravessa:
@server fn load_user(id: int) -> User { return db.query(...) } // só servidor: nunca vai pro cliente@client fn on_scroll() { ... } // só cliente: roda no browser (WASM)fn format_date(d: DateTime) -> string { ... } // sem marca: roda onde for chamadaModelo de ilhas
Seção intitulada “Modelo de ilhas”A maior parte da página é HTML estático renderizado no servidor; só os pedaços interativos (as “ilhas”) viram WASM no cliente, carregando apenas a reatividade daquela ilha. Não há hidratação de página inteira (o custo do React): você manda pro browser só o que reage.
A fronteira servidor/cliente é um channel de rede
Seção intitulada “A fronteira servidor/cliente é um channel de rede”Quando uma ilha precisa falar com o servidor, é o channel de rede do capítulo 09, não um mecanismo de
UI novo. Servidor e cliente são dois mundos isolados conversando por Channel[T] com
T + Serializable:
@clientfn LikeButton(post_id: int) { @state liked := false fn handle_click() { chan := net.connect[LikeAction]("/api/like") catch |e| { return } chan <- LikeAction{ post: post_id } reply := -> chan timeout(3s) catch |e| { return } liked = reply.ok } return { <button onclick={handle_click}>{{ liked ? "♥" : "♡" }}</button> }}CSS escopado (hashing de classe), @css pra CSS externo, e @jsimport (FFI de JS, sob o namespace
js.) completam a extensão, todos restritos a .mkoui.
Próximo: 15 · Tooling na prática