Czy powinienem zameldować się w module node_modules, aby uruchomić git podczas tworzenia aplikacji node.js na Heroku?

368

Postępowałem zgodnie z podstawowymi instrukcjami dotyczącymi uruchamiania pliku node.js na Heroku tutaj:

https://devcenter.heroku.com/categories/nodejs

Te instrukcje nie nakazują tworzenia .gitignore node_modules, a zatem sugerują, że moduły node_modu powinny być zalogowane do git. Po dołączeniu do węzła modułów w git moja aplikacja dla początkujących działała poprawnie.

Kiedy poszedłem za bardziej zaawansowanym przykładem:

https://devcenter.heroku.com/articles/realtime-polyglot-app-node-ruby-mongodb-socketio https://github.com/mongolab/tractorpush-server (źródło)

Polecił mi dodać węzeł_modules do .gitignore. Więc usunąłem node_modules z git, dodałem go do .gitignore, a następnie ponownie wdrożyłem. Tym razem wdrożenie się nie powiodło:

-----> Heroku receiving push
-----> Node.js app detected
-----> Resolving engine versions
       Using Node.js version: 0.8.2
       Using npm version: 1.0.106
-----> Fetching Node.js binaries
-----> Vendoring node into slug
-----> Installing dependencies with npm
       Error: npm doesn't work with node v0.8.2
       Required: node@0.4 || 0.5 || 0.6
           at /tmp/node-npm-5iGk/bin/npm-cli.js:57:23
           at Object.<anonymous> (/tmp/node-npm-5iGk/bin/npm-cli.js:77:3)
           at Module._compile (module.js:449:26)
           at Object.Module._extensions..js (module.js:467:10)
           at Module.load (module.js:356:32)
           at Function.Module._load (module.js:312:12)
           at Module.require (module.js:362:17)
           at require (module.js:378:17)
           at Object.<anonymous> (/tmp/node-npm-5iGk/cli.js:2:1)
           at Module._compile (module.js:449:26)
       Error: npm doesn't work with node v0.8.2
       Required: node@0.4 || 0.5 || 0.6
           at /tmp/node-npm-5iGk/bin/npm-cli.js:57:23
           at Object.<anonymous> (/tmp/node-npm-5iGk/bin/npm-cli.js:77:3)
           at Module._compile (module.js:449:26)
           at Object.Module._extensions..js (module.js:467:10)
           at Module.load (module.js:356:32)
           at Function.Module._load (module.js:312:12)
           at Module.require (module.js:362:17)
           at require (module.js:378:17)
           at Object.<anonymous> (/tmp/node-npm-5iGk/cli.js:2:1)
           at Module._compile (module.js:449:26)
       Dependencies installed
-----> Discovering process types
       Procfile declares types -> mongod, redis, web
-----> Compiled slug size is 5.0MB
-----> Launching... done, v9

Uruchomienie „heroku ps” potwierdza awarię. Ok, nie ma problemu, więc wycofałem zmianę, dodałem node_module z powrotem do repozytorium git i usunąłem go z .gitignore. Jednak nawet po przywróceniu nadal pojawia się ten sam komunikat o błędzie podczas wdrażania, ale teraz aplikacja działa ponownie poprawnie. Uruchomienie „heroku ps” mówi mi, że aplikacja jest uruchomiona.

Więc moje pytanie brzmi: jaki jest właściwy sposób to zrobić? Uwzględnić moduły_węzła czy nie? I dlaczego nadal pojawia się komunikat o błędzie podczas wycofywania? Domyślam się, że repozytorium git jest w złym stanie po stronie Heroku?

Jason Griffin
źródło
10
Jestem właścicielem języka Node w Heroku, a odpowiedź jest prosta: Nie. Nie node_modulesmelduj się w aplikacjach Heroku.
hunterloftis
@hunterloftis 'Nie sprawdzaj modułów węzła w ' lub 'Nie sprawdzaj modułów węzła w '? Aby to wyjaśnić, jako właściciel języka Node w Heroku, czy chcesz, abyśmy przesyłali całe nasze moduły node_modu za pośrednictwem naszego git push, czy nie? Wolę tego nie robić z powodu marnowania przepustowości i faktu, że Heroku dostanie je na zapleczu mojego git push; musiałem jednak ręcznie edytować pliki w moim module_węzła, aby Heroku załadował moją aplikację. Dlatego musiałem zignorować moduły node_modules minus cały moduł, który zawierał mój edytowany plik, aby go uruchomić.
ZStoneDPM

