O guia completo do package.json do Node.js

NPM
NPM

O package.json é um elemento-chave em muitas aplicações do ecossistema Node.js. Se você trabalha com JavaScript, ou se você já interagiu com um projeto JavaScript antes, Node.js ou front-end, você certamente já se deparou com um arquivo package.json.

Para quê ele serve?

O que você deveria saber sobre ele e que coisas legais pode fazer com ele?

O package.json é uma espécie de manifesto do seu projeto. Ele pode fazer várias coisas, completamente não relacionadas. Ele é um repositório central de configurações de ferramentas, por exemplo. Ele também é onde npm e yarn armazenam os nomes e versões dos pacotes instalados.

Neste artigo você vai ver:

Vamos lá!

A estrutura do arquivo

Aqui temos um exemplo de arquivo package.json válido:

Está vazio Não existem exigências fixas do que deve estar em um arquivo package.json para uma aplicação. O único requisito é que ele respeite o formato JSON, de outra maneira ele não poderá ser lido pelos programas que tentarem acessar suas propriedades programaticamente. Se você está construindo um pacote Node.js que você quer distribuir através do npm, as coisas mudam radicalmente e você deve ter um conjunto de propriedades que ajudem outras pessoas a usá-lo. Veremos mais sobre isso mais tarde. Este é outro package.json válido:

Ele define uma propriedade name, que diz o nome da aplicação ou pacote, que está contido na mesma pasta onde o arquivo vive. Aqui temos um exemplo muito mais complexo, o qual eu extraí de uma aplicação Vue.js de exemplo:

Existem muitas coisas acontecendo aqui:

  • name define o nome da aplicação ou pacote;
  • version indica a versão atual;
  • description é um resumo da sua aplicação/pacote;
  • main define o ponto de entrada da aplicação;
  • private (true) previne a sua aplicação de ser publicada acidentalmente no npm;
  • scripts define um conjunto de scripts Node para você executar;
  • dependencies define uma lista de pacotes npm instalados como dependências;
  • devDependencies define uma lista de pacotes npm instalados como dependências de desenvolvimento;
  • engines define quais versões de Node este pacote/aplicação funciona;
  • browserslist é usado para dizer quais browsers (e versões) você quer suportar;

Todas estas propriedades são usadas tanto pelo npm quanto por outras ferramentas que podemos usar.

Detalhando as propriedades

Esta seção descreve as propriedades que você pode usar em detalhes. Eu refiro várias vezes a pacote, mas a mesma coisa se aplica a aplicações locais que você não use como pacote. A maioria destas propriedades são usadas somente no site do npm. Outras são usadas por scripts que interagem com seu código, como npm ou outros. name Define o nome do pacote. Ex:

O nome deve ser menor que 214 caracteres, não pode ter espaços e somente pode conter letras minúsculas, hífens (-) ou underscore (_).

Isto tudo porque quando um pacote é publicado no npm, ele ganha sua URL baseado nesta propriedade. Se você publicou este pacote publicamente no GitHub, um bom valor para esta propriedade é o nome do repositório. author Exibe o nome do autor do pacote. Ex:

Também pode ser usado neste formato:

contributors

Assim como o autor, o projeto pode ter um ou mais contribuidores. Esta propriedade é uma array que os lista:

Pode também ser ussado neste formato:

bugs

Links para o issue tracker do pacote, geralmente uma página de issues no GitHub. Ex:

homepage

Define a página inicial do pacote. Ex:

version

Indica a versão atual do pacote. Ex:

Esta propriedade segue a notação semântica de versionamento (semver), o que significa que a versão é sempre expressada com três números: x.x.x.

O primeiro número é a versão principal, o segundo é a versão secundária e o terceiro é a versão do patch.

Existe um significado nestes números: uma release que somente corrija bugs é uma release patch, uma release que introduza mudanças na compatibilidade retroativa é uma release secundária e uma release principal é aquela que pode quebrar compatibilidade.

