package.json original
package.json alterado

Diff de package.json: comparar manifestos npm online

Cole o package.json antigo à esquerda, o novo à direita, e veja exatamente quais dependências, scripts e engines mudaram. Roda no seu navegador, nada é enviado.

O que é esta ferramenta de diff de package.json

Uma ferramenta gratuita que roda no navegador para comparar dois arquivos npm package.json lado a lado. Cole o manifesto antigo à esquerda, o novo à direita, e as diferenças são destacadas caractere por caractere. O texto nunca sai da sua máquina, o que importa quando o manifesto pertence a um repositório privado ou a um produto não lançado.

Foi feita para o momento em que um PR do Renovate ou Dependabot chega e você precisa saber o que de fato mudou além dos bumps de versão. Alguém colou uma edição de script? O campo engines passou de Node 18 para Node 20? Uma peerDependency foi apertada? A visão de diff do GitHub responde parte disso, mas colar dois manifestos numa visão limpa de dois painéis é mais rápido quando você está varrendo vários PRs em sequência ou comparando branches que ainda não foram empurrados.

Por baixo, é o mesmo diff ciente de JSON que move nossa página compare-json, com enquadramento e texto ajustados para fluxos npm e yarn. Ambos os manifestos são parseados como JSON e formatados antes do diff rodar, então diferenças cosméticas de espaços não poluem o destaque. Se você precisa de diff de texto cru para um formato de manifesto não-JSON, nossa ferramenta compare-text cobre isso, e compare-yaml trata pnpm-lock.yaml.

Como o diff realmente funciona

Cada painel é parseado como JSON. Se o parsing tem sucesso, o manifesto é reformatado com indentação consistente de dois espaços e a ordem das chaves é preservada como escrita. Se o parsing falha (uma vírgula extra, uma chave faltante, um copia-cola que pegou poucos caracteres) a ferramenta cai para modo texto plano e diz qual linha quebrou. Uma vez que ambos os lados são JSON válido, o diff roda caractere por caractere, depois uma passada de limpeza semântica reagrupa as mudanças em pedaços legíveis, então um bump de versão de ^18.2.0 para ^19.0.0 lê como uma edição, não nove edições de caractere.

Inserções no painel direito aparecem em verde; deleções no painel esquerdo aparecem em vermelho. Os dois painéis têm scroll travado juntos, então quando você acha uma mudança bem dentro de devDependencies num lado, o outro pula para a mesma chave. Como o diff é de nível de texto após formatar, ele vê mudanças estruturais como uma pessoa lê: uma dependência removida desaparece como linha, um intervalo semver mudado destaca dentro do valor, um script novo encaixa no bloco scripts na posição que você colocou.

O que a ferramenta deliberadamente não faz: não é um resolvedor de dependências. Não vai te dizer quais pacotes transitivos um bump de intervalo caret traz, se um peer está satisfeito, ou se a versão nova introduz um aviso de segurança. Para isso, rode npm install seguido de npm audit localmente, ou use npm com um serviço ciente de lockfile como Snyk ou os alertas do Dependabot do GitHub. Esta página te diz o que o texto do manifesto diz. O trabalho de resolução pertence ao seu gerenciador de pacotes.

Como fazer diff de um package.json em três passos

Dois painéis de texto, um diff. Sem flags de CLI, sem passo de instalação, sem formato de patch para ler.

  1. 1

    Cole o manifesto antigo à esquerda

    Copie a versão anterior de package.json do seu editor, de git show main:package.json, ou de um colega. Cole no painel esquerdo. A ferramenta vai parsear como JSON e formatar; se o JSON for inválido, o editor vai exibir o erro de parsing para você corrigir o snippet antes de fazer o diff.

  2. 2

    Cole o manifesto novo à direita

    Faça o mesmo com a versão atualizada. Se você está revisando um PR do Renovate ou Dependabot, a fonte mais fácil é o arquivo cru da branch do PR. Ambos os arquivos são formatados com indentação consistente, então edições cosméticas de espaços não vão aparecer como mudanças falsas no diff.

  3. 3

    Leia as diferenças destacadas

    Deleções aparecem como riscado vermelho à esquerda; inserções aparecem em verde à direita. Varre os blocos de dependências primeiro, depois cheque a seção scripts por edições de comando, depois os campos engines e peerDependencies. Bumps de versão dentro de um único valor destacam os caracteres mudados, então você pode distinguir um bump de patch de um maior num relance.

