Executando verificação de segurança...
4
GkIgor
5 min de leitura ·

Passou da hora de migrar scripts em Node para GO

Durante esses últimos anos, o Node virou a escolha padrão para scripts e ferramentas de linha de comando (substituindo Python e Bash). É conveniente, todo mundo já tem npm instalado e todo mundo sabe programar em Javascript, o que traz muitos contribuidores para o projeto.

Node carrega uma runtime inteira para executar coisas que muitas vezes, poderiam ser só um binário simples. Tempo de inicialização maior, consumo de memória alto e dependência de ambiente configurado corretamente. Em projeto pequeno isso passa despercebido. Em CI rodando dezenas de vezes por dia, não.

Opinião pessoa: Linguagem interpretada (JS, Java) não deveria ser usada para criar scripts CLI ou automações

Não é coincidência que ferramentas focadas em performance tenham ido por outro caminho. O esbuild é escrito em Go e usa concorrência para processar arquivos em paralelo, Pulumi, mesmo permitindo múltiplas linguagens na camada de uso, mantém sua engine principal em Go para garantir previsibilidade e leveza.

Outro ponto ignorado com frequência é portabilidade. Um script em Node depende da versão correta do Node instalada (as vezes não). Já um programa em Go vira um único executável. Você compila para a arquitetura desejada e acabou. Sem runtime externa, sem gerenciador de pacotes, sem surpresas (dependência circular).

Ferramentas que já estão no limite

Algumas ferramentas do ecossistema frontend claramente já estão sofrendo com o peso da escolha original.

Angular Language Service
Ele roda junto com o editor, analisando templates e tipos em tempo real. É pesado, consome memória e impacta a experiência do desenvolvedor em projetos grandes. Uma engine escrita em Go poderia manter a análise estática com menor consumo e melhor tempo de resposta.

Experiencia própria, o lsp do Angular é incrível, mas terrivelmente pesado. Quando eu tinha apenas 8Gb e usava Windows + wsl, esse peso me atrapalhava.

ESLint
Lint é basicamente análise de AST em larga escala. Em projetos grandes, rodar ESLint pode virar um gargalo real na pipeline. Um motor em Go, compilado e concorrente, poderia reduzir drasticamente o tempo de execução. esbuild é bastante eficiente, e isso prova meu ponto

Prettier
Formatação é processamento puro de texto e AST. Não precisa de runtime dinâmica nem de ambiente complexo. Um formatter compilado tende a inicializar mais rápido e executar com menos overhead.

Spell-checker de código e documentação
Ferramentas de correção ortográfica que rodam em CI ou no editor analisam grandes volumes de texto. É I/O e processamento simples. Perfeito para um binário leve, portátil e rápido (GO e Rust seriam perfeitos para essas ferramentas)
Esses casos têm algo em comum: são ferramentas de sistema, não aplicações web. Não precisam de uma runtime JavaScript completa para existir.

Concorrência sem contorcionismo

O modelo de event loop do Node funciona muito bem para aplicações web. Mas para ferramentas que precisam paralelizar processamento de arquivos, chamadas de rede ou tarefas intensas de I/O, a abordagem de goroutines em Go é mais direta. Não exige arquitetura pensada para contornar limitações do runtime.
E tem a tipagem. Em Go ela é parte da linguagem e validada em tempo de compilação. Não é uma camada adicional. O erro aparece antes de virar problema em produção.

Conclusao

Node continua excelente onde nasceu para brilhar: backend web orientado a I/O.
Mas para ferramentas locais, análise estática, formatação, linting e automação pesada, carregar uma runtime inteira começa a parecer excesso.
Infelizmente, o JIT do Node não é suficiente para otimizar recursão em leitura de arquivos que mudam o tempo todo.

Eu como um dev mais experiente, tenho um tempo de digitação muito acelerado, então o debounce de algumas ferramentas mantém a folga do analisador, mas durante minhas pausas para renomear variáveis, fazer micro alterações enquanto penso na lógica, o analisador vai rodar e ficar acusando erros, ai um overhead começa a acontecer e aí começa o ciclo: CPU sobe, memória sobe, a IDE engasga, o build roda de novo.