Odpowiedzi:

400

Druga aktualizacja

FAQ nie jest już dostępne.

Z dokumentacji shrinkwrap:

Jeśli chcesz zablokować określone bajty zawarte w pakiecie, na przykład aby mieć 100% pewności co do możliwości odtworzenia wdrożenia lub kompilacji, powinieneś sprawdzić swoje zależności w kontroli źródła lub zastosować inny mechanizm, który może zweryfikować treść zamiast wersji.

Shannon i Steven wspomnieli o tym wcześniej, ale myślę, że powinna być częścią przyjętej odpowiedzi.


Aktualizacja

Źródło wymienione dla poniższej rekomendacji zostało zaktualizowane . Nie zalecają już zatwierdzenia node_modulesfolderu.

Zwykle nie. Pozwól npm na rozwiązanie zależności dla twoich pakietów.

W przypadku wdrożonych pakietów, takich jak strony internetowe i aplikacje, należy użyć npm shrinkwrap, aby zablokować pełne drzewo zależności:

https://docs.npmjs.com/cli/shrinkwrap


Oryginalny post

Dla odniesienia, npm FAQ wyraźnie odpowiada na twoje pytanie:

Sprawdź node_modules w git dla rzeczy, które wdrażasz, takich jak strony internetowe i aplikacje. Nie sprawdzaj modułów node_module w git dla bibliotek i modułów przeznaczonych do ponownego użycia. Użyj npm do zarządzania zależnościami w środowisku deweloperskim, ale nie w skryptach wdrażania.

i dla dobrego uzasadnienia, przeczytaj post Mikeala Rogersa na ten temat .


Źródło: https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git

Kostia
źródło
13
To nie jest poprawne - w rzeczywistości jest to bardzo zły pomysł. Jeśli programujesz w systemie Windows, a następnie wdrażasz w systemie Linux, podczas wdrażania musisz odbudować moduły node_modules. Co oznacza - chaos. Dużo zmodyfikowanych plików i nie mam pojęcia, co robić.
user3690202
8
To nie jest możliwe - niektórzy z naszych programistów opracowują okna docelowe, inni celują w Linux, ale mają tę samą bazę kodu. Najlepszym rozwiązaniem byłoby nie zatwierdzanie modułów węzłów - ups.
user3690202
7
@ user3690202 Wygląda na to, że masz raczej niekonwencjonalny przypadek niż normę, więc powiedzenie „to nie jest poprawne” jest prawdopodobnie przesadą. Powiedziawszy to, nie jestem pewien, jaki jest twój dokładny przypadek użycia, ale nie mogę wymyślić żadnego powodu, aby używać zarówno Windows, jak i Linuksa do programowania. Trzymaj się jednego i przeprowadzaj testy lub kontrolę jakości na wszystkich platformach swojego wsparcia.
Kostia
16
@Kostia Nasz przypadek użycia jest dość powszechny. Jesteśmy wolontariuszami i korzystamy z własnych maszyn, a nie firmowych. Wydaje się to dość powszechną sytuacją w przypadku oprogramowania typu open source.
Adam
4
@Adam stycznie, czy możesz dodać kompilowane pliki .gitignore? W ten sposób źródło jest w git, a żadne skompilowane komponenty nie są, podobnie jak distlub outputfoldery są gitignorowane w projektach typu chrząknięcie i przełknięcie.
Kostia
160

Moim największym problemem ze nie sprawdzając node_modulesw git jest to, że 10 lat w dół drogi, gdy aplikacja produkcja jest nadal w użyciu, może być npm dookoła. Lub npm może ulec uszkodzeniu; lub opiekunowie mogą zdecydować o usunięciu biblioteki, na której polegasz, z ich repozytorium; lub używana wersja może zostać obcięta.

