npm devDependencies - Kiedy używać --save-dev? Poradnik!

Diagram przedstawia proces instalacji pakietów w JavaScript, gdzie npm save dev pozwala na dodawanie zależności.

Napisano przez

Alex Jabłoński

Opublikowano

11 cze 2026

Spis treści

W projektach JavaScript nie każdy pakiet ma taki sam status. Część bibliotek musi działać w przeglądarce albo na serwerze po wdrożeniu, a część jest potrzebna tylko do budowania, testów, lintowania czy typowania kodu. To właśnie robi zapis do devDependencies, czyli najbliższy sens temu, co wiele osób skrótowo nazywa npm save dev. W praktyce chodzi o to, by nie mieszać narzędzi dla programisty z zależnościami, bez których aplikacja nie ruszy na produkcji.

Najkrócej: zapis do devDependencies porządkuje zależności używane tylko podczas pracy nad projektem

  • Do devDependencies trafiają pakiety do budowania, testów, lintowania i typowania, a nie biblioteki wymagane w runtime.
  • npm install -D i npm install --save-dev zapisują paczkę w sekcji devDependencies.
  • npm aktualizuje przy tym także package-lock.json, więc instalacje w zespole są bardziej przewidywalne.
  • Na produkcji często używa się npm ci --omit=dev albo instalacji bez zależności deweloperskich.
  • Jeśli pakiet jest potrzebny po wdrożeniu, nie powinien trafiać do sekcji dla narzędzi developerskich.
  • Najczęstszy błąd to wrzucanie do złej sekcji bundlera, lintera albo biblioteki runtime.

Czym jest zależność deweloperska i kiedy ma sens

Zależność deweloperska to pakiet, który pomaga tworzyć, sprawdzać lub przygotować kod, ale nie jest potrzebny do jego uruchomienia w produkcji. Dokładnie tak rozróżnia to dokumentacja npm: dependencies są dla aplikacji działającej po wdrożeniu, a devDependencies dla lokalnego developmentu i testów.