O ponto aqui, são ferramentas de desenvolvimento, que TODAS elas são absurdamente pesada, desde o vscode até o build. E sinceramente, as vezes a integração de múltiplas ferramentas é a formula do comedor de recursos.

O problema não é uma ferramenta isolada, era o conjunto.

VSCode.
Language Server.
Spell checker.
ESLint.
Prettier.
Auto-fix.
Build em watch.
Backend rodando.
Frontend rodando.
Docker com banco e Redis.
Túnel externo aberto.

Por exemplo, em 2024, eu costumava usar auto-save do vscode, Code Spell Checker, Angular Language Server, Eslit, Prettier, etc.
Meu vscode era configurado para formatar o código, fazer auto fix e ao mesmo tempo, eu tinha o build em modo watch rodando no terminal, back, front e Docker com Redis + DB (as vezes tinha ngrok rodando junto).

Chegou uma hora que eu pensei, "Porque diabos eu uso essas coisas? Por que eu preciso de tanta coisa para escrever código?".
E assim, eu removi todas essas coisas, fiquei só com o essencial. Comecei a usar apenas o padrão, docker + eslint e o servidor local, build manual e menos watchers, e a diferença foi gritante.

Curiosamente, isso só era um problema real nos projetos em JavaScript. Em C++, Dart ou Go, análise, formatação e build raramente passavam de alguns segundos. O ambiente parecia mais leve, mais previsível.
Quando voltei a usar o Biome, ficou evidente que o problema não era o conceito das ferramentas, era a runtime (Node).

Opinião pessoal: Talvez o futuro das ferramentas de desenvolvimento não esteja em mais abstração sobre JavaScript, mas em menos runtime e mais binário. Porque no final do dia, a melhor ferramenta é aquela que trabalha em silêncio enquanto você pensa.

Porque GO?

Ferramentas deveriam migrar para Go porque elas não são aplicações web, são infraestrutura de desenvolvimento. Elas precisam iniciar rápido, consumir pouca memória, rodar de forma previsível e funcionar em qualquer ambiente sem depender de uma runtime externa. Go entrega binário único, concorrência simples, tipagem nativa e performance consistente. Para esse tipo de problema, ele não é uma alternativa estilística. Ele é tecnicamente mais adequado (na minha opinião).

Além disso, Go é uma linguagem pensada para times grandes manterem código por anos. A linguagem é pequena, a sintaxe é direta e a padronização é forte. Isso reduz bikeshedding, reduz complexidade acidental e facilita onboarding de novos contribuidores. Em ferramentas que viram padrão de mercado, previsibilidade de código importa tanto quanto performance.

A manutenção também tende a ser mais simples. Sem camadas de abstração excessivas, sem dependências profundas e sem ecossistema fragmentado de plugins e loaders competindo entre si. O resultado é menos acoplamento implícito e menos efeito cascata quando algo muda.
Migrar não é trivial, mas também não é impossível. O TypeScript mostrou isso ao reescrever partes críticas do compilador para ganhar desempenho significativo. Quando o gargalo está claro e o custo operacional é alto, reescrever o núcleo em uma linguagem mais adequada deixa de ser radical.

Opinião pessoal: Ferramentas de desenvolvimento criada por desenvolvedores para desenvolvedores, não devem nunca ficarem presas ao mesmo ecossistema. Estamos na era da IA, a tecnologia está evoluindo em um ritmo humanamente impossível de acompanhar!

Carregando publicação patrocinada...
2

Eu comecei a migrar ferramentas locais em node e em python para GoLang. Ainda tem algumas coisas que preciso dar mais atenção, mas na maioria das coisas que uso que troquei para GoLang foi uma maravilha.

Não tem que rodar npm install, pasta node_modules gigante, ou par o Python com o pip install e ativar o ambimente virtual (venv).

É arquivo único, é fácil de distribuir ou transportar (para outros lugares).