Pracujesz nad biblioteką JavaScript i za każdym razem, gdy zmieniasz jej kod, musisz ponownie ją budować lub instalować? Lokalne linkowanie pakietu pozwala podłączyć katalog biblioteki bezpośrednio do aplikacji, dzięki czemu zmiany są widoczne niemal od razu. Pokażę, jak działa ten mechanizm, jak skonfigurować go krok po kroku, kiedy uważać na konflikty zależności i czym zastąpić go w większym projekcie.
Najważniejsze informacje o lokalnym linkowaniu pakietów
- Cel: testowanie lokalnej biblioteki npm w aplikacji bez publikowania jej w rejestrze.
- Mechanizm: npm tworzy dowiązanie symboliczne do katalogu pakietu.
- Workflow: najpierw rejestrujesz bibliotekę lokalnie, a potem podłączasz ją w projekcie korzystającym z pakietu.
-
Ograniczenie: link nie jest domyślnie zapisywany w
package.json, więc nie nadaje się jako jedyna konfiguracja zespołu. - Alternatywa: w monorepo zwykle lepiej sprawdzają się workspaces.

Co robi lokalne linkowanie pakietu
Mechanizm tworzy dowiązanie symboliczne, czyli specjalny wpis wskazujący na inny katalog na dysku. Aplikacja widzi bibliotekę tak, jakby znajdowała się w jej własnym folderze node_modules, ale faktyczne pliki nadal leżą w katalogu projektu biblioteki.
To rozwiązanie jest szczególnie wygodne, gdy rozwijam jednocześnie komponent UI, bibliotekę narzędziową albo wewnętrzny moduł używany przez kilka aplikacji. Zmiana w kodzie źródłowym może być od razu dostępna dla aplikacji, chociaż czasem trzeba jeszcze uruchomić build lub watcher, jeśli pakiet korzysta z kompilacji TypeScriptu albo bundlera.
Linkowanie nie publikuje pakietu, nie wysyła go do rejestru i nie tworzy jego kopii. To wyłącznie lokalna konfiguracja środowiska deweloperskiego, dlatego po usunięciu dowiązania aplikacja przestaje korzystać z lokalnych plików.
Jak połączyć bibliotekę z aplikacją krok po kroku
Standardowy proces składa się z dwóch poleceń. Pierwsze uruchamiasz w katalogu biblioteki, a drugie w projekcie, który ma z niej korzystać.
cd ../biblioteka-ui
npm link
cd ../aplikacja-demo
npm link nazwa-pakietu
W pierwszym miejscu npm zapisuje globalne dowiązanie do biblioteki. W drugim tworzy wpis w node_modules aplikacji i wskazuje na wcześniej zarejestrowany pakiet. Nazwa użyta w drugim poleceniu musi odpowiadać wartości pola name w pliku package.json, a niekoniecznie nazwie katalogu.
Przykładowy fragment konfiguracji biblioteki może wyglądać tak:
{
"name": "@firma/biblioteka-ui",
"version": "0.1.0",
"main": "dist/index.js"
}
W takim przypadku aplikacja powinna odwoływać się do pełnej nazwy zakresowej, czyli @firma/biblioteka-ui. Po podłączeniu sprawdzam import w aplikacji i uruchamiam test lub serwer deweloperski. Jeśli moduł nie jest znajdowany, najpierw weryfikuję nazwę pakietu, ścieżkę wejściową main oraz to, czy katalog dist faktycznie został wygenerowany.
Co dzieje się z package.json i node_modules
Najczęstsze zaskoczenie polega na tym, że lokalne dowiązanie nie zapisuje się domyślnie w package.json. To zamierzone zachowanie. Link ma służyć do tymczasowego testowania własnego kodu, a nie zastępować regularną zależność projektu.
| Rozwiązanie | Co trafia do projektu | Kiedy ma sens |
|---|---|---|
| Dowiązanie symboliczne | Wpis w node_modules wskazujący na lokalny katalog |
Szybki development i testowanie zmian |
Zależność file:
|
Ścieżka do lokalnego pakietu zapisana w konfiguracji | Kontrolowane użycie lokalnej paczki, gdy ścieżka jest dostępna dla zespołu |
| Workspace | Automatyczne powiązanie pakietów w jednym repozytorium | Monorepo i kilka współdzielonych bibliotek |
| Pakiet z rejestru | Wersja pobrana według zakresu semver | CI/CD, produkcja i praca całego zespołu |
Można wymusić zapis lokalnej referencji za pomocą opcji --save, ale robię to tylko wtedy, gdy wszyscy pracują na zgodnym układzie katalogów. W przeciwnym razie ktoś sklonuje repozytorium w innym miejscu i otrzyma niedziałającą ścieżkę.
Do sprawdzenia efektu używam zwykle npm ls nazwa-pakietu. Jeśli wynik pokazuje połączenie z lokalnym katalogiem, aplikacja korzysta z podpiętej wersji. Warto też pamiętać, że biblioteka może wymagać własnego procesu budowania, więc samo dowiązanie nie oznacza automatycznej konwersji plików źródłowych.
Typowe problemy i sposoby ich rozwiązania
Pakiet nie został znaleziony
Najczęściej winna jest rozbieżność między nazwą folderu a polem name w package.json. Sprawdzam też, czy polecenie zostało uruchomione w odpowiednim katalogu oraz czy aplikacja używa właściwego workspace albo właściwej wersji npm.
Zmiany w bibliotece nie są widoczne
Dowiązanie może działać poprawnie, ale aplikacja nadal ładuje stary plik z katalogu wyjściowego. W takim przypadku uruchamiam ponownie skrypt build lub watcher, a potem sprawdzam pola main, module i exports. Problemem bywa również cache bundlera, który trzeba wyczyścić.
Występuje błąd związany z Reactem
Podłączona biblioteka może mieć własną kopię Reacta, niezależną od kopii w aplikacji. Efektem bywają komunikaty o nieprawidłowym użyciu hooków. W bibliotece React powinien zwykle znajdować się w peerDependencies, a wersje zależności w obu projektach powinny być zgodne.
Przeczytaj również: Pętla while w JavaScript - Jak używać i unikać błędów?
Link trzeba usunąć
W aplikacji można usunąć lokalne podłączenie poleceniem npm unlink nazwa-pakietu. Jeśli chcesz wyczyścić także globalny wpis, wykonaj usuwanie w trybie globalnym, a potem zainstaluj pakiet ponownie ze źródła używanego przez projekt.
Na Windows dodatkową przeszkodą mogą być uprawnienia systemowe albo ograniczenia systemu plików. npm tworzy tam czasem skróty typu .cmd dla plików wykonywalnych, a konfiguracja może zachowywać się inaczej niż na macOS lub Linuksie.
Kiedy lepiej użyć workspaces
Jeśli biblioteka i aplikacja znajdują się w jednym repozytorium, ręczne linkowanie szybko przestaje być wygodne. W takiej sytuacji konfiguruję workspaces, czyli mechanizm npm do zarządzania wieloma pakietami z jednego katalogu głównego.
{
"private": true,
"workspaces": [
"packages/*",
"apps/*"
]
}
Po instalacji npm rozpoznaje pakiety należące do workspace i sam tworzy odpowiednie powiązania. Zyskujesz wtedy wspólny lockfile, prostsze skrypty oraz konfigurację widoczną dla całego zespołu. To rozwiązanie jest mniej podatne na błąd wynikający z różnego układu katalogów na komputerach programistów.
Ręczne dowiązanie wybieram głównie wtedy, gdy pracuję nad dwoma niezależnymi repozytoriami. Workspaces mają więcej sensu w monorepo, a pakiet z rejestru pozostaje właściwym wyborem dla testów CI, wdrożeń i środowiska produkcyjnego.
Najbezpieczniejszy sposób pracy z lokalną biblioteką
Traktuję lokalne linkowanie jako narzędzie do szybkiej iteracji, a nie jako docelowy sposób dostarczania zależności. Najpierw testuję zmiany na dowiązaniu, później sprawdzam bibliotekę po zbudowaniu paczki lub zainstalowaniu konkretnej wersji.
Przed zatwierdzeniem zmian usuwam lokalne połączenie i upewniam się, że aplikacja działa z deklaracji zapisanych w package.json oraz package-lock.json. Taki prosty etap kontrolny często ujawnia brakującą zależność, błędny wpis exports albo problem, który lokalne dowiązanie przypadkiem maskowało.