Można to złagodzić za pomocą menedżerów repozytoriów, takich jak maven, ponieważ zawsze możesz użyć własnego lokalnego Nexusa lub Artifactory do utrzymania kopii lustrzanej za pomocą używanych pakietów. O ile rozumiem, taki system nie istnieje dla npm. To samo dotyczy menedżerów bibliotek po stronie klienta, takich jak Bower i Jamjs.

Jeśli pliki zostały przypisane do własnego repozytorium git, możesz je zaktualizować, kiedy chcesz, i masz komfort powtarzalnych kompilacji oraz wiedzę, że Twoja aplikacja nie ulegnie awarii z powodu działań innych firm.

Jonathan
źródło
10
Wiele opcji dzisiaj: Nexus ( wystawa.sonatype.org/browse/NEXUS-5852 ), Artifactory ( jfrog.com/jira/browse/RTFACT-5143 ), npm_lazy ( github.com/mixu/npm_lazy ), npm-lazy- mirror ( npmjs.org/package/npm-lazy-mirror ) itp.
Johann
4
Cytat z npmjs FAQ: „Jeśli masz paranoję na punkcie polegania na ekosystemie npm, powinieneś uruchomić prywatne lustro npm lub prywatną pamięć podręczną.”. Myślę, że to wskazuje na problem, który masz na myśli, prawda?
Taylan
2
Npm nie zniknie z dnia na dzień, więc korzyść tak naprawdę nie łączy się z utratą przejrzystości w historii zmian i ogromnym rozmiarem pakietu. Jeśli ktoś buduje aplikację, która według niego będzie nadal aktywna za 10 lat, uzasadnione jest oczekiwanie, że zostanie ona po drodze poddana dużej konserwacji. Argument o awariach NPM jest jednak znacznie lepszym argumentem, chociaż prawdopodobnie istnieją lepsze sposoby na ograniczenie tego ryzyka niż zobowiązanie się do źródła.
Sam P
3
Nawet miesiąc później jest niebezpieczny, jeśli nie popełnisz swoich zależności (najlepiej w oddzielnym repozytorium). Jak znalazłem pewnego ranka, kiedy sklonowałem jeden z moich projektów i odkryłem, że wersja pakietu została usunięta z npm. Spędziłem pół dnia zmieniając wszystkie wersje zależności kaskadowych, aby aktualizacja NPM działała i budowała ponownie.
Richard
67

Należy nie zawierają node_modules w swojej .gitignore(lub raczej ty powinien zawierać node_modules w swoim źródle rozmieszczonych Heroku).

Jeżeli node_modules:

  • istnieje, a następnie npm installużyje tych bibliotek lib i odbuduje wszelkie zależności binarne npm rebuild.
  • nie istnieje, wówczas npm installbędzie musiał pobrać wszystkie zależności, co wydłuży czas kompilacji ślimaka.

Zobacz źródło kompilacji Node.js, aby uzyskać dokładne instrukcje

Jednak pierwotny błąd wygląda na niezgodność między wersjami npmi node. Dobrym pomysłem jest zawsze jawne ustawianie enginessekcji packages.jsonzgodnie z tym przewodnikiem, aby uniknąć tego rodzaju sytuacji:

{
  "name": "myapp",
  "version": "0.0.1",
  "engines": {
    "node": "0.8.x",
    "npm":  "1.1.x"
  }
}

Zapewni to parytet tworzenia / produkcji i zmniejszy prawdopodobieństwo takich sytuacji w przyszłości.

Ryan Daigle
źródło
Dzięki za pomoc Ryan. To mi pominęło błąd wersji npm, ale teraz kończy się niepowodzeniem podczas kompilacji pakietu redis. Komunikat o błędzie to „OSError: [Errno 2] Brak takiego pliku lub katalogu: '/ Users / Jason / tastemade / tastebase / node_modules / redis-url / node_modules / redis / node_modules / hiredis / build'”. Wygląda na to, że używa ścieżki z mojego lokalnego urządzenia na serwerach heroku. Czy w module node_modules są pewne pliki, które muszę dodać do .gitignore?
Jason Griffin
Nie jestem pewien, co się dzieje z tą konkretną biblioteką, ale w tym przypadku spróbuję wykluczyć node_modules z git i sprawdzić, czy to pomoże (zmuszając npm do pobrania wszystkiego i zapewnienie świeżego środowiska kompilacji).
Ryan Daigle,
@RyanDaigle Najlepsza praktyka teraz (listopad 2013) zalecana zarówno przez npm ( npmjs.org/doc/… ), jak i heroku ( devcenter.heroku.com/articles/… ) to sprawdzanie modułów node_mules, aby uzyskać git. Czy zaktualizowałbyś swoją odpowiedź (ponieważ ma najwyższe rozliczenia)?
Tim Diggins,
Naciskając na heroku otrzymasz wynik „-----> Buforowanie katalogu node_modules dla przyszłych kompilacji”. Ma to na celu skrócenie przyszłej kompilacji ślimaków.
ph3nx
Mam problem z tym, że ścieżka pliku node_modules jest zbyt długa, aby ją zatwierdzić. Git nie znajdzie plików.
Kod Faraon
22

