O Victor Cavalcante analisou o Yarn 7 meses atrás aqui no blog da Lambda3. Essa semana saiu o Node.js 8, que será o novo Node LTS, e saiu também o Npm 5, com diversas melhorias. Ao mesmo tempo, saíram várias versões novas do Yarn, ou seja, houve também uma grande evolução. Estava na hora de compará-los novamente.
Eu mesmo troquei pro Yarn uns meses atrás. Basicamente porque ele era mais rápido e mais consistente que o Npm, duas das funcionalidades que estão entre as mais alardeadas do Yarn. Com as novidades, fui testar, e foquei nesses dois pontos: velocidade e consistência.
Se você não sabe o que é o Yarn, leia o post do Victor pra se inteirar.
Estou com um projeto razoavelmente simples, de front-end, e achei que o projeto seria um bom candidato. O projeto tem cerca de 460 pacotes.
Desempenho
Pra começar, o desempenho. Aqui os tempos que eu obtive:
# | Cenários | Npm | Yarn | Observações |
---|---|---|---|---|
1 | Sem cache, 1a instalação, sem lock file | 115s | 99s | Início de projeto, máquina nova |
2 | Sem cache, 1a instalação, com lock file | 67s | 83s | Máquina nova, projeto recém clonado |
3 | Com cache, 1a instalação, sem lock file | 87s | 54s | Início de projeto, máquina antiga |
4 | Com cache, 1a instalação, com lock file | 58s | 43s | Máquina antiga, projeto recém clonado |
5 | Com cache, 2a instalação (com lock file) | 5s | 1s | Máquina antiga, projeto antigo sem modificações no package.json (cenário mais comum) |
6 | Com cache, instalando pacote faltante | 5s | 18s | Máquina e projeto antigos, sem modificações no package.json, com inconsistência no node_modules |
7 | Com cache, instalando pacote novo | s | s | Máquina e projeto antigos, package.json com nova dependência |
Os números foram bastante consistentes. Rodei várias vezes, sempre com os mesmos números, tanto Npm quanto Yarn. Estou em uma máquina Windows 10, em uma conexão de 100mbps. Usei o Npm 5.0.0, e o Yarn 0.24.6, ambos nas últimas versões estáveis.
Nos testes do Victor, 7 meses atrás, o Yarn sempre ganhava. Não é mais o caso. E, nos casos em que o Yarn ganha, a diferença não é mais tão grande.
Esse projeto específico tem 5 dependências que utilizam ou download de binários ou de compilação de fonte (normalmente C e C++), o que atrasa ainda mais. O Yarn ganha forte nesse caso, porque faz essas ações em paralelo, enquanto o Npm faz em série.
No cenário mais comum, que é um projeto em andamento, o Yarn é 5x mais rápido, mas em termos absolutos essa diferença não impacta muito, porque ambos são muito rápidos. Sim, o Yarn dá uma impressão de imediatismo, mas os 5 segundos do Npm não chegam a te jogar naquele mar de tédio onde você vai tomar um café, checar seu Twitter, ou algo do tipo, ele é também muito rápido.
O único cenário que o Npm ganhou foi onde não havia um cache (ou seja, é uma máquina nova, ou você começou a trabalhar com Node.js agora), em um projeto já existente. Quando o Yarn ganha seu cache ele fica muito mais rápido, algo que, pela pequena diferença com ou sem cache do Npm (ele só é ~50% mais rápido com o cache), tudo indica que o Npm não sabe aproveitar seu cache.
Consistência
Ambos mantiveram cerca de 460 pacotes, e mantiveram o número de pacotes constante entre as instalações.
No entanto, peguei uma diferença importante: o Yarn não é capaz de detectar quando há alguma inconsistência no seu node_modules. Por exemplo, removi o pacote “yargs”, e, ao rodar “npm install” o Npm atualizou o pacote, mas o Yarn, ao rodar “yarn”, não instalou o pacote faltante. O Npm levou apenas 5 segundos para recolocar o pacotes no lugar, praticamente o mesmo tempo que leva quando não há nada a fazer. Há um bug reportado no Github sobre isso, aproveite para contribuir o seu +1 por lá. A solução dada no próprio issue do Github é fazer a instalação com o “yarn install –check-files”, e, nesse caso, o desempenho do Yarn foi bem pior, levando mais do que o triplo do que o Npm para reparar o erro. É importante notar, no entanto, que esse é um cenário incomum, os pacotes do node_modules não devem desaparecer do nada.
Conclusão
Não consigo nesse momento dizer que algum dos dois ganhou.
Apesar do Yarn resolver um problema de fato, acho a fragmentação que ele traz ruim. O ideal seria que o Npm evoluísse, e isso finalmente está acontecendo, a concorrência fez o Npm se mexer. Com a evolução atual, além de diversas outras que vieram com o Npm 5, acredito que o Npm voltou a ficar usável. E o Npm vem com o Node.js, o que é uma vantagem. Ele está em todo build server, todos os membros do seu time já o tem instalado, isso sem dúvida é outra vantagem.
Com relação a desempenho, claramente o Yarn é vencedor, então, depende muito das suas prioridades. Se aquele mínima diferença no install é importante pra você, vale a pena ir pro Yarn.
Espero que pelo menos essa análise o ajude a decidir. De qualquer forma, o ideal é o time escolher uma e concordar em qual está usando, porque ambos possuem lock files diferentes, e se estes arquivos ficarem dessincronizados com o package.json isso vira um problema para o time, que, além de ter que manter 2 arquivos diferentes, perde os ganhos de desempenho.
Vocês estão usando o Yarn? Se sim, como tem sido pra vocês? Vão considerar voltar pro Npm, agora na versão 5? Fizeram os testes de vocês? Quais foram os resultados? Postem nos comentários para compararmos.
Giovanni Bassi
Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.