DOM & Web APIs (web-sys)
Acesse o DOM e as APIs do navegador a partir de Rust via web-sys e js-sys.
Receita
use wasm_bindgen::prelude::*;
use web_sys::{console, Document, Window};
#[wasm_bindgen]
pub fn log_message(msg: &str) {
// Registra uma mensagem no console do navegador.
console::log_1(&JsValue::from_str(msg));
}Quando usar isso: Módulos WASM que precisam manipular o DOM, buscar URLs ou usar Canvas/WebGL diretamente.
Exemplo de Trabalho
use wasm_bindgen::prelude::*;
use web_sys::{Document, HtmlElement, Window};
// Retorna a janela global do navegador.
fn window() -> Window {
web_sys::window().expect("no global window")
}
// Retorna o documento atual do navegador.
fn document() -> Document {
window().document().expect("no document")
}
#[wasm_bindgen]
pub fn mount_greeting(name: &str) -> Result<(), JsValue> {
let doc = document();
// Obtém o corpo do documento, retornando um erro se não existir.
let body = doc.body().ok_or("no body")?;
// Cria um novo elemento div.
let div = doc.create_element("div")?;
// Define o conteúdo de texto do elemento div.
div.set_text_content(Some(&format!("Hello, {name}!")));
// Adiciona o elemento div ao corpo do documento.
body.append_child(&div)?;
Ok(())
}
#[wasm_bindgen]
pub fn set_title(text: &str) {
// Define o título da página do navegador.
document().set_title(text);
}O que isso demonstra:
web_sysenvolve as APIs do navegador com tipos Rust.- Padrões
Option/Resultsubstituem verificações de nulo. - Mutações do DOM funcionam a partir de funções WASM exportadas.
- Erros são propagados como
JsValuepara chamadores JavaScript.
Mergulho Profundo
Flags de Funcionalidade
web-sys expõe milhares de APIs sob recursos do Cargo.
[dependencies.web-sys]
version = "0.3"
features = [
"console",
"Document",
"Element",
"HtmlElement",
"Window",
"Request",
"Response",
]Habilite apenas o que você precisa para manter os tempos de compilação razoáveis.
Exemplo de Fetch
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestInit, Response};
// Busca o conteúdo de texto de uma URL de forma assíncrona.
pub async fn fetch_text(url: &str) -> Result<String, JsValue> {
let opts = RequestInit::new();
opts.set_method("GET"); // Define o método HTTP como GET.
let request = Request::new_with_str_and_init(url, &opts)?; // Cria uma nova requisição.
let window = web_sys::window().unwrap(); // Obtém a janela global.
// Executa a requisição e aguarda a resposta.
let resp_value = JsFuture::from(window.fetch_with_request(&request)).await?;
// Converte o valor da resposta para o tipo Response.
let resp: Response = resp_value.dyn_into()?;
// Obtém o corpo da resposta como texto e aguarda.
let text = JsFuture::from(resp.text()?).await?;
// Retorna o texto como String, ou uma string vazia se a conversão falhar.
Ok(text.as_string().unwrap_or_default())
}Armadilhas
- Habilitar todos os recursos do web-sys - Os tempos de compilação explodem. Correção: Liste apenas os recursos necessários em
Cargo.toml. - DOM sem
window- SSR e testes não possuemwindow. Correção: Proteja as chamadas; simule em testes. - Lifetimes de empréstimo - Nós DOM são de propriedade do JS. Correção: Não armazene referências entre pontos de
awaitsem entender o GC. - Liberação de Closure - Closures de listener de eventos coletados muito cedo. Correção: Armazene
Closureem uma variável global ou useforgetintencionalmente. - Falhas de CORS - Erros de
fetchparecem falhas de rede. Correção: Configure os cabeçalhos CORS do servidor; apresente erros aos usuários.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Leptos / Yew | UI declarativa com Rust | Pequeno trecho de DOM |
| Camada de cola JavaScript | Equipe focada em JS | Você quer Rust de ponta a ponta |
| WASI HTTP (futuro) | HTTP fora do navegador | DOM do navegador necessário |
FAQs
web-sys vs js-sys?
js-sys cobre builtins do JS (Object, Array). web-sys cobre APIs Web IDL (Document, Canvas).
Como adiciono event listeners?
Use Closure::wrap e add_event_listener_with_callback.
Renderização Canvas?
Habilite os recursos CanvasRenderingContext2d e HtmlCanvasElement.
localStorage?
Habilite os recursos Storage e Window::local_storage.
WebSockets?
Use o recurso WebSocket com wasm-bindgen-futures para mensagens assíncronas.
serde JSON fetch?
Combine fetch_text com serde_json::from_str no corpo da resposta.
Testando código DOM?
wasm-bindgen-test no Chrome headless. Ou fatie a lógica pura das chamadas DOM.
Vazamentos de memória?
Remova os listeners quando terminar. Evite Closure::forget sem necessidade.
Shadow DOM?
Habilite os recursos ShadowRoot. A API espelha de perto o JS do navegador.
Workers?
APIs DOM não estão disponíveis em Web Workers. Use recursos DedicatedWorkerGlobalScope em vez disso.
Relacionados
- wasm-bindgen - Fundamentos da ponte JS
- Frameworks Frontend (Leptos / Yew) - UI de nível superior
- wasm-pack & Bundling - Envio para npm
- Performance & Tamanho - Disciplina de flags de funcionalidade
Versões da Stack: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, e Polars 0.46+.