3 pontos por GN⁺ 2024-03-29 | 1 comentários | Compartilhar no WhatsApp
  • O framework de GUI em Rust Dioxus 0.5 simplifica bastante os fluxos de desenvolvimento web, desktop, mobile e Fullstack, com foco na reescrita do dioxus-core e na remoção de unsafe
  • Entre as versões 0.4.3 e 0.5.0, foram incluídas mais de 100.000 linhas de código e mais de 1.400 commits; o novo core mudou para eliminar dependências de lifetimes e de Scope
  • O gerenciamento de estado antes centrado em use_state e use_ref foi substituído pela API Signal copiável, reduzindo o custo de Clone repetitivo em event handlers e futures
  • Com um único dioxus::launch e o fluxo dx serve --platform, é possível executar apps web, desktop e Fullstack; a CLI passa automaticamente as build features adequadas à plataforma de destino
  • Hot reload de assets, reescrita de eventos, melhorias na renderização desktop e streaming de funções de servidor também foram alterados, ampliando o alcance de uma base de código única em Rust

Direção do lançamento do Dioxus 0.5

  • Dioxus é uma biblioteca para criar GUIs em Rust e é usada para distribuir apps web, desktop e mobile
  • O lançamento 0.5 foi projetado com o objetivo de melhorar a simplificação, a robustez e o nível de acabamento pedidos pela comunidade
  • As principais mudanças são as seguintes
    • Reescrita completa do dioxus-core e remoção de código unsafe
    • Introdução de uma API baseada em Signal no lugar de use_state e use_ref
    • Remoção de todos os lifetimes e do estado cx: Scope
    • Uma única função launch para iniciar apps em todas as plataformas
    • Hot reload de assets com suporte a Tailwind e Vanilla CSS
    • Reescrita de eventos que permite acessar tipos de evento nativos do WebSys
    • Integração de Error Boundary, Server Future e Suspense
    • Melhoria de 5 vezes no reconciliation em desktop
    • Streaming de funções de servidor e hot reload Fullstack
  • Há um migration guide disponível para usuários que estão atualizando a partir do Dioxus 0.4

Remoção de lifetimes e Scope

  • Do Dioxus 0.1 ao 0.4, valores dentro de componentes tinham o lifetime 'bump, permitindo usar hooks, props e scope em event listeners sem clonagem
  • Em event handlers isso geralmente funcionava bem, mas futures do Dioxus precisam ser 'static, então era necessário fazer clone antes de mover valores para dentro de uma future
  • Quando ocorria um erro de lifetime, a mensagem podia dizer que cx, e não o hook em si, precisava viver mais que 'static, o que podia gerar confusão
  • O Dioxus 0.5 remove Scope e o lifetime 'bump, e transforma Element em uma forma sem lifetime
  • Componentes agora podem receber props diretamente, sem um parâmetro de scope
    • Ex.: fn MyComponent(name: String) -> Element
  • Funções de runtime podem ser usadas diretamente não só dentro de componentes, mas também dentro de futures e event handlers
  • Como Element passou a ser 'static, também é possível usá-lo dentro de hooks ou fornecê-lo por meio da context API
  • Essa mudança cria uma base que facilita implementar APIs como listas virtuais ou renderização off-screen

Remoção de unsafe do dioxus-core

  • A remoção do lifetime 'bump e de scope criou uma oportunidade para reduzir código unsafe dentro do Dioxus
  • dioxus-core 0.5 não contém código unsafe
  • Algumas dependências ainda têm uma pequena quantidade de unsafe, e a equipe do Dioxus planeja removê-la durante o ciclo de lançamento da 0.5
  • O unsafe restante é classificado como algo que pode simplesmente ser removido ou como necessário por causa de FFI

