Rust e NodeJS: uma combinação poderosa
Resumo
Quando falamos de JavaScript, a primeira coisa que nos vem a cabeça é o desenvolvimento Web. Somado ao poder do NodeJS, temos uma ferramenta completa, capaz de de construir o FrontEnd e o BackEnd. Porém, conforme a tecnologia avança, a alta performance e a segurança vão se tornando cada vez mais requisitadas.
Que o JavaScript e o NodeJS são tecnologias muito poderosas, não podemos negar, afinal, estão entre as queridinhas da comunidade de desenvolvimento. Contudo, assim como todas as tecnologias, elas tem seus prós e contras, ou seja, nem sempre serão as opções mais rápidas, seguras e performáticas.
Desenvolver funcionalidades que requerem alta performance é um desafio para qualquer programador, mas nem sempre precisamos nos limitar ao poder de uma só ferramenta. Vocês já ouviram falar sobre addons?
O que são addons
Explicando de uma forma muito simples e didática, addons são módulos escritos em C++ e Rust e que podem ser usados em conjunto com o NodeJS.
Por exemplo, vamos supor que a gente esteja desenvolvendo uma aplicação que tem uma funcionalidade que adiciona filtro em imagens. Depois de algumas pesquisas, descobrimos que o rust é muito mais rápido e performático para esse recurso do que o NodeJS.
O que fazemos? Simples! Podemos somar a força do NodeJS com a alta performance do rust, desenvolvendo um addon em rust para essa determinada funcionalidade e depois importando por meio do require, ou seja, construímos um módulo em rust que adiciona filtro as imagens e depois o importamos para o nosso código JavaScript.
Em conjunto com o C++, podemos:
- Acessar funcionalidades que não estão disponíveis no JavaScript,
- Interagir com o sistema operacional,
- Usar bibliotecas externas
- Construir recursos que requerem alta performance
- e etc.
Sobre o Rust
Rust é uma linguagem de programação de sistemas que é extremamente rápida e gerencia memória eficientemente. Ela não possui runtime ou garbage collector, o que permite potencializar a performance de serviços críticos, rodar em sistemas embarcados e facilmente integrar-se a outras linguagens.
O rico sistema de tipos de Rust e seu modelo de ownership garantem segurança de memória e segurança de concorrência, permitindo que você elimine muitas categorias de erros durante a compilação (inclusive, já escrevi sobre ownership e as suas regras de escopo)
Essas são regras do ownership (a característica mais impar da linguagem):
- Cada valor em Rust possui uma variável que é dita seu owner (sua dona).
- Pode apenas haver um owner por vez.
- Quando o owner sai fora de escopo, o valor será destruído
Obs. essas regras são verificadas em tempo de compilação e não implicam qualquer custo em tempo de execução.
Os benefícios de construir addons em rust nas suas aplicações NodeJS são muitos, tais como: melhoria no desempenho, confiabilidade, portabilidade e etc. É claro que não podemos esquecer que o NodeJS é uma ferramenta extremamente poderosa, então a necessidade depende do contexto e do seu objetivo.
Como desenvolver addons nativos
Existem duas principais ferramentas para quem quer desenvolver addons nativos para NodeJS em rust: o napi-rs e o node-rs. Para instalar é muito fácil, basta seguir os passos desse site:
Vejamos um exemplo simples de addons, nesta primeira estrutura nós temos um código em rust que retorna a soma de dois valores ("a" e "b").
//O objeto CallContext fornece acesso aos argumentos passados para a função.
fn add(ctx: CallContext) -> Result<JsNumber> {
let a = ctx.get::<JsNumber>(0)?.get_double()?; //primeiro argumento
let b = ctx.get::<JsNumber>(1)?.get_double()?; //segundo argumento
let sum = a + b; //a soma dos parâmetros
ctx.env.create_double(sum)
}
//função especial do Napi que inicializa o addon
fn init(mut exports: JsObject) -> Result<()> {
exports.create_named_method("add", add)?;
Ok(())
}
Agora vejamos como importar esse addon para o nosso arquivo JavaScript:
//importamos o addon por meio do require
const addon = require('./my-addon.node');
//e retornamos ele com o console.log
console.log(addon.add(2, 3)); // 5