O Victor Cavalcante fez uma análise sobre o Yarn no blog da Lambda3, há 7 meses. Recentemente 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 mudei 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.
***
Este artigo foi produzido em parceria com a Lambda3. Leia outros conteúdos no blog da empresa: blog.lambda3.com.br