Zamierzałem zostawić to po tym komentarzu: Czy powinienem zameldować się w node_modules, aby git podczas tworzenia aplikacji node.js na Heroku?

Ale przepełnienie stosu formatowało to dziwnie. Jeśli nie masz identycznych maszyn i sprawdzasz w module node_modules, zrób .gitignore na rozszerzeniach natywnych. Nasz .gitignore wygląda następująco:

# Ignore native extensions in the node_modules folder (things changed by npm rebuild)
node_modules/**/*.node
node_modules/**/*.o
node_modules/**/*.a
node_modules/**/*.mk
node_modules/**/*.gypi
node_modules/**/*.target
node_modules/**/.deps/
node_modules/**/build/Makefile
node_modules/**/**/build/Makefile

Sprawdź to, najpierw sprawdzając wszystko, a następnie poproś innego programistę o wykonanie następujących czynności:

rm -rf node_modules
git checkout -- node_modules
npm rebuild
git status

Upewnij się, że żadne pliki nie uległy zmianie.

ibash
źródło
Właśnie to dodałem. Rozwiązałem mój problem. Windows github ciągle się zawieszał, próbując przejść przez ponad 7000 plików node_module: /
Batman
10

Uważam, że npm installnie powinno to działać w środowisku produkcyjnym. Jest kilka rzeczy, które mogą pójść nie tak - awaria npm, pobieranie nowszych zależności (wydaje się, że shrinkwrap to rozwiązało) to dwie z nich.

Z drugiej strony, node_modulesnie należy popełniać na git. Poza dużymi rozmiarami, commits, w tym również, mogą stać się rozpraszające.

Najlepsze rozwiązania byłyby następujące: npm installpowinny działać w środowisku CI podobnym do środowiska produkcyjnego. Wszystkie testy zostaną uruchomione i zostanie utworzony skompresowany plik wydania, który będzie zawierał wszystkie zależności.

użytkownik2468170
źródło
Dlaczego miałbyś mieć krok działający na CI, który nie działałby jako część twojego wdrożenia? Oznacza to, że nie masz parzystości między dwoma systemami! Jak mówi odpowiedź powyżej - zatwierdź folder po prostu zignoruj ​​rozszerzenia natywne, w ten sposób jesteś objęty np.
Awariami
1
Dzięki za komentarz. Uważam, że moduły node_modu, które działają na twoim serwerze produkcyjnym, powinny być generowane z instalacji npm, a nie z tego, co zatwierdzili deweloperzy. Folder dev_nod_modules niekoniecznie pasuje do zawartości package.json.
user2468170,
8

Używałem zarówno zatwierdzania folderu node_modules, jak i zawijania. Oba rozwiązania nie sprawiły mi radości.

W skrócie: zatwierdzone moduły node_dodają zbyt dużo szumów do repozytorium.
Plik shrinkwrap.json nie jest łatwy do zarządzania i nie ma gwarancji, że jakiś projekt owinięty w folię zostanie zbudowany za kilka lat.

Odkryłem, że Mozilla używa osobnego repozytorium dla jednego ze swoich projektów https://github.com/mozilla-b2g/gaia-node-modules

Tak więc nie zajęło mi dużo czasu wdrożenie tego pomysłu w narzędziu CLI węzła https://github.com/bestander/npm-git-lock

Tuż przed każdą kompilacją dodaj
npm-git-lock --repo [[email protected]: your / dedykowane / node_modules / git / repository.git]