license Indica a licença do pacote. Ex:

keywords Esta propriedade contém um array ou palavras-chave associados com o que seu pacote faz. Ex:

Isto ajuda as pessoas a encontrar o seu pacote quando estiverem procurando pacotes similares ou quando navegam pelo site do npm.

description

Esta propriedade contém um resumo do pacote. Ex:

Isto é especialmente útil se você decidir publicar seu pacote para o npm, visando que outras pessoas possam descobrir o que este pacote faz.

repository Esta propriedade especifica onde o repositório do pacote está localizado. Ex:

Note o prefixo github. Existem outros serviços populares também:

Você pode explicitamente definir o controle de versão do sistema:

Você também pode usar diferentes sistemas de controle de versão:

main Define o ponto de entrada do pacote. Quando você importa este pacote em uma aplicação, é essa aplicação que a aplicação irá buscar pelo module.exports. Ex:

private Se definido como true, previne que a aplicação/pacote seja acidentalmente publicada no npm. Ex:

scripts Define um conjunto de scripts node que você pode executar. Ex:

Estes scripts são aplicações de linha de comando. Você pode rodá-los usando npm run XXXX ou yarn XXXX, onde XXXX é o nome do comando. Ex:

Você pode usar qualquer nome que você quiser para um comando, e os scripts podem ser literalmente qualquer coisa que você quiser.

dependencies

Define uma lista de pacotes npm instalados como dependências. Quando você instalar um pacote usando npm ou yarn:

o pacote será automaticamente inserido nesta lista. Exemplo:

devDependencies

Define uma lista de pacotes npm instalados como dependências de desenvolvimento. Eles diferem de dependencies porque eles serão instalados somente em máquinas de desenvolvimento, não necessárias para executar o código em produção.

Quando você instalar um pacote usando npm ou yarn:

o pacote será automaticamente inserido nessa lista. Exemplo:

engines

Define quais versões de Node.js e outros comandos que este pacote ou aplicação suporta. Exemplo:

browserslist

É usado para dizer quais browsers (e suas versões) você quer suportar. Ele é referenciado pelo Babel, Autoprefixer, e outras ferramentas, para somente adicionar os polyfills e fallbacks necessários aos navegadores-alvo. Exemplo:

Esta configuração significa que você quer suportar ao menos as duas versões principais de todos os browsers com ao menos 1% de uso no mercado (as estatísticas são do CanIUse.com ), exceto IE8 e inferiores (saiba mais no browserslist do NPM).

Comandos específicos de propriedades

O arquivo package.json também pode hospedar configurações de comandos específicos, por exemplo Babel, ESLint, e muito mais.

Cada um possui uma propriedade específica, como eslintConfigbabel e outros. Estes são comandos específicos e você pode encontrar como usá-los na documentação do respectivo comando ou projeto.

Versões de Pacote

Eu já falei sobre isso extensivamente neste artigo aqui.

O arquivo package-lock.json

Na versão 5 o NPM introduziu o arquivo package-lock.json, que é automaticamente gerado quando você instala pacotes Node.

O que ele faz? Você provavelmente sabe tudo sobre o arquivo package.json a essa altura, o que é bem mais comum e está aí há bem mais tempo.

O objetivo deste arquivo é manter registro das versões exatas de cada pacote que é instalado para que um produto possa ser 100% reproduzível da mesma maneira mesmo se os pacotes forem atualizados por seus mantenedores.

Isto soluciona um problema bem específico que o package.json não resolvia. No package.json você pode definir quais versões você quer atualizar, usando a notação semver, por exemplo:

  • se você escrever ~0.13.0, você quer somente atualizar patch releases: 0.13.1 está ok, mas 0.14.0 não.
  • se você escrever ^0.13.0, você quer atualizar patches e minor releases: 0.13.10.14.0 e assim por diante.
  • se você escrevere 0.13.0, você somente usará esta versão exata do pacote.