Quando um diff de package.json é a escolha certa

Revisar um PR do Renovate ou Dependabot

Um bot abre quinze PRs numa manhã. A maioria é rotina, mas um colou uma mudança de script, ou uma peerDependency apertada, ou um bump de engines que quebra sua imagem de CI. O título do PR diz "chore(deps): bump foo from 4.1.0 to 4.2.1" e você confia em piloto automático. Cole o package.json antes-e-depois no diff e você pode verificar em cinco segundos que nada mais se mexeu. Esta é a única razão mais comum pela qual engenheiros JS pegam um diff de manifesto.

Comparar duas branches antes de mesclar

Você e um colega ambos tocaram package.json em branches de feature separadas. O Git vai mesclar limpinho porque as edições estão em blocos diferentes, mas merge limpo não significa merge correto. Cole os manifestos das duas branches no diff para identificar um script que uma branch derrubou, uma dependência que uma branch downgradou, ou um conflito onde ambas as branches adicionaram o mesmo pacote em versões diferentes. Mais barato que descobrir depois que o CI rodar npm ci contra o resultado mesclado.

Auditar o que npm install promoveu em package-lock.json

Editar package.json é metade da mudança. A outra metade é o que package-lock.json registra sobre a árvore resolvida. Após rodar npm install, cole o lockfile antigo ao lado do novo para ver quais pacotes transitivos vieram a passeio. Adições surpresa são comuns quando um intervalo caret puxou um novo minor de uma dependência profundamente aninhada. Para inspeção crua de lockfile nossa página compare-json trata os arquivos maiores melhor; esta página é melhor para o manifesto em si.

Conferir um downgrade após uma regressão

Sai uma release, surge um bug, você bisseta, e o suspeito está em algum lugar na árvore de dependências. Cole o package.json da última release boa ao lado do atual. Descarte mentalmente os blocos sem mudança e foque nos intervalos de versão destacados. A correção é frequentemente um downgrade de uma biblioteca para a versão fixada no último build verde. Uma vez que você ache o suspeito, trave com uma versão exata (sem caret, sem til) até o problema upstream ser resolvido.

Comparar seu manifesto local com o de um colega

Dois engenheiros, um merge complicado, dois arquivos package.json diferentes no fim do rebase. O lockfile está ainda mais confuso. Cole os dois manifestos lado a lado para ver quais chaves discordam, depois resolva-as deliberadamente em vez de aceitar o resultado de git merge -X theirs sem ler. Esta também é a ferramenta certa quando integrando um novo contribuidor cujo npm install pega uma árvore diferente da sua e você suspeita de drift de manifesto.

Revisão pré-publish do package.json de uma biblioteca

Antes de rodar npm publish numa biblioteca, os campos do manifesto que importam são diferentes dos de um app: main, module, types, exports, files, peerDependencies, engines. Faça diff do manifesto prestes a publicar contra o último publicado. Uma entrada peerDependencies derrubada, uma condição exports mudada, ou um intervalo engines apertado pode quebrar consumidores de formas que o próprio npm não vai te avisar. Os docs de packages do Node.js são a referência para o que esses campos significam.

Campos de package.json que vale conhecer

Os campos que aparecem em diffs reais de package.json e o que significam. Vale varrer antes de aprovar um PR do Renovate ou mesclar duas branches que ambas tocaram o manifesto.