Gerenciamento de estado baseado em Signal

  • O Dioxus 0.5 introduz Signal como tipo primitivo central de estado para componentes
  • Signal tem duas vantagens em relação aos antigos use_state e use_ref
    • É sempre Copy
    • Não exige assinatura manual
  • Estado Copy

    • Signal<T> é Copy mesmo quando o valor interno T não é Copy
    • Esse comportamento é possível graças ao crate generational-box, implementado sem unsafe
    • Se necessário, Signal pode ser Send+Sync, permitindo movê-lo entre threads
    • A combinação de estado Copy, Signal Send+Sync e componentes static permite mover estado facilmente para onde for necessário, como futures, event handlers e threads
    • O padrão de uso de memória é quase igual ao da 0.4, mas sem necessidade de Clone explícito
  • Assinaturas inteligentes

    • Signal decide com mais granularidade quais componentes devem ser executados novamente quando o valor muda
    • Um componente só é executado novamente se tiver lido o valor do Signal
    • Leituras em tarefas async ou event handlers não são tratadas como assinaturas para reexecutar o componente
    • Se um pai altera um Signal ao clicar em um botão, mas não lê o valor diretamente, e apenas o filho lê o valor, só o filho é renderizado novamente
    • Graças a essa estrutura, o Fermi, que era um crate separado de gerenciamento de estado, deixa de ser necessário
    • Fermi fornecia uma API semelhante a use_state usando static como chave
    • No Dioxus 0.5, é possível colocar GlobalSignal em um static e usá-lo como um Signal comum
    • Signal também funciona com a context API, permitindo compartilhar estado entre componentes sem um hook use_shared_state separado
    • Ao ler um Signal dentro de hooks como use_future e use_memo, esse Signal é adicionado automaticamente às dependências do hook

Hot reload de CSS e assets

  • Como parte da reformulação do sistema de assets, o Dioxus 0.5 implementa hot reload para arquivos CSS no diretório de assets
  • Quando um arquivo CSS aparece dentro de RSX, a CLI dx monitora esse arquivo e transmite imediatamente as atualizações para o app em execução
  • O suporte abrange Web, Desktop e Fullstack; suporte mobile será oferecido em uma futura atualização com foco em mobile
  • Usado junto com o watcher do Tailwind, também há suporte a hot reload de Tailwind CSS
  • No VSCode, é possível obter dicas de classes Tailwind por meio da custom regex extension
  • É possível transmitir mudanças simultaneamente para vários dispositivos e fazer hot reload em todos os dispositivos de destino

Reescrita do sistema de eventos

  • Desde seu lançamento, o Dioxus usa um sistema de synthetic events para criar uma API de eventos cross-platform
  • Synthetic events são úteis para comportamento de eventos entre plataformas e serialização em rede, mas também têm limitações
  • O Dioxus 0.5 expõe os tipos de evento subjacentes de cada plataforma e também fornece traits para a API cross-platform
  • Essa mudança traz duas vantagens
    • É possível obter diretamente as informações necessárias a partir do tipo de evento da plataforma ou passá-lo para outras bibliotecas
    • Código de eventos que o app não usa pode ser separado por bundle splitting
  • No exemplo hello world, o tamanho gzipped caiu cerca de 25%
  • Dicas para criar bundles pequenos estão incluídas no Dioxus optimization guide

API de execução cross-platform

  • O Dioxus 0.5 introduz uma nova API cross-platform para executar apps
  • Em vez de importar um pacote de renderer separado, basta ativar a feature no crate dioxus e chamar a função launch do prelude
  • Um único app pode ser executado tendo como alvo as seguintes plataformas
    • Desktop: dx serve --platform desktop
    • SPA Web: dx serve --platform web
    • Fullstack: dx serve --platform fullstack
  • A CLI passa automaticamente a build feature apropriada de acordo com a plataforma de destino

Sistema de assets beta e Manganis

  • Em Dioxus e em apps web, caminhos de assets podem ficar desatualizados, links podem variar entre desktop e web, e assets a incluir no bundle precisam ser adicionados manualmente
  • Assets também podem se tornar gargalos de desempenho
  • No exemplo do guia Dioxus Mobile, a versão 0.4 levava 7 segundos para carregar e transferia 9 MB de recursos
  • O guia mobile da 0.5 usa as mesmas imagens, mas carrega em menos de 1 segundo e reduz os recursos necessários para 1/3
  • O Dioxus 0.5 introduz o novo sistema de assets manganis
    • Ele se integra à CLI para verificar, empacotar e otimizar assets do app
    • A API ainda é instável, então é distribuída como um crate separado
    • Ao envolver assets com a macro mg!, a CLI os detecta automaticamente
    • Mais detalhes estão na documentação do manganis
  • Durante o lançamento da 0.5, também há planos de adicionar hot reload aos assets do manganis