Você não commita no Git a sua pasta node_modules, uma vez que ela é geralmente muito grande, e quando você tenta replicar o projeto em outra máquina usando o comando npm install, se você especificar a sintaxe ~ e uma patch release de um pacote tiver sido lançada, ela será instalada. O mesmo para  ^ e minor releases.

Se você especificar as versões exatas, como 0.13.0 neste exemplo, você não sofre desse problema.

Além poder ser um problema para você, pode ser um problema para outra pessoa qualquer querendo rodar o seu projeto com npm install, podendo acontecer do seu projeto original ficar diferente da nova instalação. Isto implica obviamente em possíveis bugs, mesmo que seja um patch ou minor release.

O arquivo package-lock.json define as versões instaladas de cada pacote de maneira irreversível e o npm usará exatamente estas versões quando você rodar npm install.

Este conceito não é novo e outros gerenciadores de pacotes de linguagens de programação (como o Composer do PHP) usam um sistema semelhante por anos.

O arquivo package-lock.json precisa ser commitado no Git para que possa ser baixado por outras pessoas. E se precisar atualizar as versões das dependências no package-lock.json, basta rodar npm update.

Espero que este artigo tenha sido útil para você que está aprendendo Node.js Para conteúdo mais aprofundado, recomendo meus livros. Para videoaulas, recomendo o meu curso online.

Curso Node.js e MongoDB
Curso Node.js e MongoDB

A Fórmula do Lançamento – Resenha

Atualizado em 20/08/2019!

A Fórmula do Lançamento é o nome do livro mais famoso (e único?) de Jeff Walker, um empreendedor (assim como eu) americano que é o sinônimo do que é viver um lifestyle business. Launch, em inglês, ainda tem o subtítulo “As estratégias secretas para vender online, criar um negócio de sucesso e viver a vida dos seus sonhos” e, embora o título soe muito “charlatão”, o livro é incrível.

O primeiro ponto que geralmente é uma barreira para as pessoas conhecerem o trabalho de Jeff Walker, autor da Product Launch Formula, é o idioma. Como o livro (e o curso original) existe somente em inglês, isso distancia muitos empreendedores (ou aspirantes a empreendedores) brasileiros de conhecerem seu trabalho. Um dos motivos do livro nunca ter sido traduzido e pelo qual eu descobri a existência de Jeff Walker é o curso Fórmula de Lançamento do Erico Rocha, versão tropicalizada do original e que o Erico detém os direitos autorais no Brasil. O livro não substitui os cursos originais, tanto o do Jeff quanto o do Eric, mas te dá muitos insights interessantíssimos e dicas práticas de como lançar produtos digitais.

Basicamente ele começa com Jeff fazendo o storytelling de sua vida enquanto funcionário até se tornar empreendedor, o que cria uma empatia muito grande com a maioria dos leitores. Na sequência, ele começa a falar da psicologia por trás da Product Launch Formula e porque ela funciona. Ele segue explicando a referida fórmula e dizendo o passo-a-passo de como ativar os gatilhos mentais ensinados por ele no capítulo anterior para alcançar seus objetivos de vendas, bem como as ferramentas necessárias para tanto.

As poucas críticas que o livro tem são referentes ao livro não falar de como construir seu produto especificamente, ele foca-se no lançamento do mesmo. Assim, quem nunca empreendeu online fica “à deriva” sem saber como ter um produto em si, para que seja possível fazer um lançamento. No entanto, a didática é muito boa e ele inclusive pode ser utilizado para validar ideias de produtos, como mostrado no post do Noah Kagan.

Ainda não consegui aplicar tudo o que aprendi com o livro em meus negócios digitais, mas corroborou algumas coisas nas quais acreditava e o conhecimento já foi utilizado por mim em mais de uma ocasião. Na verdade estou no aguardo de ter um produto digital que realmente valha um lançamento no melhor estilo Jeff Walker!

