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:
versionindica a versão atual;namedefine o nome do pacote/aplicação;descriptioné uma breve descrição do app/pacote;maindefine o ponto inicial da aplicação;privatese definido comotrueimpede que a aplicação/pacote seja publicado acidentalmente nonpm;scriptsdefine um conjunto de scripts que você pode rodar com o node;dependenciesdefine a lista de pacotesnpminstalados como dependências;devDependenciesdefine a lista de pacotesnpminstalados como dependências de desenvolvimento;enginesdefine 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.