Renderização desktop 5 vezes melhor

  • O Dioxus usa várias otimizações para tornar o diff de renderização rápido
  • Templates permitem pular o diff das partes estáticas da macro rsx!
  • No Dioxus Web, o sledgehammer aplica rapidamente mudanças no DOM a partir de Rust
  • O Dioxus 0.5 usa a mesma abordagem para aplicar mudanças via rede
  • Os renderers Desktop e LiveView comunicam mudanças por meio de um protocolo binário em vez de JSON
  • Em trabalhos com alta carga de renderização, o novo renderer reduz para 1/5 o tempo para aplicar mudanças no navegador e reduz a latência pela metade
  • Um benchmark em que o renderer travava continuamente no Dioxus 0.4 roda suavemente no Dioxus 0.5

Recursos que facilitam escrever componentes

  • O Dioxus 0.5 oferece suporte a estender um element específico e espalhar atributos em um element
    • Ex.: em um componente ImgPlus que estende os atributos de um element img, é possível receber normalmente atributos comuns de img, como width, height e src
  • Ao passar valores para atributos e componentes, é possível usar a sintaxe abreviada de inicialização de structs
    • É possível escrever class em vez de class: class
  • Atributos abreviados funcionam com qualquer item que implemente IntoAttribute, e Signal também se beneficia disso
  • Atributos Signal ainda não pulam diffing, mas isso deve ser adicionado como otimização de desempenho durante o ciclo de lançamento da 0.5
  • Atributos divididos em várias linhas podem ser mesclados
    • Ao adicionar valores condicionais ao mesmo atributo class, eles são mesclados usando espaço como separador
    • Isso é importante para bibliotecas como Tailwind, que exigem parsing em tempo de compilação e também processamento dinâmico em runtime
    • Essa sintaxe é integrada ao compilador do Tailwind e elimina o overhead em runtime de bibliotecas como tailwind-merge

Streaming de funções de servidor e Fullstack

  • O Dioxus 0.5 oferece suporte ao crate moderno de server functions, que dá suporte a dados em streaming
  • Funções de servidor podem transmitir dados para o cliente ou transmitir dados do cliente para o servidor
  • Uma função de servidor em streaming pode ser criada definindo o tipo de saída e retornando TextStream a partir da função de servidor
  • Isso é adequado para atualizar o cliente durante tarefas demoradas
  • Há um exemplo que usa Kalosm e um LLM local para fornecer, em hardware comum, uma funcionalidade semelhante ao endpoint OpenAI ChatGPT
  • A CLI agora oferece suporte à plataforma fullstack e fornece hot reload e builds paralelos para cliente e servidor
    • dx serve
    • dx serve --platform fullstack

LiveView, handler de assets e processamento de arquivos

  • No Dioxus 0.5, o router funciona por padrão em apps LiveView
  • O Dioxus Desktop oferece suporte a custom asset handler
  • Custom asset handlers permitem transmitir dados de forma eficiente do código Rust para o navegador sem passar por JavaScript
  • Isso é adequado para comunicação de alta largura de banda, como streaming de vídeo
  • É possível entregar dados de gstreamer ou webrtc diretamente para a webview, reduzindo a necessidade de codificar e decodificar frames manualmente
  • O drop de arquivos no desktop também foi integrado nativamente ao sistema de eventos

