W tym wpisie dowiesz się, co to jest npm, do czego Ci się może przydać oraz jak go wykorzystać w praktyce.
Co to jest npm?
npm jest menadżerem zależności (dependencies) dla języka JavaScript. Do opublikowania zależności w npm jedyne co jest konieczne to założenie konta na npmjs.org. W zasobach npm znaleźć można zarówno zależności tworzone jak i rozwijane przez organizacje, a także paczki utrzymywane przez społeczność.
Instalacja
Instalacja npm na lokalnej maszynie jest banalna. Należy odwiedzić stronę nodejs.org i pobrać Node.js. Wraz z Node.js dystrybuowany jest npm jako domyślny menedżer pakietów. Po zakończeniu procesu instalacji, w wierszu poleceń warto wykonać polecenia: node -v
oraz npm -v
. Zwracają one aktualnie zainstalowane wersje Node.js oraz npm.
Tworzenie nowego projektu
Aby rozpocząć rozwijanie projektu z wykorzystaniem zewnętrznych zależności, należy utworzyć projekt. Głównym plikiem w projekcie jest package.json
. Aby stworzyć nowy projekt, można skorzystać z polecenia npm init
. Można oczywiście również stworzyć plik package.json
ręcznie. Po wywołaniu omawianego polecenia należy podać nazwę projektu, wersję, opis, entry point, komendę do testów, link do repozytorium, słowa kluczowe oraz typl licencji. W rezultacie wyświetlony zostanie podgląd, a konfigurator zapyta się, czy wszystko jest wpisane poprawnie. Alternatywą jest wykorzystanie flagi --yes
, która sprawia, że tworzony jest plik z domyślnymi parametrami.
Po zatwierdzeniu zmian wprowadzonych do konfiguratora w folderze z projektem zostaje stworzony plik package.json
. Poniżej znajdziesz przykład.
{
"name": "example-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Dominik Szczepaniak",
"license": "MIT"
}
Co ciekawe, znajduje się tu pole z autorem, którego wcześniej nie podałem. Część z danych, które dla rozwijanych projektów będą takie same można ustawić poprzez ustawienie globalnej konfiguracji npm. Jako globalne dane można ustawić: autora, email, stronę www oraz licencja. Omawiany rezultat można osiągnąć poprzez wywołanie następujących poleceń.
npm config set init.author.name "Dominik Szczepaniak"
npm config set init.author.email [email protected]
npm config set init.author.url https://devszczepaniak.pl
npm config set init.license MIT
Instalacja zależności
Kluczowym zagadnieniem pracy z npm są zależności. Pakiety/zależności to paczki z kodem, które można pobrać i wykorzystać w projekcie w ramach licencji, jaka obowiązuje dla danej zależności. W celu instalacji zależności należy wywołać polecenie npm install
, a po nim nazwa paczki, bądź paczek. W przypadku gdy nie zostanie podana żadna nazwa, zostaną zainstalowane wszystkie zależności, jakie znajdują się w package.json
w danej lokalizacji.
Istnieje też możliwość skorzystania ze skróconej wersji polecenia — słowo install
zastępujemy literą i
. Następnie przez odpowiednie flagi możemy wywoływać pożądane efekty i zależności. Pełnia możliwości polecenia npm install została opisana w dokumentacji npm.
Zależności mogą być instalowane na kilka sposobów. Pierwszy z nich to globalna instalacja zależności. Oznacza to, że taka paczka będzie dostępna globalnie, czyli w każdym projekcie. Wykonujemy to poprzez flagę --global
lub skróconą wersję -g
. Ten sposób instalowania paczek zdecydowanie nie jest polecany dla zależności wykorzystywany bezpośrednio w projekcie. Należy pamiętać, że sam projekt nie zawiera wtedy żadnej informacji o tej zależności. Jeżeli projekt zostanie uruchomiony na innej maszynie, to w przypadku wykorzystania zależności zainstalowanych globalnie projekt może nie działać poprawnie. Ten sposób instalacji rekomendowałbym dla zależności, które są wykorzystywane jako narzędzia pomocnicze do pracy z projektem tj. http-server czy npm-check-updates.
Drugi sposób to instalowanie zależności z flagą --save
, bądź skróconą wersją -S
. Powoduje to dodanie zależności do obiektu dependencies
. W tym obiekcie przechowywane są definicje dla zależności wykorzystywanych w wersji produkcyjnej naszej aplikacji. Każda zależność definiowana jest jako para wartości — nazwa zależności i jej wersja.
Trzecią opcją jest skorzystanie z flagi --save-dev
lub skróconej wersji -D
, co oznacza, że paczka zostanie zainstalowana jako zależność developerska. Takie zależności przechowywane są w obiekcie devDependencies
. Zależności developerskie, to takie, które wykorzystywane są podczas pracy nad projektem, lecz nie znajdują się w produkcyjnej wersji aplikacji. Przykładowe zależności developerskie to wszelkiego rodzaju bundlery, test runnery, lintery itd.
Wersjonowanie
Najczęściej spotykanym formatem wersjonowania paczek jest format major.minor.patch. Taki format dzieli wersję na trzy części:
- major — aktualizacja tej części wersji wskazuje, że w zależności zaszły zmiany niekompatybilne względem poprzedniej wersji.
- minor — do zależności dodane zostały nowe funkcjonalności, kompatybilne względem poprzedniej wersji.
- patch — wersja zawiera poprawki z zachowaniem kompatybilności wstecznej.
Taki sposób wersjonowania nazywany jest wersjonowaniem semantycznym (semantic versioning). Więcej o wersjonowaniu semantycznym możesz przeczytać na semver.org.
Przy instalacji zależności można zdefiniować wersję do zainstalowania na kilka sposobów:
1.0.0
– w takim wypadku zostanie zainstalowana dokładnie ta wersja paczki.~1.0.0
– zainstalowana zostanie zdefiniowana wersja lub wyższa, jeśli istnieje wyższa wersja patch (np.1.0.2
).^1.0.0
– zainstalowana zostanie zdefiniowana wersja lub wyższa, jeśli istnieje wyższa wersja minor, lub patch (np.1.1.2
).
Aktualizacja i usuwanie zależności
Zależności w projekcie można aktualizować poleceniem npm update
. Alternatywnie można też wykorzystać zależność npm-check-updates, która pozwala na sprawdzenie czy istnieje nowsza wersja dla zainstalowanych zależności.
Usuwanie paczek odbywa się za pomocą polecenia npm uninstall
. Tutaj również możemy skorzystać z flag --save
i --save-dev
i ich skróconych alternatyw. Oczywiście można też usunąć zależność ręcznie z pliku package.json
.
Lokalizacja zależności
Zainstalowane zależności zlokalizowane są w folderze node_modules
. Zazwyczaj jest to największy i najcięższy folder w naszym projekcie. Zawartości folderu node_modules
nie umieszczamy ani na serwerze produkcyjnym, ani w repozytorium. Nie przejmuj się też rozmiarem tego folderu. Potrafi on mieć rozmiary kilkuset MB, a czasem nawet kilku GB. Istnieją rozwiązania takie jak pnpm, które pozwalają optymalizować przestrzeń zajmowaną przez node_modules
poprzez mechanizmy linkowania i reużywania paczek.
Polecenia
W pliku package.json
istnieje możliwość definiowania poleceń. Dzięki temu za pomocą jednej komendy możliwe jest wykonanie kilku poleceń.
{
"name": "example-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --mode development --progress --hot --open",
"build": "webpack --mode production --progress"
},
"author": "Dominik Szczepaniak",
"license": "MIT",
"dependecies": {
"lodash": "^4.17.10"
},
"devDependecies": {
"webpack": "^4.16.0",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.1.4"
}
}
Zdefiniowane zostały dwa polecenia: dev
i build
. Jedno z nich powoduje uruchomienie servera developerskiego, natomiast drugie powoduje zbudowanie projektu. Polecenia używamy korzystając z polecenia npm run
, a potem nazwa polecenia, np. npm run build
.
Plik .npmrc
W pliku .npmrc
przechowywana jest konfiguracja npm. Domyślną lokalizacją dla tego pliku jest katalog domowy ( C:\Users\Nazwa_usera
w systemie Windows lub ~/
w systemach Unixowych). Po otwarciu pliku ujrzeć można rezultat wcześniej przestawionych komend związanych z inicjalizacją projektu oraz inne opcje konfiguracyjne, jeśli zostały uprzednio ustawione.
Jedną z istotniejszych możliwości konfiguracji jest zdefiniowanie domyślnego repozytorium dla paczek oraz przekazanie tokenów dostępowych. Są one konieczne w przypadku wykorzystywania prywatnych zależności oraz publikowania zależności w repozytorium npm. Konieczne tutaj będzie założenie konta w serwisie npmjs.com. Po założeniu konta zachęcam gorąco do włączenia uwierzytelniania dwuskładnikowego. Następnie należy wybrać zakładkę Access Tokens oraz kliknąć przycisk Generate New Token. W tym miejscu serwis zapyta nas o typ tokenu. Jeżeli token będzie wykorzystywany do publikowania paczek, to należy wybrać token typu Publish, w innym razie rekomenduję token Read-only. Odradzałbym wykorzystanie tokenów Automatic, chyba że jest to absolutnie konieczne. Tego typu tokeny nie wymagają wspomnianego już dwuskładnikowego uwierzytelniania, które oprócz dodatkowej warstwy bezpieczeństwa chroni także przed omyłkowym opublikowaniem paczki. Po wybraniu typu tokenu należy kliknąć Generate Token oraz koniecznie skopiować token, gdyż jego zawartość nie będzie wyświetlona nigdy więcej!
Po skopiowaniu tokenu, należy umieścić go w pliku .npmrc
w następujący sposób.
//registry.npmjs.org/:_authToken=twój-access-token
Od teraz pobieranie prywatnych paczek oraz publikowanie paczek stoją przed nami otworem!
Publikowanie zależności
Publikowanie zależności jest banalnie proste. Pierwszym krokiem powinno być zdefiniowanie zawartości paczki. W pliku package.json
należy dodać pole files
, które będzie zawierało wszystkie pliki, które mają znaleźć się w opublikowanej paczce.
{
"name": "example-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"files": [
"/dist",
"/assets"
],
"scripts": {
"dev": "webpack-dev-server --mode development --progress --hot --open",
"build": "webpack --mode production --progress"
},
"author": "Dominik Szczepaniak",
"license": "MIT",
"dependecies": {
"lodash": "^4.17.10"
},
"devDependecies": {
"webpack": "^4.16.0",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.1.4"
}
}
Następnie zachęcam do wywołania polecenia npm pack
. W rezultacie zostanie utworzony plik z paczką. Dzięki temu możemy sprawdzić, co ostatecznie znajdzie się w opublikowanej paczce. Zachęcam też do utworzenia pliku README.md
, którego zawartość będzie pokazana na stronie paczki w serwisie npmjs.com. Jeśli wszystko się zgadza, to można wywołać polecenie npm publish
. W przypadku gdy włączono uwierzytelnianie dwuskładnikowe, konieczne będzie potwierdzenie operacji np. kodem z aplikacji 2FA.
Alternatywy dla npm
Zarówno dla repozytorium zależności, jak i samego menadżera istnieją alternatywy. Alternatywne menadżery paczek, które możesz wykorzystać to yarn i pnpm. Z kolei alternatywami dla repozytorium paczek są:
- GitHub Packages — pozwala zamieścić paczkę w obrębie konkretnego repozytorium (zarówno paczki publiczne, jak i prywatne).
- Verdaccio — jest to lokalne, prywatne repozytorium paczek. Może być przydatne, na przykład w przypadku gdy obawiamy się wycieku zawartości naszych zależności.
Myślę, że w tym momencie jesteś gotów, aby stworzyć swój pierwszy projekt z wykorzystaniem! Jeśli masz jakieś uwagi, pytania lub wątpliwości napisz mi o tym w komentarzu!
Dzięki wielkie za ten artykuł! 🙂 Będę do niego często wracał, aby odświeżyć podstawy.
> Npm czyli node package manager
No właśnie nie. npm to npm → https://www.quora.com/I-keep-hearing-NPM-doesnt-stand-for-Node-Package-Manager-what-does-it-stand-for
Mimo że wersja z Node Package Manager jest powtarzana jak mantra nawet w publikacjach takich wydawnictw jak O’Reilly, nie zmienia to faktu, że jest to błąd.
Dobrze że o tym piszesz, sam do tej pory żyłem w błędzie 🙂
Dzięki, już poprawiam!
Warto tez wiedzieć jak działa npm link. Ja często robię małe statyczne strony, gdzie chętnie korzystam z preprocesorów CSS, Browserify i innych mniejszych pierdółek. Folder node_modules najmuje mi prawie 100mb. Niby nie duzo, ale po co za każdym razem to instalować. Zainstalowałem najczęściej używane paczki globalnie, a przy tworzeniu nowego projektu tylko do nich linkuje. Np:
npm link gulp gulp-sass gulp-plumber gulp-autoprefixer gulp-remove-empty-lines bs-html-injector browser-sync gulp-html-partial gulp-changed
Rach ciach i gotowe. Oczywiście zdaje sobie sprawę z tego, że czasami pożądana jest lokalna instalacja paczek, ale warto wiedzieć, że jest i taka opcja.
Z innych przydatnych rzeczy to komenda, która listuje zainstalowane paczki npm w systemie (globalnie): npm list -g –depth=0
Super! Dzięki za wartościowy komentarz!
Czad! 🙂 dzięki