Diff package.json: porównuj manifesty npm online
Wklej stare package.json po lewej, nowe po prawej i zobacz dokładnie, które dependencies, scripts i engines się zmieniły. Działa w przeglądarce, nic nie jest wysyłane.
Czym jest to narzędzie do diffu package.json
Darmowe narzędzie działające w przeglądarce do porównywania dwóch plików npm package.json obok siebie. Wklej stary manifest po lewej, nowy po prawej, a różnice są podświetlane znak po znaku. Tekst nigdy nie opuszcza twojej maszyny, co ma znaczenie, gdy manifest należy do prywatnego repozytorium albo niewydanego produktu.
Jest zbudowane na ten moment, gdy wpada PR od Renovate albo Dependabota i musisz wiedzieć, co naprawdę się zmieniło poza bumpami wersji. Czy ktoś wcisnął edycję skryptu? Czy pole engines przeszło z Node 18 na Node 20? Czy zaciśnięto peerDependency? Widok diff GitHuba odpowiada na część tego, ale wklejenie dwóch manifestów do czystego widoku z dwoma panelami jest szybsze, gdy przeglądasz kilka PR-ów pod rząd albo porównujesz gałęzie, które jeszcze nie są wypchnięte.
Pod spodem to ten sam świadomy JSON-a diff, który napędza naszą stronę compare-json, z framingiem i tekstem dostrojonym do przepływów npm i yarn. Oba manifesty są parsowane jako JSON i ładnie formatowane przed uruchomieniem diffu, więc kosmetyczne różnice w spacjach nie zanieczyszczają podświetlenia. Jeśli potrzebujesz surowego diffu tekstowego dla formatu manifestu spoza JSON, nasze narzędzie compare-text to obsługuje, a compare-yaml radzi sobie z pnpm-lock.yaml.
Jak diff naprawdę działa
Każdy panel jest parsowany jako JSON. Jeśli parsowanie się udaje, manifest jest reformatowany ze spójnym wcięciem dwóch spacji, a kolejność kluczy zachowywana tak, jak została zapisana. Jeśli parsowanie zawiedzie (zabłąkany przecinek, brakująca klamra, kopia-wklej która złapała za mało znaków) narzędzie wraca do trybu zwykłego tekstu i mówi, która linia się złamała. Gdy obie strony są poprawnym JSON-em, diff biegnie znak po znaku, potem przebieg czyszczenia semantycznego grupuje zmiany z powrotem w czytelne kawałki, więc bump wersji z ^18.2.0 do ^19.0.0 czyta się jako jedna edycja, nie dziewięć edycji znaków.
Wstawienia w prawym panelu są renderowane na zielono; usunięcia w lewym panelu są renderowane na czerwono. Dwa panele są zsynchronizowane przewijaniem, więc gdy znajdziesz zmianę głęboko w devDependencies po jednej stronie, druga skacze do tego samego klucza. Ponieważ diff jest na poziomie tekstu po ładnym formatowaniu, widzi zmiany strukturalne tak, jak czyta je człowiek: usunięta zależność znika jako linia, zmieniony zakres semver podświetla się wewnątrz wartości, nowy skrypt wskakuje w blok scripts w pozycji, w której go umieściłeś.
Czego narzędzie celowo nie robi: nie jest resolverem zależności. Nie powie ci, jakie tranzytywne pakiety wciąga bump zakresu caret, czy peer jest spełniony, ani czy nowa wersja wprowadza alert bezpieczeństwa. Do tego uruchom lokalnie npm install a po nim npm audit, albo użyj npm z usługą świadomą lockfile'a jak Snyk czy alerty Dependabota od GitHuba. Ta strona mówi ci, co mówi tekst manifestu. Praca rozwiązywania należy do twojego menedżera pakietów.
Jak zrobić diff package.json w trzech krokach
Dwa panele tekstowe, jeden diff. Bez flag CLI, bez kroku instalacji, bez formatu patcha do czytania.
- 1
Wklej stary manifest po lewej
Skopiuj poprzednią wersję package.json z edytora, z git show main:package.json, albo od członka zespołu. Wklej do lewego panelu. Narzędzie sparsuje go jako JSON i ładnie sformatuje; jeśli JSON jest niepoprawny, edytor pokaże błąd parsowania, więc możesz naprawić wycinek przed diffem.
- 2
Wklej nowy manifest po prawej
Zrób to samo z zaktualizowaną wersją. Jeśli przeglądasz PR od Renovate albo Dependabota, najłatwiejszym źródłem jest surowy plik z gałęzi PR-a. Oba pliki są ładnie formatowane ze spójnym wcięciem, więc kosmetyczne edycje spacji nie pojawią się jako fałszywe zmiany w diffie.
- 3
Czytaj podświetlone różnice
Usunięcia pokazują się jako czerwone przekreślenia po lewej; wstawienia pokazują się jako zielone po prawej. Najpierw przeskanuj bloki zależności, potem sprawdź sekcję scripts pod kątem edycji komend, potem pola engines i peerDependencies. Bumpy wersji wewnątrz pojedynczej wartości podświetlają zmienione znaki, więc możesz odróżnić bump patcha od majora na pierwszy rzut oka.
Kiedy diff package.json to właściwy wybór
Przegląd PR-a od Renovate albo Dependabota
Bot otwiera piętnaście PR-ów rano. Większość to rutyna, ale jeden wcisnął zmianę skryptu, albo zaciśniętą peerDependency, albo bump engines, który psuje twój obraz CI. Tytuł PR-a mówi "chore(deps): bump foo from 4.1.0 to 4.2.1" i ufasz na autopilocie. Wklej package.json przed-i-po do diffu i możesz w pięć sekund zweryfikować, że nic innego się nie ruszyło. To pojedynczo najczęstszy powód, dla którego inżynierowie JS sięgają po diff manifestu.
Porównanie dwóch gałęzi przed mergem
Ty i kolega oboje dotknęliście package.json na osobnych gałęziach feature. Git zmerguje czysto, bo edycje są w różnych blokach, ale czysty merge nie znaczy poprawny. Wklej manifesty dwóch gałęzi do diffu, żeby wyłapać skrypt, który jedna gałąź upuściła, zależność, którą jedna gałąź zdowngrade'owała, albo kolizję, gdzie obie gałęzie dodały ten sam pakiet w różnych wersjach. Tańsze niż odkrycie tego po tym, jak CI uruchomi npm ci przeciwko zmergowanemu wynikowi.
Audyt tego, co npm install awansował w package-lock.json
Edycja package.json to połowa zmiany. Druga połowa to to, co package-lock.json zapisuje o rozwiązanym drzewie. Po uruchomieniu npm install, wklej stary lockfile obok nowego, żeby zobaczyć, jakie tranzytywne pakiety pojechały na przejażdżkę. Niespodziewane dodatki są częste, gdy zakres caret wciągnął nowy minor głęboko zagnieżdżonej zależności. Do surowej inspekcji lockfile'a nasza strona compare-json radzi sobie lepiej z większymi plikami; ta strona jest najlepsza dla samego manifestu.
Sprawdzenie downgrade'u po regresji
Wychodzi release, pojawia się bug, robisz bisect, a podejrzany jest gdzieś w drzewie zależności. Wklej package.json z ostatniego dobrego release'u obok obecnego. Mentalnie odetnij niezmienione bloki i skup się na podświetlonych zakresach wersji. Naprawa to często downgrade jednej biblioteki do wersji przypiętej w ostatnim zielonym buildzie. Gdy znajdziesz podejrzanego, zablokuj go dokładną wersją (bez careta, bez tildy), aż problem upstream zostanie rozwiązany.
Porównanie lokalnego manifestu z manifestem kolegi
Dwóch inżynierów, jeden trudny merge, dwa różne pliki package.json na końcu rebase'u. Lockfile jest jeszcze bardziej zagubiony. Wklej oba manifesty obok siebie, żeby zobaczyć, które klucze się nie zgadzają, potem rozwiąż je świadomie zamiast akceptować wynik git merge -X theirs bez czytania. To także właściwe narzędzie, gdy onboardujesz nowego kontrybutora, którego npm install wyciąga inne drzewo niż twoje i podejrzewasz drift manifestu.
Przegląd przed publikacją package.json biblioteki
Zanim uruchomisz npm publish na bibliotece, pola manifestu, które się liczą, są inne niż w aplikacji: main, module, types, exports, files, peerDependencies, engines. Zrób diff manifestu mającego być opublikowanym z ostatnim opublikowanym. Upuszczona pozycja peerDependencies, zmieniony warunek exports albo zaciśnięty zakres engines mogą zepsuć konsumentów w sposób, o którym sam npm cię nie ostrzeże. Dokumentacja packages Node.js jest referencją dla tego, co te pola znaczą.
Pola package.json warte poznania
Pola, które pojawiają się w prawdziwych diffach package.json i co znaczą. Warto przeskanować przed zatwierdzeniem PR-a od Renovate albo zmergeniem dwóch gałęzi, które obie dotknęły manifestu.
| Topic | What this tool does |
|---|
| dependencies vs devDependencies vs peerDependencies | dependencies wysyłają się z twoim pakietem i są instalowane przez każdego, kto go konsumuje. devDependencies są instalowane tylko gdy uruchamiasz npm install w korzeniu projektu, nigdy dla konsumentów po stronie odbiorcy. peerDependencies to pakiety, których twoja biblioteka oczekuje, że host dostarczy (zazwyczaj React, framework testowy, bundler) i npm 7+ zainstaluje je automatycznie, chyba że są w konflikcie. Przesunięcie pakietu między tymi blokami zmienia, kto płaci koszt instalacji. |
|---|
| Zakresy semver caret (^) vs tilda (~) | Caret ^1.2.3 pozwala na każdą wersję do, ale bez 2.0.0; to domyślny npm i najluźniejszy popularny zakres. Tilda ~1.2.3 pozwala tylko na patche, do, ale bez 1.3.0. 1.2.x to to samo co tilda. * oznacza dowolną wersję (nie używaj tego na produkcji). latest rozwiązuje się w czasie instalacji i produkuje niereprodukowalne buildy, więc unikaj. |
|---|
| Dokładne przypięcie (bez prefiksu zakresu) | Napisanie "react": "18.2.0" bez careta ani tildy przypina do tej dokładnej wersji. Połączone z lockfile'em, daje to najbardziej reprodukowalną instalację kosztem nigdy nieotrzymywania patchy bezpieczeństwa automatycznie. Niektóre zespoły przypinają wszystko; inne polegają na kombinacji caret plus lockfile. Nie ma uniwersalnie poprawnej odpowiedzi, ale kompromis to bardziej deterministyczne buildy kontra bardziej nieaktualne zależności. |
|---|
| Determinizm package-lock.json | package-lock.json zapisuje dokładnie rozwiązaną wersję każdego pakietu w drzewie zależności, włącznie z tranzytywnymi. npm ci instaluje z lockfile'a i odmawia jego modyfikacji; npm install może go zaktualizować, jeśli zakres pozwala na nowszą wersję. Dla CI zawsze używaj npm ci. Dla deweloperów npm install jest okej, dopóki commitujesz wynikającą zmianę lockfile'a. |
|---|
| Pole workspaces dla monorepo | Tablica workspaces mówi npm, żeby traktował katalogi siostrzane jako linkowane pakiety w monorepo. npm install w korzeniu instaluje wszystkie workspaces i tworzy jedno wyhostowane drzewo node_modules. Yarn i pnpm wspierają workspaces ze swoimi własnymi konwencjami, a pnpm w szczególności hostuje mniej agresywnie, co łapie więcej bugów wycieków zależności w czasie instalacji. |
|---|
| Pole engines | engines.node deklaruje wersje Node.js, które twój pakiet wspiera. Domyślnie npm tylko ostrzega, gdy host to narusza; engine-strict=true w .npmrc zmienia to w twardy błąd. Bumpowanie pola engines to łamiąca zmiana dla konsumentów utknących na starszym Node, i jest to typ zmiany, który chowa się w PR-ze "chore" od Renovate. Zawsze czytaj diff engines. |
|---|
| Pole exports dla ES modules | Pole exports kontroluje, które ścieżki konsumenci mogą importować z twojego pakietu i które warunki (import, require, types, node, browser) rozwiązują się do których plików. Dodanie albo usunięcie pozycji to łamiąca zmiana dla kodu po stronie odbiorcy. Dokumentacja packages Node.js pokrywa zasady rozwiązywania szczegółowo; traktuj każdy diff exports jako edycję wartą wersji major, chyba że celowo dodajesz nowy punkt wejścia. |
|---|
| Kolejność wpisów w package.json | Nie ma wymuszonej kolejności dla kluczy najwyższego poziomu w package.json. Konwencjonalnie większość projektów zaczyna od name, version, description, potem scripts, potem zależności. W blokach zależności kolejność alfabetyczna po kluczu jest standardem de facto i większość menedżerów pakietów posortuje blok przy zapisie. Diff pokazujący przeporządkowane, ale poza tym identyczne pozycje, zazwyczaj jest różnicą narzędziową, nie prawdziwą zmianą. |
|---|
Diff package.json: często zadawane pytania
Czym to się różni od npm diff albo npm-check-updates?
npm diff to wbudowane polecenie npm, które porównuje dwie opublikowane wersje pakietu w registry, włącznie z ich tarballami i źródłami. npm-check-updates (ncu) raportuje, które zależności w twoim manifeście mają dostępne nowsze wersje. Żadne z nich nie pokazuje ci różnicy między dwoma dowolnymi plikami package.json, które masz na dysku albo w dwóch gałęziach. To narzędzie to robi. Użyj ncu, żeby się dowiedzieć, że powinieneś zaktualizować, npm diff, żeby zobaczyć zmiany po stronie registry między releasami, i tej strony, żeby przeczytać własny manifest przed-i-po w widoku obok siebie.
Czy audytuje bezpieczeństwo albo sprawdza znane podatności?
Nie. Ta strona robi tylko diff tekstu. Nie pyta registry npm, GitHub Advisory Database ani żadnej usługi podatności. Do audytu bezpieczeństwa uruchom npm audit przeciwko zainstalowanemu drzewu, użyj npm audit signatures do weryfikacji pochodzenia pakietu, albo polegaj na alertach Snyk, Socket lub Dependabot. To narzędzie jest właściwym wyborem, gdy chcesz wiedzieć, co się zmieniło w manifeście. Jest złym wyborem, gdy chcesz wiedzieć, czy zmiana jest bezpieczna do wysłania.
Czy wykrywa zmiany w tranzytywnych zależnościach?
Nie z samego manifestu. package.json wymienia tylko bezpośrednie zależności i ich żądane zakresy. Pełne rozwiązane drzewo, włącznie z tranzytywnymi, mieszka w package-lock.json (albo yarn.lock albo pnpm-lock.yaml). Żeby porównać rozwiązane drzewa, wklej oba lockfile'e w diff. Ponieważ lockfile'e są duże, nasza strona compare-json radzi sobie z nimi lepiej niż ta. Specyficznie dla pnpm-lock.yaml użyj compare-yaml. Ta strona jest zoptymalizowana pod manifest.
Jak porównać dwa pliki package-lock.json?
Wklej oba lockfile'e w panele tak samo, jak zrobiłbyś to z manifestem. Narzędzie sparsuje je jako JSON, ładnie sformatuje i zrobi diff. Pamiętaj, że lockfile'e mogą sięgać tysięcy linii, więc podświetlony diff może być długi. Skup się najpierw na pozycjach packages najwyższego poziomu, potem na polach version. Dla plików większych niż mniej więcej pięć tysięcy linii nasza strona compare-json pasuje lepiej, bo jest skonfigurowana do obsługi dużych ładunków JSON tym samym silnikiem.
Jaka jest różnica między zakresami caret (^) a tilda (~)?
Oba to zakresy semver, które pozwalają na aktualizacje bez ręcznej edycji manifestu. Caret ^1.2.3 pozwala na każdą wersję, która nie zmienia najbardziej lewej cyfry niezerowej, więc 1.2.3 do 1.999.999 są akceptowane, ale 2.0.0 nie. Tilda ~1.2.3 jest bardziej rygorystyczna: pozwala tylko na aktualizacje patcha, więc 1.2.3 do 1.2.999 są akceptowane, ale 1.3.0 nie. Caret to domyślny npm i luźniejszy zakres; tildy sięgasz, gdy biblioteka ma historię łamania w releasach minor.
Czy są limity rozmiaru dla dużych lockfile'ów?
Praktycznie tak. Diff działa w twojej przeglądarce, więc bardzo duże wejścia (np. 20 000-liniowy lockfile z monorepo) mogą spowolnić stronę albo zatrzymać kartę w zależności od pamięci. Dla typowych manifestów aplikacji i lockfile'ów do kilku tysięcy linii na stronę diff kończy się w zasadzie natychmiast. Dla większych plików nasza strona compare-json jest lepszym punktem wejścia. Jeśli regularnie porównujesz ogromne lockfile'e, rozważ uruchomienie git diff package-lock.json lokalnie i przepuszczenie przez pager; ten przepływ skaluje się dalej niż jakiekolwiek narzędzie przeglądarkowe.
Prywatność i jak to działa
Twoje manifesty nigdy nie opuszczają twojej przeglądarki. Diff, parsowanie JSON, podświetlanie i renderowanie wszystko działa na twojej maszynie. Nie wysyłamy tekstu, nie logujemy go, ani nie przekazujemy do żadnej usługi trzeciej strony. To ma znaczenie szczególnie dla kodu zastrzeżonego: wklejenie package.json niewydanej biblioteki albo lockfile'a prywatnego repo do usługi chmurowej może samo w sobie naruszać politykę obsługi danych twojego pracodawcy, zwłaszcza gdy manifest nazywa wewnętrzne pakiety scoped, hosty prywatnego registry albo nazwy produktów w trakcie rozwoju. Weryfikacja roszczenia jest prosta. Otwórz DevTools przeglądarki, przełącz na zakładkę Network, wklej oba manifesty i obserwuj. Nie ma żadnych żądań wychodzących, gdy porównujesz. Ten sam model prywatności obowiązuje w naszych innych narzędziach, włączając compare-json, compare-yaml dla pnpm-lock.yaml, i git-diff-online do ogólnego przeglądu kodu. Po specyfikację u podstawy zobacz referencję konfiguracji Yarn i dokumentację package.json npm.