- Rwf é um framework abrangente para criar aplicações web em Rust, baseado no padrão clássico MVC, e traz por padrão os recursos necessários para construir apps web rápidos e seguros
- Os recursos básicos incluem servidor HTTP, ORM para consultas PostgreSQL, templates dinâmicos, autenticação e sessões de usuário, middleware, tarefas em background e tarefas agendadas, além de migrações de banco de dados
- Também oferece um framework REST integrado com suporte a serialização JSON, WebSockets, hospedagem de arquivos estáticos, configurações por ambiente, logging e métricas, além de CLI
- Integra-se estreitamente ao Hotwired Turbo para criar SPAs orientadas pelo backend, e oferece um servidor WSGI para migração de Django/Flask e um servidor Rack para migração de Rails
- Atualmente em estado beta, busca early adopters; afirma que a maioria dos recursos está em bom estado e que a documentação já é utilizável
Framework web MVC para Rust
- Rwf é um framework abrangente para construir aplicações web em Rust
- Foi escrito com o padrão clássico MVC(model-view-controller)
- Seu objetivo é incluir por padrão os recursos necessários para facilitar a criação de apps web rápidos e seguros
- A documentação está disponível na documentação oficial
Recursos oferecidos
- Servidor e processamento de requisições
- Dados e estrutura da aplicação
- Oferece um ORM amigável para criar consultas PostgreSQL com facilidade
- Suporta migrações de banco de dados
- Oferece Dynamic templates
- Inclui Authentication e sessões de usuário integradas
- API e processamento de tarefas
- Operação e ferramentas de desenvolvimento
- Suporta configurações por ambiente
- Oferece logging e métricas
- Inclui uma CLI
Hotwired Turbo e suporte a migração
Início rápido
- Crie uma aplicação binária em Rust e adicione
rwf às dependências para usá-lo
cargo add rwf
- Um app básico usa
rwf::prelude::* e rwf::http::Server para definir controllers e rotas
use rwf::prelude::*;
use rwf::http::Server;
#[controller]
async fn index() -> Response {
Response::new().html("Welcome to Rwf!
")
}
#[tokio::main]
async fn main() {
Server::new(vec![
route!("/" => index),
])
.launch()
.await
.unwrap();
}
Exemplos e status do projeto
- Casos de uso comuns podem ser consultados em examples
- O Rwf está atualmente em estado beta e busca early adopters
- Afirma que a maioria dos recursos está em bom estado e que a documentação já é utilizável
- Contribuições são bem-vindas; o guia está em CONTRIBUTING, a orientação sobre a estrutura do código está em ARCHITECTURE, e a lista de recursos desejados está em ROADMAP
1 comentários
Opiniões do Hacker News
O lançamento deve parecer bastante irreal, parabéns. A maior coisa que aprendi fazendo MVC web com Rails por muito tempo é que o framework precisa conter fortemente a lógica de negócios na camada de modelo
Acho melhor não colocar no modelo de dados callbacks como os de que o Active Record fala, por exemplo hooks como
afterCreate. Ainda não está no ORM, mas se estiver no roadmap, acho melhor que continue foraNo entanto, isso só funciona direito quando se recomenda fortemente uma camada de serviço, ou seja, de lógica de negócios. A maioria dos meus apps Rails organiza objetos de comando/serviço com gems como Interactor
Só MVC, e portanto só a configuração padrão do Rails, não me parece ideal para escrever um app operável, por causa da ausência de uma camada de serviço. Também fico curioso sobre por que não aproveitaram ORMs ou query builders existentes da comunidade. Ainda não escrevi uma única linha de Rust, mas estou ficando cada vez mais curioso
Acho que serviços deveriam ser quase sempre trechos de código mais complexos e específicos disparados a partir do modelo. Controllers finos e modelos gordos foram o melhor para depuração, organização e descobribilidade, e, pela minha experiência, usar muitos serviços gera muito código espaguete
Mesmo de uma perspectiva puramente orientada a objetos, o modelo é o objeto fundamental que define a entidade.
Userdeve saber tudo o que precisa saber sobre si mesmo e se comunicar com outras entidades por mensagensMas concordo quanto aos callbacks. Callbacks criam muitos efeitos colaterais estranhos e tornam a depuração realmente difícil
Dá para fazer isso, mas fica bem difícil raciocinar sobre de que maneiras uma entidade pode ser atualizada. Isso porque qualquer número de procedimentos pode atualizá-la e cada um pode ter suas próprias regras de negócio. Se for assim, os procedimentos poderiam escrever diretamente no banco de dados e eliminar o modelo
Mas, depois de mais de 20 anos desenvolvendo, cheguei à conclusão de que encapsulamento é um fardo, não um recurso, e que dados devem ser separados das operações realizadas sobre esses dados. Isso é chamado de design orientado a dados ou programação orientada a dados, e não sou o único a ter chegado à mesma conclusão
Há outras formas de modelagem que escalam bem, e também alguns textos relacionados. Há este artigo de alguém da Basecamp: https://dev.37signals.com/vanilla-rails-is-plenty/
Claro, isso é muito orientado a objetos, então também não gosto tanto. Por exemplo, o framework Phoenix, do Elixir, usa contextos para agrupar funcionalidades relacionadas; em termos simples, dá para vê-los como uma fachada
Se você gosta de serviços, pode usá-los, mas acho um pouco fora do alvo dizer que MVC não é suficiente para produção. Tratar processos de negócio pesados com callbacks de modelo não é bom, mas para pequenas tarefas de ajustar dados para o formato correto, funciona muito bem
Talvez eu tenha um viés, especialmente porque minha experiência de programação começou com PHP para Wordpress, que usa hooks extensivamente
O que criei tem uma especificação de tabelas que pode ser convertida para definições SQL ou cuspir formulários HTML bem formatados. Um controller separado lida com todas as conexões ao DB e operações CRUD, e há hooks antes e depois que permitem, se necessário, referenciar facilmente outras tabelas e restrições
Funciona bem, mas, se pudesse, eu migraria para Laravel imediatamente
Se é um framework REST, eu esperaria que, por padrão, ele conseguisse gerar definições Swagger/OpenAPI. Vejo isso como um dos recursos matadores do FastAPI
Também não entendo bem por que criaram o próprio ORM em vez de integrar com um ORM existente como diesel.rs, e por que fizeram a própria linguagem de templates em vez de escolher um engine de templates existente e popular
Fora isso, o projeto parece realmente interessante e pretendo continuar acompanhando
[0] https://diesel.rs/
[1] https://crates.io/categories/template-engine
No geral, foi uma boa primeira tentativa de ajustar tipos de banco de dados a tipos Rust, mas um ORM precisa ser mais flexível e fácil de usar. Ele deve tornar consultas mais fáceis, não mais difíceis :)
Na parte de templates, criar a própria linguagem é quase um rito de iniciação no clube dos nerds de 30 anos ou mais. Não li o Dragon Book, mas sempre quis ter feito aquela disciplina na faculdade. Sempre há várias implementações para a mesma coisa, e pareceu certo usar esta implementação que imita bem de perto o que o ERB do Rails faz
Do ponto de vista de SRE, https://levkk.github.io/rwf/migrating-from-python/ chamou minha atenção. Por um lado, é realmente incrível terem conseguido fazer isso, mas, do ponto de vista de um SRE olhando para estabilidade, isso me faz gritar por dentro
Quando a escala cresce, isso precisa ser tratado por um proxy reverso como Caddy, Nginx ou Traefik
É possível escrever um servidor WSGI estável e, com um pouco de atenção a detalhes como número de threads, vacuum e reiniciar a cada n requisições como o antigo php-fpm, não é tão difícil. Basicamente, se você implementar a maioria das opções que o uwsgi tem, está no caminho certo. Está no roadmap tornar o Rwf comparável a executar com Gunicorn
A escolha do nome é realmente impressionante. É uma forma de aparecer no topo dos resultados de busca :P
Falando sério, ficou bem feito. Criar um bom framework é um trabalho surpreendentemente grande, e é sempre bom ver pessoas explorando o espaço de design e testando novas ideias
rwfRustOnWeb.com também pode ser comprado por US$ 10 :) só comentando
Gostei da expressão “pense em Rails, não em Flask”. Linguagens de tipagem estática precisam ter mais, ou melhores, frameworks opinionated como Rails/Django
Ficou bem feito. Vale tentar fazer com que seja apresentado em https://www.arewewebyet.org/
Legal! Um Django/Rails feito em uma linguagem de primeira linha
Como sugestão, talvez
async-traitjá tenha sido estabilizado, então a macro pode não ser mais necessária; e seria bom adicionar uma integração com OpenTelemetry para obter métricas e tracing por padrão. Para targets Linux, também seria bom usar jemallocPretendo adicionar tags do OpenTelemetry às funções do crate
tracing. O jemalloc pode ser adicionado ao app binário que usa Rwf e não precisa entrar como dependência de biblioteca[1] https://blog.rust-lang.org/2023/12/21/async-fn-rpit-in-trait...
Tentei aprender Rust, mas desisti logo no começo. Vindo de C#, C/C++, Java e Python, Rust me pareceu estranho
O que me derrubou não foi a estranheza em si, mas o fato de a velocidade para concluir uma tarefa ser menor do que em linguagens como C#, Java e Python
Hoje em dia faço principalmente desenvolvimento web, então facilidade de uso e produtividade são prioridade máxima. Rust pode ser um pouco melhor em throughput e velocidade, mas, olhando benchmarks modernos de frameworks web, C# e Java também se saem muito bem nesse aspecto
Espero que isso não seja lido como crítica ao Rust nem como uma forma de diminuir a grande conquista de criar um framework MVC do zero. Está mais para “a ferramenta certa para o trabalho”
Para superar a curva de aprendizado, é preciso uma motivação forte. Pode ser porque você precisa usar a linguagem, porque se sente atraído pelo sistema de tipos e pelos benefícios de segurança, ou por algum motivo concreto próprio
Se você não tem essa motivação, tudo bem. Eu também não tinha no início, e por isso minhas primeiras tentativas de aprendizado não foram muito longe. Como muita gente sente, Rust leva mais tempo do que Java ou Python para terminar as coisas e exige pensar mais antecipadamente. Em certas situações isso vale a pena, mas, se não estiver claro por que aceitar esse trade-off, não há um motivo forte para continuar
Recentemente abandonei o loader JS do webpack e passei a usar um loader em Rust 50 vezes mais rápido, e eu também me apaixonei por Rust. Rust tem um grande impacto em ganhos de desempenho e, hoje, C++ e Rust são minhas linguagens favoritas
Avaliei todos os candidatos comumente mencionados para trabalho de backend em Rust e fiz pequenos protótipos. Até agora, embora seja de nível mais baixo do que eu gostaria, acabei concordando, a contragosto, com a conclusão coletiva de que Axum é a melhor opção no geral
Os outros candidatos eram Loco e Rocket. O Loco era parecido demais com Rails, e, no Rocket, as macros só começaram a me incomodar depois de eu ter usado mais Rust
Este framework parece se encaixar perfeitamente no meu critério de “baterias incluídas, mas não prescritivo demais”. É uma boa adição ao ecossistema