Najczęściej trafiają tam narzędzia, których użytkownik końcowy nigdy nie widzi, choć bez nich zespół nie pracowałby wygodnie:

  • ESLint - sprawdza jakość i spójność kodu przed commitem.
  • Prettier - formatuje pliki bez wpływu na działanie aplikacji.
  • TypeScript - kompiluje i typuje kod, ale sam w sobie nie jest częścią runtime.
  • Vite, Webpack, Rollup - przygotowują paczkę do wdrożenia.
  • Vitest, Jest, Cypress - odpowiadają za testy i weryfikację zachowania.
  • @types/* - dostarczają definicje typów, potrzebne głównie podczas pracy nad kodem.

Jeśli pakiet jest potrzebny po stronie runtime, nie powinien lądować w tej kategorii. Przykładowo biblioteka do komunikacji z API w frontendzie albo sterownik bazy w backendzie zwykle zostaje w zwykłych zależnościach, bo bez niej aplikacja nie wykona podstawowej logiki. Z tego rozróżnienia wynika też to, jak powinien wyglądać kolejny krok instalacji.

NPM zarządza zależnościami projektu. Użyj `npm save dev` do dodania pakietów deweloperskich.

Jak zapisać pakiet jako devDependency w praktyce

Najprostsza forma to npm install -D albo równoważne npm install --save-dev . npm dopisze wpis do package.json w sekcji devDependencies i zaktualizuje package-lock.json, dzięki czemu reszta zespołu dostanie ten sam zakres wersji.

npm install -D eslint
npm install --save-dev vitest
npm install -D @types/node

Po takiej instalacji w package.json zobaczysz wpis podobny do "eslint": "^9.0.0". Domyślnie npm zapisuje wersję z zakresem semver, zwykle z ^. Jeśli zależy ci na dokładnym przypięciu wersji, dodaj -E (--save-exact), ale robię to tylko wtedy, gdy naprawdę chcę zamrozić narzędzie, a nie tylko jego główną linię rozwojową.

W drugą stronę działa to symetrycznie: gdy pakiet przestaje być potrzebny, usuwam go przez npm uninstall -D . To ważne, bo porządek w zależnościach zaczyna się nie od samej instalacji, ale od konsekwentnego sprzątania po zmianach.

Jak odróżnić dependencies, devDependencies i inne typy

Najwięcej pomyłek bierze się stąd, że patrzy się tylko na nazwę pakietu, a nie na moment jego użycia. Ja zadaję jedno pytanie: czy kod bez tego pakietu uruchomi się po wdrożeniu?

Typ Kiedy używać Przykłady Co się dzieje w produkcji
dependencies Gdy pakiet jest potrzebny w runtime React w aplikacji, klient HTTP, biblioteka dostępu do bazy Musi być dostępny, bo aplikacja z niego korzysta
devDependencies Gdy pakiet służy do budowania, testów, lintowania lub typowania ESLint, Prettier, Vitest, TypeScript, Vite Często jest pomijany w instalacji produkcyjnej
peerDependencies Gdy tworzysz bibliotekę i wymagasz konkretnej wersji pakietu hosta Plugin do Reacta, rozszerzenie do frameworka Oczekuje, że host dostarczy ten pakiet sam
optionalDependencies Gdy pakiet jest dodatkiem, a jego brak nie powinien wywalić instalacji Natywne dodatki, niekrytyczne rozszerzenia Instalacja może pominąć taki pakiet bez blokowania projektu

Warto też pamiętać, że peerDependencies służą do współpracy z pakietem hosta, a nie do „schowania” czegoś z produkcji. To częsty błąd przy tworzeniu bibliotek UI i pluginów. Gdy nie jestem pewien, sprawdzam, czy pakiet ma uruchamiać aplikację, czy tylko pomóc mi ją zbudować albo przetestować.

Co dzieje się przy instalacji lokalnie, w CI i na produkcji

Sam zapis do devDependencies nie znaczy jeszcze, że pakiet zniknie z dysku. Przy zwykłym npm install npm instaluje także zależności deweloperskie, o ile nie ustawisz pomijania dla środowiska produkcyjnego. W praktyce najczęściej spotkasz npm install --omit=dev albo NODE_ENV=production, które prowadzą do pominięcia pakietów z tej sekcji.

  • npm install - pełna instalacja do pracy lokalnej.
  • npm ci - czysta, powtarzalna instalacja na CI, oparta na lockfile.
  • npm ci --omit=dev - wariant dla produkcji, gdy nie chcesz instalować narzędzi deweloperskich.

To ważne, bo w wielu deploymentach właśnie devDependencies odpowiadają za rozmiar instalacji i czas uruchamiania pipeline'u. Jeśli projekt trafia do środowiska produkcyjnego bez bundlowania, pominięcie tej sekcji potrafi realnie zmniejszyć obraz kontenera albo paczkę wdrożeniową. Z drugiej strony w klasycznym buildzie front-endowym te pakiety bywają niezbędne na etapie kompilacji, więc nie wolno ich usuwać „na ślepo”.

Najczęstsze błędy, które psują porządek w projekcie

  • Wrzucone do złej sekcji narzędzie buildowe. Jeśli Vite, ESLint albo TypeScript lądują w dependencies, produkcja niesie zbędny balast.
  • Runtime bez zależności produkcyjnej. Jeśli aplikacja po wdrożeniu nie znajdzie biblioteki, która była w devDependencies, błąd wyjdzie dopiero na serwerze.
  • Brak lockfile w repozytorium. Bez package-lock.json zespół może instalować inne zakresy wersji niż ty.
  • Globalna instalacja zamiast lokalnej. Narzędzie dostępne tylko na twoim komputerze nie rozwiązuje problemu w projekcie.
  • Za szybkie kasowanie zależności deweloperskiej. Jeśli pakiet bierze udział w buildzie, jego usunięcie rozwala pipeline albo testy.

Najlepsza obrona przed takimi wpadkami jest prosta: przed instalacją sprawdzam, czy pakiet jest potrzebny do uruchomienia aplikacji, czy tylko do jej przygotowania. To jedno pytanie oszczędza więcej czasu niż szukanie późniejszych błędów w CI. Gdy trzeba coś zmienić, robię to lokalnie, zapisuję w odpowiedniej sekcji i od razu weryfikuję, czy build nadal przechodzi.

Praktyczna reguła, która porządkuje większość decyzji

Gdybym miał to uprościć do jednego zdania, powiedziałbym: jeśli pakiet nie jest potrzebny do działania aplikacji po wdrożeniu, zapisuję go jako zależność deweloperską. Dzięki temu plik zależności pozostaje czytelny, build jest lżejszy, a osoba wchodząca do projektu od razu widzi, co służy runtime, a co tylko pracy zespołu.

W projektach front-endowych ta zasada najczęściej oznacza taki podział: React, router, klient API czy biblioteka do komunikacji z backendem trafiają do zwykłych zależności, natomiast bundler, linter, test runner, TypeScript i typy trafiają do devDependencies. To nie jest tylko porządek estetyczny. W większym zespole taki podział ogranicza błędy w deploymentach i ułatwia automatyzację.

Jeśli chcesz utrzymać projekt w ryzach, trzymaj jeszcze jedną zasadę pomocniczą: instaluj lokalnie, zapisuj świadomie, a na CI używaj npm ci. Taki zestaw daje przewidywalne instalacje i nie zmusza cię do zgadywania, czy problem wynika z kodu, czy z rozjechanych zależności.

FAQ - Najczęstsze pytania

devDependencies to pakiety potrzebne tylko podczas tworzenia, testowania lub budowania aplikacji (np. ESLint, Prettier, TypeScript). Nie są one wymagane do uruchomienia aplikacji w środowisku produkcyjnym, co odróżnia je od zwykłych dependencies.

Aby dodać pakiet do devDependencies, użyj komendy `npm install -D ` lub `npm install --save-dev `. Spowoduje to zapisanie pakietu w sekcji devDependencies w pliku package.json i aktualizację package-lock.json.

Rozdzielanie zależności porządkuje projekt, zmniejsza rozmiar paczki produkcyjnej i przyspiesza instalację na serwerach. Pomaga też w utrzymaniu czystości kodu i ułatwia zarządzanie zależnościami w zespole, minimalizując ryzyko błędów.

Domyślnie `npm install` instaluje wszystkie zależności, w tym devDependencies. Aby pominąć devDependencies na produkcji, użyj `npm install --omit=dev` lub `npm ci --omit=dev`. To ważne dla optymalizacji środowiska produkcyjnego.

Jeśli narzędzie buildowe (np. Vite, ESLint) trafi do `dependencies`, produkcja będzie zawierać zbędny balast. Zwiększy to rozmiar paczki i czas instalacji, a także może wprowadzić zamieszanie w zarządzaniu zależnościami projektu.

Oceń artykuł

Ocena: 0.00 Liczba głosów: 0

Tagi:

npm save dev czym jest devdependencies kiedy używać devdependencies npm install -d devdependencies a dependencies różnica devdependencies dependencies

Udostępnij artykuł

Alex Jabłoński

Alex Jabłoński

Nazywam się Alex Jabłoński i od 9 lat zajmuję się programowaniem webowym. Moja przygoda z tą dziedziną zaczęła się od prostych projektów, które z czasem przerodziły się w pasję do tworzenia użytecznych i estetycznych aplikacji internetowych. Fascynuje mnie nie tylko sam proces kodowania, ale także to, jak technologie wpływają na nasze życie i jak możemy je wykorzystać, aby rozwiązywać codzienne problemy. Piszę o różnych aspektach programowania, od podstawowych języków po bardziej zaawansowane techniki i narzędzia. Staram się, aby moje teksty były przystępne i zrozumiałe, a skomplikowane zagadnienia przedstawiam w prosty sposób. Regularnie śledzę nowinki w branży, co pozwala mi dostarczać aktualne i rzetelne informacje. Moim celem jest nie tylko edukacja, ale także inspirowanie innych do rozwijania swoich umiejętności w programowaniu.

Napisz komentarz