Jak zaimportować globalne moduły w Node? Otrzymuję komunikat „Błąd: nie można znaleźć modułu <module>”?

145

Próbuję skonfigurować Node w systemie Mac OSX Lion. Wygląda na to, że wszystko działa dobrze, ale nie mogę zaimportować żadnych modułów z mojego globalnego folderu modułów. Otrzymuję błąd,

Error: Cannot find module <module>

Jeśli uruchomię to node -e require.paths:, otrzymam odpowiedź:

[ '/usr/local/lib/node_modules',
  '/Users/Me/.node_modules',
  '/Users/Me/.node_libraries',
  '/usr/local/Cellar/node/0.4.12/lib/node' ]

Co jest poprawne, moje moduły są rzeczywiście zainstalowane w / usr / local / lib / node_modules. Jednak kiedy próbuję uruchomić skrypt, otrzymuję to:

Error: Cannot find module 'socket.io'
    at Function._resolveFilename (module.js:326:11)
    at Function._load (module.js:271:25)
    at require (module.js:355:19)
    at Object.<anonymous> (/Users/Me/node/server.js:2:10)
    at Module._compile (module.js:411:26)
    at Object..js (module.js:417:10)
    at Module.load (module.js:343:31)
    at Function._load (module.js:302:12)
    at Array.<anonymous> (module.js:430:10)
    at EventEmitter._tickCallback (node.js:126:26)

Mój .bash_profile wygląda tak:

export PATH=/usr/local/mysql/bin:$PATH
export NODE_PATH=/usr/local/lib/node_modules
export DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:/usr/local/mysql/lib/"

Naprawdę byłbym wdzięczny za pomoc, nie mam pojęcia, dlaczego nie mogę zaimportować żadnych bibliotek.

Hanpan
źródło
1
Wiesz, że nie jest to preferowany sposób robienia rzeczy, prawda?
thejh
1
Czy mógłbyś to rozwinąć? Czy masz na myśli, że nie powinienem instalować bibliotek w moim folderze globalnym?
Hanpan
3
@Hanpan: Preferowanym sposobem jest lokalna instalacja modułów, których chcesz używać za pośrednictwem require ().
thejh
1
Lepszą i bardziej aktualną odpowiedź (która nie opiera się na npm link) można znaleźć tutaj: stackoverflow.com/a/15646750/2671392
GGG
1
Jestem oldschoolowy i przyzwyczajony do instalowania bibliotek w lokalizacjach globalnych. Nigdy nie widziałem żadnego przekonującego powodu do intensywnego korzystania z instalacji lokalnej biblioteki. Klasa mongodb, którą biorę, kończy się gdzieś blisko stu małych projektów, zanim skończymy, a każdy z nich będzie zawierał głównie zduplikowany zestaw bibliotek - mongodb, express, konsolidacja itp. Przejście na języki interaktywne pozostawia depozyty lokalnych bibliotek w każdym miejscu. Muszę mieć tysiące bibliotek Scala w lokalnych repozytoriach Scala. Jak wyżej Meteor, groovy i ruby.
Stephen W. Wright,

Odpowiedzi:

116

Jeśli używasz npm> = 1.0, możesz użyć npm link <global-package>do utworzenia lokalnego łącza do pakietu już zainstalowanego globalnie. ( Uwaga: system operacyjny musi obsługiwać dowiązania symboliczne ).

Jednak nie obywa się to bez problemów.

npm link to narzędzie programistyczne. Jest świetny do zarządzania pakietami na lokalnym komputerze deweloperskim. Ale wdrażanie z łączem npm to w zasadzie pytanie o problemy, ponieważ bardzo ułatwia aktualizowanie rzeczy bez zdawania sobie z tego sprawy.

Alternatywnie możesz zainstalować pakiety zarówno lokalnie, jak i globalnie.

Aby uzyskać dodatkowe informacje, zobacz

Tadeusz Wójcik
źródło
69
Czytam to i nie mogę uwierzyć własnym oczom. Więc jeśli zainstaluję, powiedzmy express, a następnie mam 20 projektów do zbudowania na szczycie Express, muszę zainstalować go 20 razy, dla każdego z nich, w każdym folderze projektu, w kółko? Nie mam dużego doświadczenia z menedżerami pakietów, ale to trochę do bani ...
treznik
25
Zgadza się, a jeśli się nad tym zastanowić, ma to sens. Zarządzanie zależnościami lokalnie sprawia, że ​​wszystko jest niezależne i pozwala na określenie konkretnej wersji zależności dla dowolnego projektu (np. Projekt foo wymaga express 2.x, podczas gdy pasek projektu może używać express 3 beta).
grahamb
43
Przez jakiś czas starałem się zrozumieć logikę tego faktu, ale po obejrzeniu moich przyjaciół Rubiego zmagających się z globalnymi aktualizacjami pakietów, kłótni o gemsets i często po prostu nigdy nie aktualizuj, przyznałem, że lokalna instalacja zależności jest absolutnie jedynym rozsądnym sposobem na zrobienie zarządzanie pakietami .
timoxley,
3
Chciałbym narysować paralelę między tą sytuacją a sytuacją z łączeniem statycznym i bibliotekami z łączeniem dynamicznym, ponieważ dotyczy to dystrybucji oprogramowania. Weź pod uwagę, że prawie wszystkie aplikacje rozpowszechniane w sklepie iOS App Store muszą statycznie łączyć zależności, których nie zapewnia zestaw SDK systemu iOS. Dlaczego to się dzieje? Globalne piekło zależności jest bardzo realne.
Steven Lu
1
Rozumiem również, że npmpamięć podręczna (która żyje ~/.npm) ułatwi proces ponownej instalacji przeprowadzany w różnych lokalizacjach.
Steven Lu
85

