en
· 4 min de leitura

O custo escondido de cada dependência que você adiciona

A instalação é grátis. A árvore transitiva, o ritmo de upgrades, o peso no bundle e o risco de supply chain não são.

fullstackaudit

Uma dependência custa nada para instalar e alguma coisa todo mês para sempre. Essa segunda parte é a que ninguém orça, e é por isso que um projeto de dois anos tem 1.400 pacotes no lock file e ninguém consegue explicar o que um terço deles faz.

Eu audito árvores de dependência do jeito que audito bancos: lendo o que está de fato lá, não o que o time acha que está. Os resultados são os mesmos toda vez. Um punhado de pacotes fazendo trabalho de verdade, e centenas puxados por um utilitário que economizou vinte minutos de alguém.

O que você está comprando de fato

Quando você adiciona um pacote, compra a árvore transitiva dele. Uma única biblioteca de datas pode trazer quarenta pacotes. Cada um tem um mantenedor, um cronograma de releases, um conjunto de issues abertas e uma chance de ser comprometido. Seu projeto agora depende de todos eles, e seu scanner de segurança vai te lembrar disso toda semana.

Você compra o ritmo de upgrades dele. Um pacote que lança uma major com breaking changes todo ano vai te custar uma migração todo ano, e um pacote que não lança nada há três anos vai te custar um fork no dia em que quebrar em uma versão nova do Node.js.

Você compra o peso no bundle, se ele roda no navegador. Com Server Components a conta mudou: um pacote pesado importado só no servidor custa nada para o usuário, e o mesmo pacote importado de um Client Component custa um download a cada visitante. Eu confiro de que lado da fronteira cada dependência fica, porque mover um import para o outro lado pode valer mais do que qualquer tree shaking.

E você compra os tipos dele. Um pacote com definições de tipo escritas à mão e desatualizadas vai mentir para o seu compilador, e a mentira vai aparecer como erro em runtime no único lugar em que você confiou no tipo.

As perguntas antes de adicionar

Faço um conjunto fixo de perguntas antes de uma dependência nova entrar em um projeto pelo qual sou responsável, e faço em voz alta para que a resposta fique no pull request.

  • Trinta linhas de código nosso resolveriam isso, e a gente entenderia essas linhas daqui a dois anos?
  • Quantos pacotes ele traz, e quantos deles têm um único mantenedor?
  • Quando foi o último release, e quantas issues abertas mencionam crash ou problema de segurança?
  • Ele entrega os próprios tipos, e são gerados ou escritos à mão?
  • Roda no servidor, no cliente ou nos dois, e precisa de APIs do Node.js que quebram no edge?
  • Qual é a licença, e a licença do nosso produto permite?

A maioria dos pacotes falha na primeira pergunta. Os que passam geralmente fazem algo genuinamente difícil: criptografia, cálculo de datas e fusos, parsing de um formato com especificação. Esses valem o custo. Um helper que preenche uma string não vale.

Mantendo a árvore honesta

O lock file é commitado, sempre, e a instalação no CI usa o modo congelado que falha se o lock file e o manifesto discordam. Essa única configuração já evitou mais quebras surpresa do que qualquer outra que conheço.

Versões ficam presas a um intervalo que aceita patches e rejeita majors. Pull requests automáticos de upgrade rodam semanalmente, um pacote por PR, para que o que quebra o build seja identificável. Um upgrade em massa de quarenta pacotes que falha não te diz nada.

Uma vez por trimestre, rodo um relatório de pacotes instalados e não importados em lugar nenhum, e removo. Na maioria dos projetos essa lista não é curta. E rodo a ferramenta de auditoria, mas leio os resultados em vez de silenciá-los, porque uma vulnerabilidade em uma ferramenta de build só de desenvolvimento e uma na biblioteca de JWT não têm a mesma gravidade, diga o scanner o que disser.

A dependência que você esqueceu que tem

A dependência mais cara na maioria dos projetos não está no manifesto. É a API proprietária da plataforma de hospedagem, o SDK do provedor de pagamento que molda seu modelo de dados, o serviço de auth que é dono dos seus ids de usuário. Essas não aparecem em contagem de pacotes e são as mais difíceis de abandonar.

Trate do mesmo jeito. Embrulhe atrás de uma interface sua, mantenha a superfície pequena e saiba quanto custaria substituir antes de precisar. A instalação é grátis. A saída nunca é.