Tratamento de erros

  • Dioxus permite tratar erros facilmente em componentes superiores por meio de Error Boundary e do trait throw
  • A abordagem throw combina as vantagens de estado de erro e retorno antecipado
  • É possível chamar throw em um tipo Result que implementa Debug para transformá-lo em estado de erro e retornar antecipadamente com ?
  • O componente ErrorBoundary renderiza outro componente quando há um erro lançado por um filho
  • ErrorBoundary pode ser aninhado, permitindo capturar erros em vários níveis do app
  • Esse padrão é útil para tratar estado de erro global quando ocorre um erro irrecuperável, sem recorrer a panic nem gerenciar manualmente o estado para cada erro

Experiência de desenvolvimento e templates

  • Dioxus introduziu hot reload na 0.3, adicionou isso ao Desktop na 0.4 e, na 0.5, ativou por padrão
  • Ao executar um app com dx serve, o hot reload fica ativado por padrão no modo de desenvolvimento
  • Mesmo quando hot reload não é possível em apps Desktop e é preciso recompilar tudo, o estado da janela aberta é preservado e restaurado
    • O tamanho e a posição da janela do app são mantidos
    • Isso reduz situações em que o app cobre a tela inteira a cada edição
  • Os novos templates foram organizados para permitir criar apps Web, Desktop, Mobile, TUI e Fullstack com um único comando
  • O app padrão de dx new passou a ter uma forma mais próxima de create-react-app
    • Inclui assets, CSS e configuração básica de deploy
    • Inclui links para recursos úteis, como dioxus-std, VSCode Extension, documentação e tutoriais

Dioxus Community e ecossistema

  • A Dioxus Community atualizou crates importantes do ecossistema para o lançamento 0.5
  • Crates como icons, charts e a biblioteca padrão específica para Dioxus foram preparados para uso imediato no momento do lançamento da 0.5
  • O projeto Dioxus Community é uma nova organização no GitHub para manter crates importantes atualizados mesmo quando o mantenedor original se afasta
  • Para quem cria bibliotecas para Dioxus, o lado do Dioxus pode ajudar na manutenção, com o objetivo de mantê-las, na prática, como suporte “Tier 2”

Recursos planejados para o futuro

  • Os planos após a 0.5 incluem os seguintes itens
    • Estabilização e integração mais profunda do sistema de assets
    • Bundle splitting direto do .wasm de saída com lazy component
    • Islands e resumable interactivity, serialização de Signal
    • Fusão de Server component e LiveView em Fullstack
    • Devtools aprimoradas e framework de testes
    • Reformulação completa de Mobile
    • Reformulação de Fullstack, incluindo WebSocket, SSE e progressive form

Prévia do Dioxus-Blitz baseado em Servo

  • No “Blitz 2.0” do Dioxus-Blitz, o objetivo é integrar o Servo para renderização nativa em WGPU com o mesmo mecanismo CSS usado para rodar o Firefox
  • Nico Burns, criador da biblioteca de layout Taffy, entrou em tempo integral para impulsionar esse trabalho
  • Na demo, google.com é renderizado na GPU a 900 FPS
  • A implementação atual ainda não está completa e a renderização de google.com ainda é um pouco estranha, mas está se aproximando rapidamente de um nível utilizável
  • O repositório pode ser consultado em https://github.com/jkelleyrtp/stylo-dioxus

Como contribuir

  • O projeto Dioxus busca as seguintes contribuições
    • Tradução da documentação
    • Tentar “Good First Issues”
    • Melhorias na documentação
    • Contribuições para a CLI
    • Responder a perguntas da comunidade no Discord
  • A equipe do Dioxus agradece pelo apoio da comunidade durante o restante de 2024 e pede ajuda para transformar o desenvolvimento de apps