E você, leu algum outro livro de empreendedorismo recentemente que gostaria de compartilhar?

Como criar uma Definição de Pronto que funciona?

done

Atualizado em 11/07/19!

Uma Definição de Pronto (Definition of Done, no original) é um artefato Scrum usado para garantir a qualidade do produto desenvolvido a cada iteração (Sprint). Um documento, um contrato entre os membros do Time Scrum e demais envolvidos para que todos entendam o que um produto “pronto” (done) significa.

Mas como criar uma definição de pronto que realmente funcione, que não seja apenas uma burocracia sem sentido no meio de um processo de desenvolvimento que deveria ser ágil?

Vou mostrar algumas ideias aqui no artigo!

Depois, se quiser conhecer mais do meu trabalho com Scrum, dê uma olhada em meu livro sobre o assunto. E se preferir assistir a um vídeo ao invés de ler o artigo, confira abaixo uma amostra gratuita do meu curso online de Scrum e Métodos Ágeis:

Basicamente a definição de pronto é o documento que define o que é considerado, para todos envolvidos no projeto, o que “pronto” (done) significa.

Quais são os requisitos para arrastar um card para a coluna DONE do Kanban? Se um desenvolvedor diz que algo está pronto, o que isso significa? O que o Product Owner espera ver, em termos gerais, durante a Sprint Review?

Essas são algumas perguntas que podem nortear a construção deste documento, que geralmente e um checklist de coisas a serem realizadas/verificada, antes de uma tarefa ser dada como pronta e, como manda o pilar da transparência do Scrum, deve ser visível e conhecido por todos do time. Dica: coloque ao lado do Kanban.

Documento colaborativo

Um primeiro ponto a se considerar é que a criação da definição de pronto deve ser realizada de maneira colaborativa, ou seja, por todos os membros do Time Scrum. Claro, alguns membros possuem mais direitos, e outros mais deveres, como o Time de Desenvolvimento, por exemplo, que será o principal encarregado de implantar os itens da definição de pronto na sua rotina de desenvolvimento. Já o Scrum Master deverá garantir e auxiliar o time na execução do que prega este documento, afinal, ele faz parte do processo Scrum e deve ser respeitado. E por fim, o Product Owner espera que todos os itens dados como prontos e entregues estejam dentro do padrão de qualidade acordado na definição de pronto.

Achou complicado? Não deveria, é mais simples do que parece.

Um bom começo é, durante a primeira Sprint Planning, o time definir a v1 da sua definição de pronto. Pense em uma folha A4 e comece com coisas simples como dizer que “todo item dado como pronto deve ter passado em testes unitários” e depois se aprofunde em itens mais “avançados” como testes de regressão, teste em pares, etc e até mesmo itens difíceis dependendo da disponibilidade do Time Scrum como “aprovar com o Product Owner”. Sim, é bem complicado deste último item ser factível pois geralmente o Product Owner não é (mas deveria ser) tão acessível quanto gostaríamos.

Como tudo no Scrum (pilares da inspeção e adaptação, lembra?), itere e melhore sua definição de pronto a cada Sprint. Pegue o que deu errado na Sprint Review (ela nunca sai 100% como foi planejado pelo Time de Desenvolvimento), aborde na Sprint Retrospective e aplique de maneira aperfeiçoada na próxima Sprint Planning. Comece simples e avance rapidamente. Lembre-se que a função deste artefato é garantir a qualidade, mas lembre-se também de se manter ágil. A dose certa de um e de outro é você que vai descobrir.

E por último, eu sugiro fazer na Sprint Planning pois dependendo dos itens colocados na sua definição de pronto, o tempo para que cada entrega fique pronta pode mudar drasticamente. Tenha a definição de pronto pronta antes de jogar Planning Poker, por exemplo.

Contrato moral