Obliczy skrót pakietu.json i albo sprawdzi zawartość node_modules ze zdalnego repozytorium, albo, jeśli jest to pierwsza kompilacja tego pakietu.json, wykona czyszczenie npm installi przekaże wyniki do zdalnego repozytorium.

bestander
źródło
5

To, co zadziałało, to jawne dodanie wersji npm do package.json („npm”: „1.1.x”) i NIE sprawdzanie modułów node_mules do git. Wdrożenie może być wolniejsze (ponieważ pobiera pakiety za każdym razem), ale nie mogłem zmusić pakietów do skompilowania, gdy były zalogowane. Heroku szukał plików, które istniały tylko na moim lokalnym komputerze.

Jason Griffin
źródło
Jeśli uważasz, że moja odpowiedź była prawidłowa, proszę ją zaakceptować? Dziękuję Ci!
Ryan Daigle,
W przypadku, gdy jest to nadal przedmiotem debaty, rzuciłbym okiem na ten post stackoverflow, który jest prawie duplikatem twojego pytania powyżej: stackoverflow.com/questions/11459733/... Zasadniczo wydaje się, że konwencja polega na sprawdzaniu modułów node_modules i zarządzaj lokalnie swoimi wersjami tych modułów. Wydaje się to dość rozsądne i być może najbardziej zwięzłe wyjaśnienie jest takie: mikealrogers.com/posts/nodemodules-in-git.html Powodzenia!
warriorpostman
3

Zamiast sprawdzać w module node_modules, utwórz plik package.json dla swojej aplikacji.

Plik package.json określa zależności aplikacji. Heroku może następnie powiedzieć npm, aby zainstalował wszystkie te zależności. Samouczek, do którego prowadzisz link, zawiera sekcję dotyczącą plików package.json.

matzahboy
źródło
Mam pakiet.json. Ma następujące elementy: {„nazwa”: „przykład-węzła”, „wersja”: „0.0.1”, „zależności”: {„express”: „2.5.x”, „redis-url”: „0.1. 0 ”,„ mongodb ”:„> = 0.9.9 ”},„ silniki ”: {„ node ”:„ 0.8.x ”}}
Jason Griffin
Zrobiłem na moim lokalnym polu, aby utworzyć katalog node_modules. Właśnie to zarejestrowałem, następnie usunąłem, a następnie dodałem ponownie.
Jason Griffin
Po dokładniejszym przyjrzeniu się samouczkowi wydaje się, że zatwierdzają moduły node_modules. W takim przypadku nie jestem pewien, czy istnieje sposób, aby nie zatwierdzać modułów_węzła. Przepraszamy
matzahboy,
3

Korzystam z tego rozwiązania:

  1. Utwórz osobne repozytorium, które będzie przechowywane node_modules. Jeśli masz natywne moduły, które powinny być budowane dla konkretnej platformy, utwórz osobne repozytorium dla każdej platformy.
  2. Załącz te repozytoria do repozytorium projektu za pomocą git submodule:

git submodule add .../your_project_node_modules_windows.git node_modules_windows

git submodule add .../your_project_node_modules_linux_x86_64 node_modules_linux_x86_64

  1. Utwórz link z katalogu specyficznego node_modulesdla platformy node_modulesi dodaj node_modulesdo .gitignore.
  2. Uruchom npm install.
  3. Zatwierdź zmiany w repozytorium submodułu.
  4. Zatwierdź zmiany w repozytorium projektu.

Możesz więc łatwo przełączać się między node_modulesróżnymi platformami (na przykład, jeśli tworzysz system OS X i wdrażasz system Linux).

mixel
źródło
3

Od https://web.archive.org/web/20150212165006/http://www.futurealoof.com/posts/nodemodules-in-git.html :

Edycja: oryginalny link był ten, ale jest już martwy. Dzięki @Flavio za zwrócenie na to uwagi.

Przypomnę.

  • Sprawdzaj tylko moduły node_ododu dla aplikacji, które wdrażasz, a nie pakiety wielokrotnego użytku, które utrzymujesz.
  • Wszelkie skompilowane zależności powinny mieć zarejestrowane źródło, a nie cele kompilacji i powinny zostać odbudowane npm $ przy wdrażaniu.