1 comentários

 
GN⁺ 2024-03-29
Opiniões no Hacker News
  • No ano passado, criei o cliente Mastodon Ebou com Dioxus e, no geral, foi uma boa experiência, mas também faltava bastante coisa.
    Quando comecei a trabalhar, ele estava na versão 0.2, e parece que as mudanças desta 0.5 removeram quase toda a complexidade que eu encontrei na época. Ainda não testei pessoalmente, mas a remoção de lifetimes e a redução da necessidade de ficar clonando tudo devem tornar a experiência bem mais agradável
    • Fico curioso para saber como você escolheu o Dioxus.
      Há muitos frameworks Rust tentando oferecer UI reativa nativa que possa ser distribuída para desktop, web/wasm, mobile etc. https://github.com/flosse/rust-web-framework-comparison, então me preocupa escolher errado e acabar tendo que manter um framework abandonado ou fazer uma migração dolorosa.
      Frameworks de servidor HTTP em Rust também eram muitos, e agora Axum, Actix e Rocket parecem estar na frente; além disso, a comunidade parece estar migrando para Axum, então às vezes me pergunto se escolher Actix foi um erro. Gostaria de saber se há sinais de que o Dioxus vai vencer, ou se há indicadores de que ele é uma escolha segura hoje além de uma comunidade grande, apoio da YC e momentum.
      Também gostaria de saber se Leptos e Yew são concorrentes importantes, e em que eles são melhores ou piores que o Dioxus. Minha empresa investiu bastante em Rust, Actix e Bevy, e no futuro queremos combinar frameworks como Bevy e Dioxus para criar clientes nativos para desktop e mobile.
      E também fico curioso se o nome Dioxus vem do Deoxys de Pokémon. O logo dá essa impressão, mas não há referências a Pokémon no codebase
  • Concordo com a frase “no geral foi bom, mas faltava bastante coisa”.
    Há uns 9 meses, criei um frontend GUI para sshfs com Dioxus, e minha impressão era de que ele era um framework GUI realmente excelente até você bater em alguma parede de um recurso que os desenvolvedores ainda não tinham terminado.
    Compartilhar estado entre contextos diferentes também às vezes é doloroso, mas todo framework GUI que já usei foi assim, independentemente da linguagem ou da tecnologia de base. O Dioxus 0.5 parece um grande avanço nessa área. Meu blog renderiza uma parte considerável do HTML com Dioxus e, como não é um uso que força os limites, funciona muito bem
  • Tenho acompanhado o Dioxus com interesse, mas ainda não tive chance de usá-lo.
    No entanto, a solução de remoção de lifetimes me parece um pouco estranha. O generational-box me parece uma espécie de coletor de lixo de pobre, então fico curioso sobre o impacto em desempenho.
    Além disso, o link [generational-box]([https://crates.io/crates/generational-box](<https://crates.io/crates/generational-box>;)) está quebrado
    • É mesmo um coletor de lixo de pobre, mas a semântica de memória é exatamente a mesma das versões anteriores.
      use_hook possui o valor durante o lifetime do componente, então quando o componente desaparece, esse valor também é descartado. Todos os signals ainda usam use_hook, portanto o lifetime também é o mesmo. Normalmente não se recomenda chamar GenerationalBox::new() fora de use_hook, então não há impacto em desempenho.
      Se você sair chamando GenerationalBox::new() sem parar dentro de um loop, esse lixo ficará lá até o componente ser descartado, mas na maior parte dos casos as pessoas vão fazer push/pop em um Map ou Vec, e aí se aplica a semântica de memória normal
    • Isso é essencialmente contagem automática de referências: https://en.wikipedia.org/wiki/Automatic_Reference_Counting
  • Não sou programador Rust, mas fiquei curioso sobre como o crate generational-box funciona.
    Entendo que seja um tipo de alocação em arena, mas não entendo como ele oferece “copiar sem copiar”, nem por que é seguro dizer que ele cria internamente uma arena de RefCell com gerações e que GenerationalBox é Copy.
    Entendo que seja possível criar ponteiros para dados estáticos, mas fico curioso sobre o que acontece com valores que não têm lifetime estático
    • Não se copia o dado, e sim a referência ao dado.
      A referência ao dado se mantém durante o lifetime do programa. A generational box permite colocar dados que vivem menos que o programa, mas esses dados não podem conter referências. Quando os dados inseridos são descartados, a box é reutilizada para outra alocação.
      É uma abordagem muito parecida com uma arena geracional, exceto pelo uso de boxes em vez de uma arena centralizada, uma escolha para evitar problemas de locking. Se você tentar acessar os dados por uma referência Copy depois de eles terem sido descartados, a operação falha com uma boa mensagem de erro
    • Não conheço bem esse crate, mas, do ponto de vista do Rust, Copy tem um significado específico.
      Quando um tipo implementa o trait Copy, isso significa que ele pode ser copiado com memcpy; não é uma cópia profunda, é mais como uma cópia rasa.
      Então não entendo como “copiar sem copiar”, mas sim como permitir tratar um tipo que não é Copy como se fosse um tipo Copy. O README diz que conteúdo estático é necessário, então para valores sem lifetime estático a resposta é “não dá para fazer isso”
  • Acompanhei por um tempo e fico muito feliz que tenha sido lançado.
    Gosto do Dioxus porque ele pega muitos dos elementos que fizeram o React dar certo, mas inova e entrega rapidamente em cima disso. Estou ansioso para experimentar os signals desta versão
  • Eu gostaria que, em vez de RSX, fosse algo mais próximo de SwiftUI do que de React/JSX.
    Reconheço as coisas boas que o React fez pelo JS e pela web, além do peso do nome, mas, se você pudesse projetar uma linguagem ou DSL do zero em 2024, não acho que código de “UI reativa” precise necessariamente se parecer com React.
    Não quero dizer que SwiftUI seja perfeito, mas o código escrito em SwiftUI parece muito mais limpo, organizado e compartimentado do que código equivalente em React

A verdadeira vantagem de usar JSX em GUIs multiplataforma é mais ou menos poder reutilizar bibliotecas existentes para a Web; já o RSX parece ter pouco “valor portável” além de permitir que o desenvolvedor transfira seu conhecimento conceitual de JSX para RSX. Talvez o melhor compromisso seja aprender um novo paradigma que seja objetivamente melhor que o paradigma React/JSX
Em resumo, seria ótimo se existisse um projeto que fosse “SwiftUI, mas multiplataforma”, mas ainda não há. Conheço @Tokamak/TokamakUI, mas ele ainda parece bem incompleto e a atividade parece ter diminuído

  • Existe o https://ribir.org/
    Atualmente ele só oferece suporte a apps desktop nativos para Linux/mac/windows, mas há planos de suporte a WASM, Web e mobile
  • Escolhi o Dioxus para criar a homepage descentralizada do Freenet
    Ela será o primeiro site descentralizado que as pessoas verão ao configurar o Freenet. Ele é um pouco parecido com o Kweb, um framework Web em Kotlin no qual venho trabalhando de forma intermitente há alguns anos, especialmente no tratamento de estado e na abordagem de DSL que mapeia código para HTML. Até agora, estou gostando
    https://freenet.org/
    https://kweb.io/
    • Legal. Acho que olhei o kweb quando estava projetando a primeira DSL, e os dois são realmente bem parecidos
      Na verdade sou fã de Kotlin e gosto da DSL de Kotlin e do seu modelo de concorrência
  • Fico curioso sobre como ele se compara ao Tauri
    • Coloquei isso no README: https://github.com/dioxusLabs/dioxus/?tab=readme-ov-file#dioxus-vs-tauri
      O Tauri coloca o frontend em uma WebView, e você precisa se comunicar com funções Rust nativas por meio de uma fronteira de IPC, como no Electron
      No Dioxus, o código Rust fica no lado nativo, então tarefas como ler o sistema de arquivos ou usar WebSockets não precisam de IPC. O Tauri força a compilação do frontend para WASM, e muitas crates Rust interessantes não compilam para wasm
      É difícil expressar em palavras o quanto o desenvolvimento fica mais simples quando não há fronteira de IPC. Como as ferramentas do Dioxus têm como alvo apenas Rust, é possível ir do zero a um .app empacotado em menos de 1 minuto. Um build novo leva cerca de 12 segundos, e um bundle novo, cerca de 20 segundos
      Ainda assim, gosto muito da flexibilidade que o Tauri oferece: poder usar como frontend qualquer UI compatível com a Web. E também é possível usar Dioxus dentro de um app Tauri
    • Eu também entrei para fazer essa pergunta
      Foi bom o Dioxus tratar disso diretamente no README, mas também fico curioso sobre a experiência real de pessoas que usaram os dois
      Fiz um app desktop de brinquedo com Tauri e confirmei se o IPC era rápido o bastante para o frontend Web atualizar a cada tecla pressionada e trabalhar sem latência; a resposta foi “sim”. Se dava para enviar um arquivo grande do frontend para a camada Rust a cada tecla pressionada e recebê-lo de volta no frontend, pelo menos na minha implementação ingênua, a resposta foi “não”
      Tanto Tauri quanto Dioxus têm muitos casos em que parecem bons, e em alguns casos o Dioxus deve ser melhor. Gostaria de ouvir relatos comparativos do tipo “no nosso projeto escolhemos Dioxus ou Tauri por causa de X e Y”. O Dioxus parece muito legal, estou ansioso para experimentar
  • Fico curioso sobre como os apps nativos são renderizados. Eles ainda rodam dentro de algum tipo de instância de navegador?
    • Você pode usar a WebView do sistema como renderizador ou escolher um engine experimental baseado em WGPU que incorpora o stylo
      O stylo é a parte do Servo compartilhada com o Firefox. No longo prazo, queremos levar as pessoas para o renderizador WGPU, mas ele ainda está em um estágio bem inicial, e muitas empresas que usam Dioxus sabem, de forma pragmática, que a WebView é uma solução boa o suficiente para cerca de 90% do app
  • Na parte que diz “durante o ciclo de lançamento da 0.5, planejamos remover o pouquíssimo unsafe restante em várias dependências”, eu gostaria de ver onde ele é usado e qual é a motivação
    Entendo que às vezes as pessoas usam unsafe com facilidade demais, mas a biblioteca padrão também é cheia de unsafe, e traçar a linha ali às vezes parece desenhar uma linha na areia
    • Na maior parte, é necessário para interagir com FFI ou declarar alguns tipos como Send/Sync
      Ele é usado em três lugares: alguns ajustes de FFI no iOS, a implementação para permitir sintaxe de chamada de função em signal e a parte que implementa Send/Sync para IDs que usam ponteiros como hash
      Agora que olho para o último caso, talvez seja possível removê-lo substituindo por usize
    • Concordo que as pessoas podem ter um pouco de medo exagerado de unsafe
      Mesmo assim, não é necessariamente uma decisão ruim um autor de crate estabelecer como meta remover unsafe da própria crate
      Autores de crates que tentam remover todo unsafe muitas vezes querem reduzir o ônus de confiança que o usuário precisa assumir. Para mim, esse é o poder da palavra-chave unsafe. Na verdade, talvez ela devesse ter sido dividida entre blocos trust_me e funções check_yourself
      unsafe restringe a conversa sobre segurança de memória a pontos muito estreitos e auditáveis do código e, ao mesmo tempo, cria uma nova conversa sobre confiança que é gerenciável
  • Entendo por que o React criou a convenção de nomes use* para a API de hooks, mas fico curioso por que, no Dioxus, a função que cria um novo signal se chama use_signal
    let mut count = use_signal(|| 0); não é uma chamada que cria um novo signal? O signal não é recriado a cada renderização, e esse é justamente o ponto de um signal
    No SolidJS, você cria um signal com createSignal, como em const [count, setCount] = createSignal(0), e isso é muito mais fácil de entender
    Nomes de API importam. Isso porque hooks de estado se comportam de maneira diferente e também podem surgir necessidades complementares como useMemo. Fico curioso se há algum motivo para ter escolhido o nome use_signal além de fazer o Dioxus parecer próximo do React
    • O Dioxus ainda renderiza novamente os componentes, mas aplica muitas otimizações ao rsx que o componente gera, chegando a um desempenho próximo ao do Solid
      Ele é mais próximo do Preact do que do Solid
      As otimizações incluem separar as partes dinâmicas da UI em “diff bins” separados, memoização básica e signals marcando propriedades implicitamente como dirty/managed