Node.js używa zmiennej środowiskowej, NODE_PATHaby umożliwić określenie dodatkowych katalogów, które mają zostać uwzględnione w ścieżce wyszukiwania modułu. Możesz użyć npmsamego siebie, aby powiedzieć, gdzie są przechowywane moduły globalne za pomocą npm root -gpolecenia. Łącząc te dwa razem, możesz upewnić się, że moduły globalne są uwzględnione w ścieżce wyszukiwania za pomocą następującego polecenia (w systemie Linux)

export NODE_PATH=$(npm root --quiet -g)

Joel B.
źródło
3
Dzięki za NODE_PATHwskazówkę dotyczącą zmiennej środowiskowej. To bardzo pomogło!
rekire
7
To powinien być najważniejszy komentarz
Adam Prax,
Musiałem ustawić NODE_PATHrównoważną ścieżkę posix, aby npm działał na MSYS2. Dziękuję Ci.
Joyce Babu
Działa również z systemem Windows i Git bash. Idealny. :-)
inf3rno
To sprawia, że .node_modulesfolder można przeszukiwać, ale aby zaimportować moduły za pomocą require(), powinny one nadal być zainstalowane w lokalnym katalogu projektu (lub alternatywnie połączone za pomocą npm link). Modułów globalnych nie można importować do projektów, można stamtąd uruchamiać tylko pliki binarne / skrypty.
Prahlad Yeri
65

Możesz użyć łącza npm, aby utworzyć symboliczne łącze do pakietu globalnego w folderze projektów.

Przykład:

$ npm install -g express
$ cd [local path]/project
$ npm link express

Wszystko, co robi, to utworzenie lokalnego folderu node_modules, a następnie utworzenie ekspresowego łącza symbolicznego -> [katalog globalny] / node_modules / express, który można następnie rozwiązać za pomocą require('express')

Nick Sotiros
źródło
Czy to jest kompatybilne z różnymi systemami operacyjnymi?
UpTheCreek
Nowsze wersje systemu Windows obsługują go od tej wersji: github.com/npm/npm/commit/ ... W przypadku starszych wersji systemu Windows spróbuj npmjs.com/package/npm-junction
Alex
22

Zainstaluj dowolny pakiet globalnie, jak poniżej:

$ npm install -g replace  // replace is one of the node module.

Ponieważ ten moduł Replace jest instalowany globalnie, więc jeśli zobaczysz folder node modules, nie zobaczysz tam modułu replace i nie możesz użyć tego pakietu przy użyciu require ('replace').

ponieważ z require możesz używać tylko lokalnych modułów, które są obecne w folderze modułu twojego węzła.

Teraz, aby użyć modułu globalnego, należy połączyć go ze ścieżką modułu węzła za pomocą poniższego polecenia.

$ npm link replace

Teraz wróć i zobacz folder modułu węzła. Możesz teraz zobaczyć tam moduł zastępujący i użyć go z require ('replace') w swojej aplikacji, ponieważ jest on połączony z modułem lokalnego węzła.

Pls daj mi znać, jeśli potrzebne są dalsze wyjaśnienia.

user5341372
źródło
14

Możesz użyć require ze ścieżką do globalnego katalogu modułu jako argumentu.

require('/path/to/global/node_modules/the_module');

Na moim Macu używam tego:

require('/usr/local/lib/node_modules/the_module');

Jak dowiedzieć się, gdzie są twoje globalne moduły? -> Gdzie npm instaluje pakiety?

molwa
źródło
7

Ustawienie zmiennej środowiskowej NODE_PATH tak, aby wskazywała na twój node_modulesfolder globalny .

W systemie Windows 7 lub nowszym ścieżka jest podobna, %AppData%\npm\node_modulespodczas gdy w systemie UNIX może być podobna, /home/sg/.npm_global/lib/node_modules/ale zależy to od konfiguracji użytkownika.

Polecenie npm config get prefixmoże pomóc w ustaleniu, która jest poprawna ścieżka.

W systemach UNIX można to zrobić za pomocą następującego polecenia:

export NODE_PATH=`npm config get prefix`/lib/node_modules/
Ben Xu
źródło
0

Używam Dockera. Próbuję utworzyć obraz Dockera, który ma zainstalowane wszystkie moje zależności węzłów, ale może używać mojego lokalnego katalogu aplikacji w czasie wykonywania kontenera (bez zanieczyszczania go katalogiem lub linkiem node_modules). Powoduje to problemy w tym scenariuszu. Moim obejściem jest wymaganie od dokładnej ścieżki, w której moduł, np. Require ('/ usr / local / lib / node_modules / socket.io')

Darin London
źródło
-1

require.paths jest przestarzałe.

Przejdź do folderu swojego projektu i wpisz

npm install socket.io

to powinno zainstalować go w lokalnym folderze ./node_modules, w którym węzeł będzie go szukał.

Trzymam moje rzeczy w ten sposób:

cd ~/Sites/
mkdir sweetnodeproject
cd sweetnodeproject
npm install socket.io

Utwórz plik app.js.

// app.js
var socket = require('socket.io')

teraz uruchom moją aplikację

node app.js

Upewnij się, że używasz npm >= 1.0i node >= 4.0.

Jamund Ferguson
źródło
8
Pyta o używanie globalnie zainstalowanych pakietów npm.
UpTheCreek
@Jamund. Pokazujesz, jak używać lokalnie zainstalowanego pakietu, ale pierwotne pytanie dotyczyło pakietów globalnych.
Vitaliy Markitanov