A definição de pronto é algo com o qual o time se compromete a cumprir para garantir a qualidade das entregas. Sendo assim, é um contrato moral. Moral porque estamos falando de pessoas e processos, não há um elemento de software envolvido, lhe cobrando diariamente que cumpra os requisitos do documento, embora o time possa optar por usar algum, como um dos itens da definição, mas nada a substitui.

Sendo um contrato moral e ao mesmo tempo algo colaborativo, o time terá de achar o checklist que agrade a todos, incluindo aqui o Product Owner, que é quem tem a palavra final sobre os itens do Backlog que o Time de Desenvolvimento está trabalhando. Jamais crie uma definição em que não há unanimidade dentro do Time pois caso contrário ela será sabotada, mais cedo ou mais tarde. Caso o time seja inexperiente, como Scrum Master “force” algumas regras pedindo um voto de confiança, explique que esse documento poderá ser alterado na próxima Sprint caso o Time não se adapte.

Mas principalmente: crie um documento que seja útil para garantir a qualidade das entregas que seja executável, exequível. É muito fácil cair na tentação de adicionar dezenas e dezenas de itens de qualidade que jamais serão empregados no projeto como “validar pessoalmente com o cliente final” seja porque não é prático, seja porque realmente e inviável (ex: cliente do outro lado do mundo). Se o Time optar por ferramentas, escolha o menor conjunto delas possível, caso contrário o tempo de desenvolvimento poderá ser enormemente afetado ou a definição enormemente sabotada.

E se você acha que seu Time não dará atenção a um contrato moral, que tipo de time você montou para executar o projeto?

Exemplos e Contra-exemplos

A seguir alguns exemplos de itens que já implementei em Times Scrum que eu liderei como Scrum Master e que sei que funcionam. Obviamente, alguns deles não funcionam dentro de realidades fora das que eu vivenciei, uma vez que a maioria das empresas que trabalhei desenvolviam software para si mesmas (cliente interno). Também obviamente não pegue todos e coloque na sua definição. Use-os como ideias, não tenho intenção alguma definir o que significa “pronto” para o SEU time de desenvolvimento.

Lembre-se que a definição de pronto deve ser clara e não permitir desculpas como “está pronto, só falta testar”…

Toda tarefa de software, para ser considerada pronta, deve…

Ter sido atualizado com o controle de versão e permanecer compilando;

Isto é o mínimo que se espera de algo dado como pronto. Em Times que usem versionamento de código (algum não usa?) o desenvolvedor, após concluir a codificação da tarefa, pegar a última versão do servidor, rodar seus testes (ver abaixo), fazer a fusão (merge) do que for necessário e garantir que, antes de enviar seu código amalgamado ao servidor, que tudo continua compilando. Ponto.

Contra-exemplo: cuidado com o envio de software inacabado (mesmo que algumas features individuais já estejam) para produção. Versionadores de código (como TFS, SVN, Git, etc) possuem recursos como branches e forks que permitem aos desenvolvedores manterem sempre uma versão de produção 100% operacional e livre de bugs enquanto trabalham em outra versão mais instável. Colocar na definição de pronto que o requisito de software desenvolvido esteja rodando em produção é muito perigoso.

Ter passado nos testes unitários com sucesso;

Se você ainda não usa Testes Unitários em sua equipe de desenvolvimento, deveria. A ideia aqui, basicamente, é que, se você testar cada uma das micro-partes que envolvem o seu software (unidades) isoladamente, a probabilidade de que o todo funcione é muito maior, ao mesmo tempo em que lhe obriga a manter um baixo acoplamento do seu software para que ele possa ser testado em micro-pedaços.

Contra-exemplo: colocar TDD na definição de pronto sem que o time tenha experiência com a metodologia. TDD é bem complicado e difícil de ser seguido à risca, mais do que o próprio Scrum.

Ter passado por testes de uso de outro colega da equipe;

