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"]
}

muitas coisas rolando aqui:

  • version indica a versão atual
  • name define o nome da aplicação
  • description é uma breve descrição da aplicação
  • main define o ponto de entrada da aplicação
  • private se definido como true, previne da aplicação ser publicada acidentalmente no npm
  • scripts define alguns scripts node que você pode rodar na linha de comando
  • 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 em quais versões do Node.js essa aplicação funciona
  • browserslist é 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.

(veja mais sobre)

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.