TopicWhat this tool does
dependencies vs devDependencies vs peerDependenciesdependencies são distribuídas com seu pacote e instaladas por qualquer um que o consome. devDependencies só são instaladas quando você roda npm install na raiz do projeto, nunca para consumidores a jusante. peerDependencies são pacotes que sua biblioteca espera que o host forneça (tipicamente React, o framework de testes, o bundler) e npm 7+ vai instalá-los automaticamente a menos que entrem em conflito. Mover um pacote entre esses blocos muda quem paga o custo de instalação.
Intervalos semver caret (^) vs til (~)Caret ^1.2.3 permite qualquer versão até mas sem incluir 2.0.0; este é o padrão do npm e o intervalo comum mais frouxo. Til ~1.2.3 permite só patches, até mas sem incluir 1.3.0. 1.2.x é o mesmo que til. * significa qualquer versão (não use isso em produção). latest resolve no momento da instalação e produz builds não reproduzíveis, então evite.
Pin exato (sem prefixo de intervalo)Escrever "react": "18.2.0" sem caret ou til pina naquela versão exata. Combinado com um lockfile, isso te dá a instalação mais reproduzível ao custo de nunca receber patches de segurança automaticamente. Alguns times pinam tudo; outros contam com a combinação caret mais lockfile. Não há resposta universalmente certa, mas o trade-off é builds mais determinísticos versus dependências mais desatualizadas.
Determinismo de package-lock.jsonpackage-lock.json registra a versão resolvida exata de cada pacote na árvore de dependências, incluindo transitivas. npm ci instala a partir do lockfile e se recusa a modificá-lo; npm install pode atualizá-lo se um intervalo permite uma versão mais nova. Para CI, sempre use npm ci. Para desenvolvedores, npm install está ok desde que você comite a mudança resultante do lockfile.
Campo workspaces para monoreposO array workspaces diz ao npm para tratar diretórios irmãos como pacotes vinculados num monorepo. npm install na raiz instala todos os workspaces e cria uma única árvore node_modules hoisted. Yarn e pnpm suportam workspaces com suas próprias convenções, e pnpm em particular hoista menos agressivamente, o que pega mais bugs de vazamento de dependência no momento da instalação.
Campo enginesengines.node declara as versões de Node.js que seu pacote suporta. Por padrão npm só avisa quando o host viola isso; engine-strict=true em .npmrc transforma em erro duro. Subir o campo engines é uma mudança que quebra para consumidores presos em Node antigo, e é o tipo de mudança que se esconde dentro de um PR "chore" do Renovate. Sempre leia o diff de engines.
Campo exports para ES modulesO campo exports controla quais caminhos consumidores podem importar do seu pacote e quais condições (import, require, types, node, browser) resolvem para quais arquivos. Adicionar ou remover uma entrada é uma mudança que quebra para código a jusante. A documentação de packages do Node.js cobre as regras de resolução em detalhe; trate qualquer diff de exports como uma edição digna de versão maior a menos que você esteja deliberadamente adicionando um novo ponto de entrada.
Ordem de arquivos dentro de package.jsonNão há ordem forçada para chaves de nível superior em package.json. Por convenção, a maioria dos projetos começa com name, version, description, depois scripts, depois dependências. Dentro de blocos de dependência, ordem alfabética por chave é o padrão de fato e a maioria dos gerenciadores de pacotes vai ordenar o bloco no save. Um diff que mostra entradas reordenadas mas no resto idênticas é geralmente uma diferença de ferramenta, não uma mudança real.

Diff de package.json: perguntas frequentes

Como isso é diferente de npm diff ou npm-check-updates?

npm diff é um comando npm embutido que compara duas versões publicadas de um pacote no registry, incluindo seus tarballs e fontes. npm-check-updates (ncu) reporta quais dependências do seu manifesto têm versões mais novas disponíveis. Nenhum te mostra a diferença entre dois arquivos package.json arbitrários que você tem em disco ou em duas branches. Esta ferramenta faz isso. Use ncu para descobrir o que deveria atualizar, npm diff para ver mudanças do lado do registry entre releases, e esta página para ler seu próprio manifesto antes-e-depois numa visão lado a lado.

