Yarn

No dia 11/10 o Facebook anunciou o lançamento do Yarn, um novo gestor de pacotes para o NodeJS. Até então utilizávamos o NPM para esse trabalho, mas se já temos o NPM por que precisamos do Yarn? Por que ele foi criado? Devo parar de usar o NPM para usar o Yarn? Vou tentar responder essas perguntas.

Primeiro vamos entender o que ele é: o Yarn substitui o cliente do NPM, mas pode ser usado junto com ele. Se você trabalha em uma equipe e seu colega usa o NPM ele pode continuar usando e você pode ir para o Yarn, pois ambos usam o arquivo package.json. A principal diferença é que o Yarn gera um arquivo chamado yarn.lock que iremos analisar logo mais.

A ideia do Yarn é melhorar o tempo de download dos pacotes, pois o NPM é conhecido por ser lento nas restaurações das dependências e inclusive sendo possível resolver dependências sem o uso da internet usando o cache local.

Como exemplo semana passada baixei o código do site do setup.loopinfinito.com.br que é um site estático que usa o docpad para a geração dos HTMLs, uma coisa bem simples, quando rodei um npm install demorou 5 minutos para realizar todo o trabalho, muito tempo na minha opinião. Acredito que esse é um desafio que o Yarn puxou para melhorar, mas que ele ainda não resolve, apenas melhora.

No site do Yarn tem alguns números mostrando como ele é rápido, mas como eu não costumo acreditar nesses números, preferi fazer o meu teste.

O teste

Como estou no Mac fiz um script bash (não conheço muito, por isso foi o escolhido queria para aprender um pouco, está bem básico), para realizar os testes utilizei um pacote do node chamado gnomon, ele me ajuda na coleta do tempo, você pode ver o script aqui, fico feliz se você mandar um pull-request melhorando ele :).

Vamos ver os resultados:

Cenários usando o node version 6.7.0 NPM Yarn
1 – Sem cache, sem node_modules e sem o arquivo Lockfile/Shrinkwrap 110s 47s
2 – Sem cache, sem node_modules com o arquivo Lockfile/Shrinkwrap 108s 46s
3 – Sem cache, com node_modules e sem o arquivo Lockfile/Shrinkwrap 2s 51s
4 – Sem cache, com node_modules com o arquivo Lockfile/Shrinkwrap 81s 0.2s

Como podemos ver acima, o Yarn é mais rápido em quase todos os cenários, o único em que ele perde é um cenário que não acontece se o utilizarmos corretamente, pois sempre o yarn.lock será gerado e por isso o cenário 3 não acontece de fato, sendo mais real a comparação do resultado do cenário 3 do npm com o cenário 4 do Yarn, o que faria o Yarn ganhar também.

Instalação e uso

Vamos começar pela instalação, veja nessa página como instalar no seu sistema, eu instalei pelo NPM: npm install -g yarn

Preferi instalar pelo npm porque uso o nvm no mac, portanto quando tento instalar com o brew ele irá verificar se tenho a formula do node instalado, ele não vai achar e vai querer instalar o node pelo brew, o que não quero.

Para facilitar vou criar uma tabelinha para ajudar na migração do NPM para o Yarn, a maioria dos comandos são os mesmos, só listei os principais comandos para o dia a dia de desenvolvimento.

NPM Yarn
npm init yarn init
npm link yarn link
npm outdated yarn outdated
npm run yarn run
npm cache clean yarn cache clean
npm install yarn
npm install jquery –save yarn add jquery
npm shrinkwrap yarn generate-lock-entry (por padrão ele já gera o yarn.lock)

Existem algumas diferenças, vamos ver quais são elas:

yarn licenses [ls|generate-disclaimer]

Esse comando até agora não tem nenhum equivalente no NPM, a ideia dele é bem interessante, o yarn licenses ls lista todas as licenças dos pacotes que estão instalados, enquanto o yarn licenses generate-disclaimer gerará um “disclaimer” contendo todos os “disclaimers” de todos os pacotes instalados.

yarn upgrade

Esse comando seria o equivalente a fazer rm -rf node_modules && npm install, ele irá atualizar os pacotes para a última versão conforme as regras estabelecidas no package.json. Não confunda com o npm update que irá atualizar o pacote para a última versão, alterando inclusive o package.json.

yarn why

Esse comando serve para sabermos o porque uma dependência está instalada, é uma mão na roda para saber porque aquele pacotes está no seu projeto.

Usando o yarn why

O yarn.lock file

A estratégia do Yarn é diferente do NPM, a cada adição de um pacote ele cria ou altera o arquivo yarn.lock que guarda a versão exata que esta sendo utilizada, e esse arquivo é usado para fazer a instalação do pacote de acordo com a versão específica utilizada no projeto, garantindo assim que quando você rodar o instalador de pacotes a versão correta seja instalada. A equipe do Yarn (e eu) recomenda que você coloque esse arquivo no seu source control, isso garantirá que todos os membros do time usem a mesma versão.

Da forma que o NPM faz atualmente podemos ter o mesmo package.json em duas máquinas diferentes e ao executarmos o npm install obter pacotes com versões diferentes entre essas máquinas, isso pode introduzir bugs no sistema.

O NPM tem uma função que faz a mesma coisa, o npm shrinkwrap cria o arquivo npm-shrinkwrap.json que é o equivalente ao yarn.lock, só que diferente do Yarn no NPM isso não é automático, você precisa explicitamente rodar o comando.

Como funciona?

Vamos entender como o Yarn trabalha internamente, ele tem 3 fases de processamento:

  1. Resolution: onde ele realiza a resolução de dependências fazendo requisições para o registro e recursivamente navegando por elas
  2. Fetching: Yarn procura no seu cache para verificar se o pacote já não foi baixado, se não existir lá ele vai fazer o download do pacote (tarball file) e colocar no cache, dessa forma ele só usara a internet se o pacote não existir no cache,
  3. Linking: Yarn copia os arquivos dos pacotes do global cache para o diretório node_modules local.

Devo parar de usar o NPM para usar o Yarn?

Eu estou usando no meu dia a dia, nesse pequeno período de tempo não tive nenhum problema, ele é mais rápido, então sendo curto e grosso a resposta é: sim.

Mas fica uma pergunta no ar: será que é bom para o ecossistema do node ter mais um cliente de gerenciamento de pacotes?

Essa pergunta vou deixar para outro post, mas gostaria de saber a opinião de vocês. O que vocês acham?