Desenvolvedores tendem a ser os piores testadores do mundo quando o assunto é testar suas próprias criações. Certamente temos um gene defeituoso que faz com que auto-sabotemos os testes visando não encontrar bugs. Geralmente outro colega da equipe (chamado cross-testing ou peer-review), que não está preocupado com o trabalho que vai dar corrigir qualquer erro encontrado, é um testador melhor que o desenvolvedor original. E se isso não for suficiente para garantir a qualidade, em casos extremos mude para “teste de uso de quem vai usar a feature”, chamando para o teste de uso o próprio usuário da feature.

Ah, esse teste de uso deve ser em ambiente de homologação. Nada de chamar o colega ou o usuário final pra usar na tua máquina. Isso evita aquela famigerada frase: “na minha máquina funciona!”.

Contra-exemplo: teste de uso automatizado. Isso faz com que você perca a experiência da usabilidade do software. Podem existir testes automatizados, mas eles não devem substituir por completo os testes manuais quando o recurso envolver interface gráfica.

O código encontra-se dentro dos padrões da empresa;

É comum, embora não deveria, desenvolvermos uma v1 de qualquer funcionalidade de maneira meio…porca. O que não é “comum” é que essa v1 seja a versão “pronta” daquele requisito. Refatoração é a chave aqui. Garanta com esse item que o código passe por uma avaliação estrutural para ver se está 100% de acordo com as normas de desenvolvimento da empresa (ex. do Google). Obviamente para que isso funcione, estas normas também devem estar visíveis e serem de conhecimento geral do Time de Desenvolvimento.

Contra-exemplo: empresas que possuam normas de desenvolvimento muito particulares tendem a fracassar ao usar este item na definição de pronto. O que seria algo muito particular? Na minha opinião algo que foge aos padrões de codificações oficiais da linguagem/framework utilizados. Quando escrevo código em Java, uso os padrões da Oracle (Camel Case para métodos, por exemplo). Já quando escrevo código em C#, uso os padrões da Microsoft (Pascal Case para métodos, por exemplo). Isso facilita a vida para todos, inclusive novos funcionários e geralmente a resistência por adotar essa prática é culpa do ego dos veteranos da empresa.

Softwares de apoio e documentação atualizados;

Um último item na definição de pronto deve dar cabo de tarefas burocráticas e pouco interessantes, mas igualmente necessárias, como essas. Todo Time de Desenvolvimento usa algum software para controlar seu progresso (Trello, por exemplo). Mas para garantir que esse software mantenha sua utilidade, ele deve permanecer atualizado com o andamento do projeto e aqui o trabalho do Scrum Master deve ser bem forte, porque o time sempre se “esquece” de atualizar. Cobrar atualizações diárias, sempre antes da Daily Scrum, geralmente resolvem este problema, mesmo antes das tarefas serem dadas como pronto.

O mesmo vale para a documentação do projeto. Eu particularmente sempre gostei de Wikis internos por serem um formato de documentação viva, colaborativa e fácil de usar e manter. Obviamente tem empresas que preferem o bom e velho Word. Encontre o que funciona para você, mas garanta que um mínimo de documentação esteja sempre atualizada e visível, como diagramas da arquitetura, do banco de dados, de implantação, etc.

Contra-exemplo: tão nocivo quanto não ter documentação é tê-la em demasia, então tome cuidado com este item, caso contrário o time pode não se comprometer de verdade, gerando um comprometimento flácido.

Conclusão

Estas foram algumas ideias de como criar ou incrementar a sua definição de pronto. A combinação de uma definição de pronto clara, com objetivos e escopos definidos, tendem a garantir entregas consistentes e de qualidade, levando o projeto ao sucesso.

Associar a sua definição de pronto a acrônimos como DEEP, INVEST e SMART também pode ajudar bastante!

* OBS: curtiu o post? Então dá uma olhada no meu livro de Scrum e Métodos Ágeis e/ou no meu curso sobre o mesmo assunto!

Curso de Scrum e Métodos Ágeis
Curso de Scrum e Métodos Ágeis