Se você trabalha com JavaScript, ou já interagiu com um projeto JavaScript, Node.js ou um projeto frontend, com certeza conheceu o arquivo package.json
.
Para que serve? O que você deve saber sobre isso e quais são algumas das coisas legais que você pode fazer com ele?
O arquivo package.json
é uma espécie de manifesto para seu projeto. Ele pode fazer um monte de coisas, completamente não relacionadas. É um repositório central de configuração de ferramentas, por exemplo. É também onde npm
e yarn
armazenam os nomes e versões de todos os pacotes instalados.
Aqui um exemplo de um arquivo package.json
:
{}
Está vazio! Não há requisitos fixos do que deve estar em um arquivo package.json
, para um aplicativo. O único requisito é que respeite o formato JSON, caso contrário não poderá ser lido por programas que tentem acessar suas propriedades programaticamente.
Se você está construindo um pacote Node.js que deseja distribuir pelo npm
, as coisas mudam radicalmente, e você deve ter um conjunto de propriedades que ajudarão outras pessoas a usá-lo. Veremos mais sobre isso mais adiante.
Este é outro package.json
:
{
"name": "test-project"
}
Ele define uma propriedade name
, que informa o nome do aplicativo, ou pacote, contido na mesma pasta em que esse arquivo reside.
Aqui está um exemplo muito mais complexo, que foi extraído de um aplicativo 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"]
}
Existem muitas que estão aqui:
version
indica a versão atual;name
define o nome do pacote/aplicação;description
é uma breve descrição do app/pacote;main
define o ponto inicial da aplicação;private
se definido comotrue
impede que a aplicação/pacote seja publicado acidentalmente nonpm
;scripts
define um conjunto de scripts que você pode rodar com o node;dependencies
define a lista de pacotesnpm
instalados como dependências;devDependencies
define a lista de pacotesnpm
instalados como dependências de desenvolvimento;engines
define quais as versões do Node.js que o pacote/aplicação funciona;browserslists
é usado para dizer quais navegadores (e suas versões) você deseja que o app suporte;
Todas essas propriedades são usadas pelo npm
ou por outras ferramentas que podemos usar.
Esta seção descreve as propriedades que você pode usar em detalhes. Referimo-nos a "pacote", mas a mesma coisa se aplica a aplicações/aplicativos locais que você não usa como pacotes.
A maioria dessas propriedades são usadas apenas em https://www.npmjs.com/, outras por scripts que interagem com seu código, como o npm ou outros.
Define o nome do pacote.
Exemplo:
{
"name": "test-project"
}
O nome deve ter menos de 214 caracteres, não deve conter espaços, só pode conter letras minúsculas, hífens (-) ou sublinhas (_).
Isso ocorre porque quando um pacote é publicado no npm, ele obtém sua própria URL com base nessa propriedade.
Se você publicou este pacote publicamente no GitHub, uma uma prática é colocar para essa propriedade é o nome do repositório do GitHub.
Listas dos nomes dos autores do pacote.
Exemplo:
{
"author": "Joe <[email protected]> (https://whatever.com)"
}
Você também pode usar dessa forma:
{
"author": {
"name": "Joe",
"email": "[email protected]",
"url": "https://whatever.com"
}
}
Além do author, o projeto pode ter um ou mais colaboradores. Esta propriedade é um array que os lista.
Exemplo:
{
"contributors": ["Joe <[email protected]> (https://whatever.com)"]
}
Você também pode usar dessa forma:
{
"contributors": [
{
"name": "Joe",
"email": "[email protected]",
"url": "https://whatever.com"
}
]
}
Links para o rastreador de problemas do pacote, provavelmente uma página issue do GitHub.
Exemplo:
{
"bugs": "https://github.com/whatever/package/issues"
}
Define a página principal do pacote.
Exemplo:
{
"homepage": "https://whatever.com/package"
}
Indica a versão atual do pacote.
Exemplo:
{
"version": "1.0.0"
}
Esta propriedade segue a notação de versionamento semântico (semver) para versões, o que significa que a versão é sempre expressa com 3 número: x.x.x
.
O primeiro é a versão principal, o segundo a versão secundária e o terceiro é a versão do patch.
Há um significado nesses números: uma versão que corrige apenas bugs é uma versão de patch, uma versão que introduz alterações compatíveis com versões anteriores é uma versão menor/minor, uma versão principal/major pode ter alterações importantes.
Indica a licença do pacote.
Exemplo:
{
"license": "MIT"
}
Essa propriedade contém um array de palavras-chaves que são adicionadas de acordo com o que seu pacote faz.
Exemplo:
{
"keywords": [
"email",
"machine learning",
"ai"
]
}
Isso ajuda as pessoas a encontrarem seu pacote quando navegam entre pacotes similares, ou quando estão pesquisando no site do https://www.npmjs.com/.
Essa propriedade contém uma breve descrição do pacote.
Exemplo:
{
"description": "A package to work with strings"
}
Isso é especialmente útil se você decidir publicar seu pacote no npm
para que as possam saber do que se trata o pacote.
Essa propriedade específica onde está localizado o repositório do pacote (GitLab, GitHub).
Exemplo:
{
"repository": "github:whatever/testing",
}
Observe o prefixo github:
. Existem também como o gitlab:
e o bitbucket:
.
Você pode definir explicitamente o sistema de controle de versão:
{
"repository": {
"type": "git",
"url": "https://github.com/whatever/testing.git"
}
}
Você pode usar diferentes sistemas de controle de versão:
{
"repository": {
"type": "svn",
"url": "..."
}
}
Define o ponto de entrada para o pacote.
Quando você importa este pacote em um aplicativo, é onde o aplicativo buscará as exportações do módulo.
Exemplo:
{
"main": "src/main.js"
}
Se definido como true
, impede que o aplicativo/pacote seja publicado acidentalmente no npm
.
Exemplo:
{
"private": true
}
Define um conjunto de scripts que você pode rodar no node.
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 aplicativos de linha de comando. Você pode executá-los chamando npm run XXXX
ou yarn XXXX
, onde XXXX
é o nome do comando.
Exemplo: npm run dev
.
Você pode usar qualquer nome que quiser para um comando, e os scripts podem fazer literalmente o que você quiser.
Define uma lista de pacotes npm
instalados como dependências.
Quando você instala um pacote usando npm
ou yarn
:
npm install <package_name>
yarn add <package_name>
esse pacote será automáticamente inserido nessa lista.
Exemplo:
{
"dependencies": {
"vue": "^2.5.2"
}
}
Define uma lista de pacotes npm
instalados como dependência de desenvolvimento.
Eles diferem das dependencies
porque devem ser instalados apenas em uma máquina de desenvolvimento, não sendo necessários para executar o código em produção.
Para você instalar um pacote como dependência de desenvolvimento você pode usar o npm
ou o yarn
:
npm install --save-dev <package_name>
yarn add --dev <package_name>
esse pacote é inserido automaticamente nesta lista.
Exemplo:
{
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1"
}
}
Define em quais versões do Node.js e outros comandos este pacote/aplicação funciona.
Exemplo:
{
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0",
"yarn": "^0.13.0"
}
}
É usado para informar quais navegadores (e suas versões) você deseja oferecer suporte. Ele é referenciado pelo Babel, Autoprefixer e outras ferramentas, para adicionar os polyills e fallbacks necessários aos navegadores que você segmenta.
Exemplo:
{
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
Essa configuração significa que você deseja oferecer suporte às duas últimas versões principais de todos os navegadores com pelo menos 1% de uso (das estatísticas do https://caniuse.com), exceto IE8 e inferior
O arquivo package.json
também pode hospedar configuração específica de comando, por exemplo, para Babel, ESLint e muito mais.
Cada um tem uma propriedade específica, como eslintConfig
, babel
e outros. Esses são comandos específicos e você pode encontrar como usá-los na respectiva documentação do comando/projeto.
Você viu na descrição acima números de versão como estes: ~3.0.0
ou ^0.13.0
. O que eles significam e quais outros especificadores de versão você pode?
Esse símbolo específica quais atualizações seu pacote aceita, dessa dependência.
Dado que usando semver (versão semântica) todas as versões têm 3 dígitos, sendo o primeiro o lançamento principal, o segundo o lançamento secundário e o terceiro o lançamento do patch, você tem essas "Regras".
Você pode combinar a maioria das versões em intervalos, assim: 1.0.0 || >= 1.1.0 < 1.2.0
, para usar 1.0.0
ou uma versão de 1.1.0
para cima, mas inferior a 1.2.0
.