Typy dependencji w package.json

Wyróżniamy 5 głównych typów dependencji w menadżerach pakietów, takich jak yarn lub npm. Zapraszam do omówienia ich wszystkich, dogłębnie i szczegółowo

W moim poprzednim artykule wspomniałem, że temat dependencji powinien otrzymać swój własny wątek. Podczas, gdy większość standardowych modułów instalujemy za pomocą polecenia npm install [nazwa], to w zależności od potrzeb i od przeznaczenia danych bibliotek, możemy instalować je nieco inaczej - jako inne typy dependencji niż te normalne. Ale co to wszystko oznacza? Przejdźmy zatem do omówienia wszystkich typów, a będą to kolejno:

  1. dependencies
  2. devDependencies
  3. peerDependencies
  4. bundledDependencies
  5. optionalDependencies

Różnią się one m. in. tym, w jaki sposób moduły są instalowane przy instalacji projektu. Nasz przykładowy plik package.json może wyglądać tak:

{
  "dependencies": {
    "gsap": "^3.5.1",
    "react-cookie": "^4.0.3",
  },
  "devDependencies": {
    "babel-eslint": "^10.1.0",
    "eslint": "^6.6.0"
  }
  "peerDependencies": {
    "chai": "^1.2"
  }
  "bundleDependencies": {
    "prop-types": "^15.7.2"
  }
  "optionalDependencies": {
    "slugify": "^1.4.6"
  }
}

Jak widać typy instalują się pod szczególnymi kluczami.

normal Dependencies

Normal dependencies (w package.json podpisane jako dependencies) są podstawowym typem dependencji w projekcie i instalują się domyślnie, chyba, że zechcemy inaczej. Wszystkie moduły zapisywane w kluczu dependencies, w package.json, są zwykłymi zależnościami - dla npm oznacza to, że moduły te są integralną częścią naszego finalnego projektu, bez których nie będzie on działał poprawnie lub w ogóle nie zadziała. Przykładem takich dependencji może być jakakolwiek bilbioteka, z której kodu korzystamy w naszej aplikacji: frameworki, axios, styled-components. Zwykłe dependencje instalujemy następująco.

npm install react    //domyślna instalacja
npm install react --save-prod
npm install react -P
npm i react
npm i react -P

devDependencies

Jak sama nazwa wskazuje, typ ten, jest typem dependencji deweloperskim. A więc w kluczu devDependencies znajdą się wszystkie moduły, które nie integrują w żaden sposób w kod naszego projektu. Typy te nie lądują na produkcji, ponieważ nie są niezbędne do działania aplikacji. Najczęściej moduły tego typu to wszelkie lintery, formattery etc. (usprawniacze pisania kodu) oraz różne narzędzia służące do budowania projektu. Przykłady modułów zapisywanych jako devDependencies:

DevDependencies instalujemy w jeden z następujących sposobów:

npm install react --save-dev
npm install react -D
npm i react --save-dev
npm i react -D

peerDependencies

Te dependencje sprawiały mi największą zagwozdkę i długo się zastanawiałem, jak wyjaśnić ich działanie. Podobnie jak normalne dependecje, są one wymagane w działaniu projektu. PeerDependency oznacza, że pakiet wymaga zależności, której wersja paczki jest dokładnie taka sama, jak zależność osoby instalującej pakiet. Jest to przydatne w przypadku zależności, takich jak React, który musi mieć jedną kopię react-dom, z którego korzysta również osoba ją instalująca. Ta funkcjonalność przydatna jest bardzo w momencie, kiedy piszemy własną bibliotekę - umieszczając peerDependency w package.json, możemy mieć pewność, że każdy będzie korzystał z działającej wersji zależności dla naszej biblioteki. Zalecam instalować te dependencje tylko wtedy, gdy jest to konieczne i umieszczone w dokumentacji modułu, ponieważ peerDependencies potrafią być problematyczne. Sposób instalacji jest trochę inny od poprzednich i najlepiej je instalować za pomocą npx i narzędzie install-peerdeps:

npx install-peerdeps react

optionalDependencies

Te dependencje również są potrzebne projektowi w działaniu. Z tą różnicą, że jak sama nazwa wskazuje, są one opcjonalne - oznacza to, że npm, nie znajdując paczki, będzie kontynuuował działanie, nawet mimo niepoprawnej instalacji. Dlatego projekt nie powinien wymagać tych dependencji w działaniu - może ale nie musi. Jest to rzadko używany typ - osobiście, w praktyce nie użyłem go nigdy. Sposoby instalacji:

npm install react --save-optional
npm install react -O
npm i react --save-optional
npm i react -O

bundleDependencies

Dependencje opakowane (tłumacząc na polski) wymagane są przez projekt. W kluczu umieszczamy zależności, które chcemy zachować lokalnie w projekcie. Zaletą takiego rozwiązania jest posiadanie działających wersji modułów niezależnie od zmieniającego się środowiska. BundleDependencies wyświetlane są bez wersji. Tak samo jak optionalDependencies są rzadko wykorzystywane. Instalujemy je następująco:

npm install react --save-bundle
npm install react -B
npm i react --save-bundle
npm i react -B

Dependencje są skomplikowane?

Jako webdeveloperzy nie mamy łatwego życia. Coraz to nowsze rozwiązania i technologie, których musimy się uczyć, by produkować aplikacje, potrafią frustrować. Dogłębna analiza i czytanie dokumentacji oraz artykułów na dany temat pomagają zrozumieć zagadnienie. Jednym z takich zgadnień są typy dependencji. Bo nawet jeśli nie przyjdzie nam używać wszystkich typów, to warto wiedzieć, że takie istnieją. A nuż w przyszłości będziemy chcieli wykorzystać je do wykonywanego projektu, gdy uznamy, że mogą być przydatne.

Źródła

© Damian Kalka 2021
Wszelkie prawa zastrzeżone