Audita segurança ou checa vulnerabilidades conhecidas?

Não. Esta página só faz diff do texto. Não consulta o registry npm, o GitHub Advisory Database, ou qualquer serviço de vulnerabilidade. Para auditoria de segurança, rode npm audit contra uma árvore instalada, use npm audit signatures para verificar a procedência do pacote, ou conte com alertas Snyk, Socket ou Dependabot. Esta ferramenta é a escolha certa quando você quer saber o que mudou no manifesto. É a escolha errada quando você quer saber se a mudança é segura para enviar.

Detecta mudanças de dependências transitivas?

Não a partir do manifesto sozinho. package.json só lista dependências diretas e seus intervalos solicitados. A árvore resolvida completa, incluindo transitivas, vive em package-lock.json (ou yarn.lock ou pnpm-lock.yaml). Para comparar árvores resolvidas, cole ambos os lockfiles num diff. Como lockfiles são grandes, nossa página compare-json os trata melhor que esta. Para pnpm-lock.yaml especificamente, use compare-yaml. Esta página é otimizada para o manifesto.

Como comparo dois arquivos package-lock.json?

Cole ambos os lockfiles nos painéis do mesmo jeito que você faria com um manifesto. A ferramenta vai parsear como JSON, formatar e fazer diff. Saiba que lockfiles podem chegar a milhares de linhas, então o diff destacado pode ser longo. Foque nas entradas packages de nível superior primeiro, depois nos campos version. Para arquivos maiores que aproximadamente cinco mil linhas, nossa página compare-json encaixa melhor porque está montada para tratar payloads grandes de JSON com o mesmo motor.

Qual a diferença entre os intervalos caret (^) e til (~)?

Ambos são intervalos semver que permitem atualizações sem editar manualmente o manifesto. O caret ^1.2.3 permite qualquer versão que não mude o dígito não-zero mais à esquerda, então 1.2.3 até 1.999.999 são aceitas, mas 2.0.0 não é. O til ~1.2.3 é mais estrito: permite só atualizações de patch, então 1.2.3 até 1.2.999 são aceitas mas 1.3.0 não é. Caret é o padrão npm e o intervalo mais frouxo; til é o que você pega quando uma biblioteca tem histórico de quebrar em releases minor.

Há limites de tamanho para lockfiles grandes?

Praticamente sim. O diff roda no seu navegador, então entradas muito grandes (um lockfile de 20.000 linhas de um monorepo, por exemplo) podem deixar a página lenta ou travar a aba dependendo da memória. Para manifestos típicos de app e lockfiles de até alguns milhares de linhas por lado, o diff completa praticamente instantaneamente. Para arquivos maiores, nossa página compare-json é o ponto de entrada melhor. Se você compara regularmente lockfiles enormes, considere rodar git diff package-lock.json localmente e canalizar para um pager; esse fluxo escala mais longe que qualquer ferramenta de navegador.

Privacidade e como isso funciona

Seus manifestos nunca saem do seu navegador. O diff, o parsing JSON, o destaque e a renderização todos rodam na sua máquina. Não enviamos o texto, não logamos, nem passamos para nenhum serviço de terceiros. Isso importa especificamente para código proprietário: colar o package.json de uma biblioteca não lançada ou o lockfile de um repositório privado num serviço cloud pode em si violar a política de manuseio de dados do seu empregador, especialmente quando o manifesto nomeia pacotes scoped internos, hosts de registry privados, ou nomes de produtos em desenvolvimento. Verificar a alegação é direto. Abra o DevTools do navegador, mude para a aba Network, cole ambos os manifestos e observe. Não há requisições saindo quando você compara. O mesmo modelo de privacidade vale em nossas outras ferramentas, incluindo compare-json, compare-yaml para pnpm-lock.yaml, e git-diff-online para revisão de código geral. Para a especificação subjacente, veja a referência de configuração do Yarn e os docs do package.json do npm.