O guia do package.json
Se você trabalha com JavaScript, ou já interagiu com um projeto JavaScript, Node.js ou um projeto frontend, você certamente conheceu o arquivo package.json
.
Pra que ele serve? O que você deveria saber sobre ele, e o quê de legal pode ser feito com ele?
O package.json
é uma espécie de manifesto do seu projeto. Ele pode fazer uma variedade de coisas, completamente não relacionadas. É um repositório central de configurações para ferramentas, por exemplo. Também é onde o npm
e o yarn
armazenam os nomes e versões de todos os pacotes instalados.
The file structure
Aqui temos um exemplo de arquivo package.json:
{}
Está vazio! Não há campos fixos obrigatórios do que pode ser colocado no arquivo package.json
, de uma aplicação. A única exigência é que respeite o formato JSON, caso contrário programas que tentem acessar as propriedades programaticamente não terão sucesso.
Se você está criando um pacote Node.js que precisa ser distribuido no npm
as coisas mudam radicalmente, e você necessita preencher algumas propriedades que vão ajudar outras pessoas a utilizar seu pacote. Vamos ver mais sobre isso em breve.
Esse é outro package.json:
{"name": "test-project"}
Ele define uma propriedade name
, que diz o nome da aplicação, ou pacote, que está contido na mesma pasta em que o arquivo reside.
Aqui temos outro exemplo muito mais complexo, que foi extraido de uma aplicação Vue.js:
{"name": "test-project","version": "1.0.0","description": "A Vue.js project","main": "src/main.js","private": true,"scripts": {"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js","start": "npm run dev","unit": "jest --config test/unit/jest.conf.js --coverage","test": "npm run unit","lint": "eslint --ext .js,.vue src test/unit","build": "node build/build.js"},"dependencies": {"vue": "^2.5.2"},"devDependencies": {"autoprefixer": "^7.1.2","babel-core": "^6.22.1","babel-eslint": "^8.2.1","babel-helper-vue-jsx-merge-props": "^2.0.3","babel-jest": "^21.0.2","babel-loader": "^7.1.1","babel-plugin-dynamic-import-node": "^1.2.0","babel-plugin-syntax-jsx": "^6.18.0","babel-plugin-transform-es2015-modules-commonjs": "^6.26.0","babel-plugin-transform-runtime": "^6.22.0","babel-plugin-transform-vue-jsx": "^3.5.0","babel-preset-env": "^1.3.2","babel-preset-stage-2": "^6.22.0","chalk": "^2.0.1","copy-webpack-plugin": "^4.0.1","css-loader": "^0.28.0","eslint": "^4.15.0","eslint-config-airbnb-base": "^11.3.0","eslint-friendly-formatter": "^3.0.0","eslint-import-resolver-webpack": "^0.8.3","eslint-loader": "^1.7.1","eslint-plugin-import": "^2.7.0","eslint-plugin-vue": "^4.0.0","extract-text-webpack-plugin": "^3.0.0","file-loader": "^1.1.4","friendly-errors-webpack-plugin": "^1.6.1","html-webpack-plugin": "^2.30.1","jest": "^22.0.4","jest-serializer-vue": "^0.3.0","node-notifier": "^5.1.2","optimize-css-assets-webpack-plugin": "^3.2.0","ora": "^1.2.0","portfinder": "^1.0.13","postcss-import": "^11.0.0","postcss-loader": "^2.0.8","postcss-url": "^7.2.1","rimraf": "^2.6.0","semver": "^5.3.0","shelljs": "^0.7.6","uglifyjs-webpack-plugin": "^1.1.1","url-loader": "^0.5.8","vue-jest": "^1.0.2","vue-loader": "^13.3.0","vue-style-loader": "^3.0.1","vue-template-compiler": "^2.5.2","webpack": "^3.6.0","webpack-bundle-analyzer": "^2.9.0","webpack-dev-server": "^2.9.1","webpack-merge": "^4.1.0"},"engines": {"node": ">= 6.0.0","npm": ">= 3.0.0"},"browserslist": ["> 1%", "last 2 versions", "not ie <= 8"]}
há muitas coisas rolando aqui:
version
indica a versão atualname
define o nome da aplicaçãodescription
é uma breve descrição da aplicaçãomain
define o ponto de entrada da aplicaçãoprivate
se definido comotrue
, previne da aplicação ser publicada acidentalmente nonpm
scripts
define alguns scripts node que você pode rodar na linha de comandodependencies
define uma lista de pacotesnpm
instalados como dependênciasdevDependencies
define uma lista de pacotesnpm
instalados como dependências de desenvolvimentoengines
define em quais versões do Node.js essa aplicação funcionabrowserslist
é usado para definir quais browsers (e suas versões) você quer dar suporte
Todas essas propriedades são usadas tanto pelo npm
quando outras ferramentas.
Separação de propriedades
Essa seção descreve as propriedades que você pode usar em detalhes. Nós nos referimos como "pacote" mas o mesmo se aplica à aplicações locais que você não utiliza como pacotes.
A maioria dessas propriedades são usadas apenas no https://www.npmjs.com/, outras por scripts que interagem com seu código, como o npm
ou outros.
name
Define o nome do pacote.
Exemplo:
"name": "test-project"
O nome deve ter menos de 214 caracteres, não pode ter espaços, apenas letras minúsculas, hífens (-
) ou underlines (_
).
Isso ocorre porque quando um pacote é publicado no npm
, ele ganha sua própria URL baseada nessa propriedade.
Se você publicou esse pacote no GitHub, é uma boa definir essa propriedade com o nome do repositório no GitHub.
author
Lista o nome do autor do pacote
Exemplo:
{"author": "Joe <pauloluan@whatever.com> (https://whatever.com)"}
Também pode ser usado com esse formato:
{"author": {"name": "Joe","email": "pauloluan@whatever.com","url": "https://whatever.com"}}
contributors
Assim como o autor, o projeto pode ter muitos contribuidores. Essa propriedade é um array que os lista.
Exemplo:
{"contributors": ["Joe <pauloluan@whatever.com> (https://whatever.com)"]}
Também pode ser usado com esse formato:
{"contributors": [{"name": "Joe","email": "pauloluan@whatever.com","url": "https://whatever.com"}]}
bugs
Link para o rastreador de issues do pacote, geralmente uma página de issues do GitHub
Exemplo:
{"bugs": "https://github.com/whatever/package/issues"}
homepage
Define a página inicial do site do pacote
Exemplo:
{"homepage": "https://whatever.com/package"}
version
Indica a versão atual do pacote.
Exemplo:
"version": "1.0.0"
Essa propriedade segue o padrão de notação de versionamento semântico chamado semver, o que significa que é sempre expresso com 3 números: x.x.x
.
O primeiro número é sempre a versão major, o segundo a versão minor e o terceiro a versão patch.
Há um significado nesses números: uma versão que só corrige bugs é uma versão patch, uma versão que introduz mudanças compatíveis com versões anteriores é uma versão minor, uma versão major pode conter quebra de comportamentos com versões antigas.
license
Indica a licença do pacote.
Exemplo:
"license": "MIT"
keywords
Esse propriedade contêm um array de palavras chave que são associadas a o quê esse projeto faz.
Exemplo:
"keywords": ["email","machine learning","ai"]
Isso ajuda pessoas a encontrarem seu pacote quando estiverem navegando por pacotes semelhantes, ou quando estiverem navegando no site https://www.npmjs.com/.
description
Essa propriedade contêm uma breve descrição do pacote
Exemplo:
"description": "Um pacote para trabalhar com strings"
Isso é útil especiaçmente se você decide publicar seu pacote no npm
, assim as pessoas podem encontrar sobre o quê se trata aquele pacote.
repository
Essa propriedade especifica onde o repositório desse pacote está localizado.
Exemplo:
"repository": "github:whatever/testing",
Note o prefixo github
. Também há outros serviçoes populares:
"repository": "gitlab:whatever/testing",
"repository": "bitbucket:whatever/testing",
Você pode explicitar o sistema de controle de versionamento:
"repository": {"type": "git","url": "https://github.com/whatever/testing.git"}
Você pode usar diferentes tipos de controle de versionamento:
"repository": {"type": "svn","url": "..."}
main
Define o ponto de entrada do pacote.
Quando você importa esse pacote em uma aplicação, é onde a aplicação vai procurar pelo module exports.
Exemplo:
"main": "src/main.js"
private
Se definido como true
, previne do pacote ser publicado acidentalmente no npm
Exemplo:
"private": true
scripts
Define um conjunto de scripts node que você pode executar
Exemplo:
"scripts": {"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js","start": "npm run dev","unit": "jest --config test/unit/jest.conf.js --coverage","test": "npm run unit","lint": "eslint --ext .js,.vue src test/unit","build": "node build/build.js"}
Esses scripts são aplicações de linha de comando. Você pode rodá-los usando npm run XXXX
ou yarn XXXX
, sendo XXXX
o nome do comando. Exemplo: npm run dev
.
Você pode usar o nome que quiser para o comando, e os scripts podem fazer qualquer coisa.
dependencies
Define uma lista de pacotes npm
instalados como dependências.
Quando você instala um pacote usando npm ou yarn:
npm install <PACKAGENAME>yarn add <PACKAGENAME>
esse pacote é inserido automaticamente nessa lista.
Exemplo:
"dependencies": {"vue": "^2.5.2"}
devDependencies
Define uma lista de pacotes npm
instalados como dependências de desenvolvimento.
Eles se diferem dos pacotes no dependencies
porque eles são instalados apenas em ambiente de desenvolvimento, não são necessários para rodar o código em produção.
Quando você instala um pacote usando npm ou yarn:
npm install --save-dev <PACKAGENAME>yarn add --dev <PACKAGENAME>
esse pacote é inserido automaticamente nessa lista.
Exemplo:
"devDependencies": {"autoprefixer": "^7.1.2","babel-core": "^6.22.1"}
engines
Define em quais versões do Node.js e outros comandos esse pacote opera
Exemplo:
"engines": {"node": ">= 6.0.0","npm": ">= 3.0.0","yarn": "^0.13.0"}
browserslist
É usado para definir quais browsers (e suas versões) você deseja dar suporte. É refenciado pelo Babel, Autoprefixer, e outras ferramentas, apenas para adicionar polyfills e fallbacks necessárias para o browser em questão.
Exemplo:
"browserslist": ["> 1%","last 2 versions","not ie <= 8"]
Essa configuração implica que você quer dar suporte paras as 2 últimas versões major de todos os browsers com pelo menos 1% de uso (das estatísticas do CanIUse.com), exceto IE8 ou anterior.
Propriedades específicas de comandos
O arquivo package.json
também pode conter configurações específicas de comandos, como por exemplo Babel, ESLint, e mais.
Cada um tem propriedades específicas, como eslintConfig
, babel
e outras. Você pode encontrar como utilizá-las em suas respectivas documentações.
Versões dos pacotes
Você viu nos exemplos acima números como esse: ~3.0.0
ou ^0.13.0
. O que eles significam, e quais outros especificadores de versão você pode usar?
O símbolo especifica quais atualizações seu pacote aceita, para aquela dependência.
Dado que ao usar semver (versionamento semântico) todas versões têm 3 dígitos, o primeiro sendo a versão major, o segundo a versão minor e o terceiro a versão patch, você tem essas regras.
Você pode combinar a maioria das versões em intervalos, como esse: 1.0.0 || >=1.1.0 <1.2.0
, para usar ou 1.0.0 ou uma versão maior ou igual que 1.1.0, mas menor que 1.2.0.