Moja ulubiona część:

Wszyscy, którzy dodaliście node_modules do swojego gitignore, usuńcie to gówno, dziś jest to artefakt ery, z której zbyt chętnie zostawiamy. Era globalnych modułów jest martwa.

Benjamin Crouzier
źródło
Wygląda na to, że witryna, do której linkujesz, wygasła i jest teraz pełna wyłudzających reklam. Chciałbym, aby te reklamy były „artefaktami epoki, w której wszyscy bylibyśmy zbyt szczęśliwi, aby pozostawić je w tyle”.
Flavio radzi sobie
1
@FlavioCopes Zaktualizowałem moją odpowiedź linkiem z Wayback Machine.
Benjamin Crouzier
2

http://nodejs.org/api/modules.html

[...] węzeł rozpoczyna się w katalogu nadrzędnym bieżącego modułu, dodaje /node_modulesi próbuje załadować moduł z tej lokalizacji.

Jeśli nie zostanie tam znaleziony, zostanie przeniesiony do katalogu nadrzędnego i tak dalej , dopóki nie zostanie osiągnięty katalog główny drzewa.

Jeśli wdrażasz własne moduły specyficzne dla aplikacji, możesz przechowywać te ( i tylko te ) w swojej aplikacji /node_modules. I przenieś wszystkie pozostałe zależności do katalogu nadrzędnego.

Ten przypadek użycia jest całkiem niesamowity, pozwala zachować moduły stworzone specjalnie dla Twojej aplikacji i nie zaśmieca aplikacji zależnością, którą można zainstalować później.

laggingreflex
źródło
1

scenariusz 1:

Jeden scenariusz: używasz pakietu, który jest usuwany z npm. Jeśli masz wszystkie moduły w folderze node_modules, nie będzie to dla ciebie problemem. Jeśli masz tylko nazwę pakietu w pliku package.json, nie możesz go już uzyskać. Jeśli paczka ma mniej niż 24 godziny, możesz ją łatwo usunąć z npm. Jeśli jest starszy niż 24 godziny, musisz się z nim skontaktować. Ale:

Jeśli skontaktujesz się z pomocą techniczną, sprawdzi, czy usunięcie tej wersji pakietu nie spowoduje awarii innych instalacji. Jeśli tak, nie usuniemy go.

Czytaj więcej

Szanse na to są niskie, ale jest scenariusz 2 ...


scenariusz 2:

Inny scenariusz, w którym tak jest: Tworzysz wersję korporacyjną oprogramowania lub bardzo ważne oprogramowanie i piszesz w pakiecie.json:

"dependencies": {
    "studpid-package": "~1.0.1"
}

Używasz metody function1(x)tego pakietu.

Teraz twórcy pakietu studpid zmieniają nazwę metody function1(x)na function2(x)i popełniają błąd ... Zmieniają wersję swojego pakietu z 1.0.1na 1.1.0. Jest to problem, ponieważ przy npm installnastępnym wywołaniu zaakceptujesz wersję, 1.1.0ponieważ użyłeś tyldy ( "studpid-package": "~1.0.1").

Dzwonienie function1(x)może teraz powodować błędy i problemy.


Przeniesienie całego folderu node_modules (często ponad 100 MB) do repozytorium będzie kosztować miejsce w pamięci. Kilka KB (tylko pakiet.json) w porównaniu z setkami MB (pakiet.json i moduły_węzła) ... Pomyśl o tym.

Możesz to zrobić / powinieneś o tym pomyśleć, jeśli:

  • oprogramowanie jest bardzo ważne.

  • kosztuje Cię pieniądze, gdy coś zawiedzie.

  • nie ufasz rejestrowi npm. npm jest scentralizowany i teoretycznie może zostać zamknięty.

Nie musisz publikować folderu node_modules w 99,9% przypadków, jeśli:

  • tworzysz oprogramowanie tylko dla siebie.

  • coś zaprogramowałeś i po prostu chcesz opublikować wynik na GitHub, ponieważ ktoś inny może być tym zainteresowany.


Jeśli nie chcesz, aby moduły node_module znajdowały się w twoim repozytorium, po prostu utwórz .gitignoreplik i dodaj linię node_modules.

ndsvw
źródło