Używanie npm do instalowania lub aktualizowania wymaganych pakietów, tak jak bundler dla rubygemów

88

Uwielbiam Bundler , jest świetny w zarządzaniu zależnościami. Uwielbiam npm , instalowanie pakietów węzłów jest łatwe! Mam aplikację nodejs i chciałbym móc określić zależności moich aplikacji i łatwo je zainstalować / zaktualizować wszędzie tam, gdzie wdrażam moją aplikację. To nie jest biblioteka, którą udostępniam, to pełnoprawna aplikacja internetowa.

Znam npm bundlepolecenie, ale wydaje mi się , że po prostu zastępuje katalog, w którym są zainstalowane pakiety.

Jestem przyzwyczajony do korzystania z pakietu w ten sposób:

# Gemfile
gem "rails", "3.0.3"

Instaluje rails v3.0.3 i wszystkie inne wymagane klejnoty na maszynie hosta tylko wtedy, gdy jeszcze nie istnieją

> bundle install

Jak mogę osiągnąć coś podobnego z npm?

Daniel Beardsley
źródło
czy moja odpowiedź nie jest tym, co chciałeś wiedzieć?
Alfred

Odpowiedzi:

147

Od npm 1.0 (który jest teraz tym, co otrzymujesz domyślnie, wykonując kroki w pliku README), „pakiet” nie jest już oddzielną rzeczą - po prostu „jak to działa”.

Więc:

  1. Umieść package.jsonplik w katalogu głównym projektu
  2. Wypisz swoje deps w tym pliku

    { "name" : "my-project"
    , "version" : "1.0.0"
    , "dependencies" : { "express" : "1.0.0" } }
    
  3. npm install Ponieważ wywołujesz to bez argumentów i nie w trybie globalnym, po prostu zainstaluje lokalnie wszystkie twoje dep.

  4. require("express") i bądź szczęśliwy.
isaacs
źródło
2
Podczas pracy zdecydowanie zalecam zmianę your_app/node_moduleskatalogu lokalnego na łącze symboliczne poza katalogiem aplikacji. Nie chcesz pobierać, kompilować i instalować każdej zależności za każdym razem, gdy wdrażasz.
Daniel Beardsley
Ok. co jeśli zapomnę zaktualizować plik package.json? Czy istnieje sposób, aby zmusić NPM do szukania nie pakietu package.json, ale pakietów, których używam w moim kodzie?
Pono
4
To nie jest do końca poprawne. NPM zainstaluje wszystkie zależności dla powyższego my-projectw ./node_modules/my-project/node_modules. Nie jestem pewien, czy istnieje wygodny sposób zainstalowania wszystkich zależności w ./node_modules Anyone?
Daniel Beardsley
@DanielBeardsley Nie sądzę, że tak działa npm. Jeśli widzisz to zachowanie i możesz je odtworzyć, napisz problem na stronie npm github.
isaacs
2
Zgadzam się z @DanielBeardsley. Cierpię na to zachowanie nawet przy npm 1.1.70
graffic
10

Edycja: dotyczy to tylko wersji npm <1.0


Trudno było to rozgryźć, ale NPM to umożliwia .

Potrzebujesz trzech komponentów

  1. Podkatalog w twoim repozytorium (tj. deps/)
  2. package.jsonPlik w powyższym katalogu, który wymienia Zależności
  3. index.jsPlik w powyższym katalogu, który wymaga od swoich zależnościami

Przykład

Wyobraź sobie, że ekspres jest Twoją jedyną zależnością

deps / package.json

Uwaga: Zwiększ numer wersji za każdym razem, gdy modyfikujesz zależności

{
  "name": "myapp_dependencies",
  "version": "0.0.1",
  "engines": {
    "node": "0.4.1"
  },
  "dependencies":{
    "express": "2.0.0beta2"
  }
}

deps / index.js

export.modules = {
  express: require('express')
  //add more
}

Teraz powinieneś być w stanie zainstalować swoje zależności za pomocą npm. Możesz nawet uczynić tę część procesu wdrażania

cd deps
npm install

Następnie w kodzie aplikacji możesz uzyskać dostęp do swojej konkretnej wersji ekspresu w następujący sposób:

var express = require('myapp_dependencies').express;
Daniel Beardsley
źródło
Dzięki, to najlepsza metoda, jaką do tej pory widziałem. Jednak czy require('express')w deps / index.js nie zaimportujemy po prostu najnowszej wersji ekspresowej, a niekoniecznie tej, którą zainstalowaliśmy? Jestem noobem nodeJS, więc proszę o wyrozumiałość.
adamJLev,
Nie, to jest magia npm install, dodaje dowiązania symboliczne w katalogu zainstalowanego pakietu do poprawnych wersji pakietów zależnych. Gdy wymagany jest pakiet zależności, require('express')najpierw sprawdza katalog lokalny i znajduje dowiązanie symboliczne do poprawnej wersji programu express.
Daniel Beardsley
5

Powinieneś przeczytać te dwa artykuły z bloga Isaacs (autor npm). Myślę, że są naprawdę dobre i wierzę, że mówią ci, jak osiągnąć swój cel:

  1. http://blog.izs.me/post/1675072029/10-cool-things-you-probably-didnt-realize-npm-could-do
  2. http://foohack.com/2010/08/intro-to-npm/

Myślę, że link 1 (punkt 11) wyjaśnia to:

11: Spakuj wszystkie zależności w sam pakiet

Kiedy używasz polecenia npm bundle, npm umieści wszystkie twoje zależności w folderze node_modules w twoim pakiecie. Ale to nie koniec.

Jeśli chcesz polegać na czymś, czego nie ma w rejestrze, możesz to zrobić. Po prostu zrób to:

npm bundle install http://github.com/whoever/whaters/tarball/master Spowoduje to zainstalowanie zawartości tego archiwum w paczce, a następnie możesz dodać go jako zależność i nie będzie próbował go zainstalować kiedy Twój pakiet zostanie zainstalowany.

Jest to również przydatne, jeśli masz własny widelec czegoś i wolałbyś nie zmieniać nazwy.

W rzeczywistości w pakiecie można uruchomić prawie każdą komendę npm. Aby zobaczyć, co jest w środku, możesz zrobić pakiet npm ls. Aby coś usunąć, zrób rzecz npm bundle rm. I oczywiście możesz zainstalować wiele wersji i aktywować tę, którą chcesz.

Alfred
źródło
Jest to przydatne, chociaż nie tego szukałem. Być może muszę dodać wyjaśnienie. Szukam sposobu, aby automatycznie zainstalować lub zaktualizować (na komputerze docelowym) pakiety NPM, od których zależy moja aplikacja, kiedy ją wdrażam. Wygląda na to, że npm bundlejest używany do gromadzenia wszystkich zależności w określonym katalogu innym niż domyślny. Prawdopodobnie wymyślę własne rozwiązanie, które działa podobnie do bundle install( bundlerdla rubinu)
Daniel Beardsley,
1
Tylko uwaga, od npmwersji 1.0+ npm bundlezostała usunięta. Zamiast tego po prostu użyj npm installpolecenia bez nazwy pakietu, odczyta plik package.json i ściągnie wymagane pakiety.
Arthur Maltson
2

Od wersji Npm 1.1.2 jest nowe polecenie, npm shrinkwrapktóre tworzy npm-shrinkwrapped.jsonplik, analogicznie do Gemfile.lock. Ważne jest, aby go utworzyć, aby zapobiec gniciu oprogramowania (patrz uzasadnienie Bundlera ). Zwłaszcza, że ​​Nodejs ma tak szybko rozwijającą się społeczność.

Chociaż bundle installtworzy Gemfile.lockautomatycznie, npm installnie utworzy npm-shrinkwrapped.json(ale użyje go, gdy istnieje). Dlatego musisz pamiętać o użyciu npm shrinkwrap.

Przeczytaj pełny przewodnik pod adresem http://blog.nodejs.org/2012/02/27/managing-node-js-dependencies-with-shrinkwrap/

Colonel Panic
źródło
2

Wydaje mi się, że najprostszym rozwiązaniem jest użycie package.jsonpliku z privateflagą (dodaną do npm dopiero w zeszłym miesiącu) ustawioną na true. W ten sposób możesz uruchomić npm installlub npm bundlepobrać zależności swojego projektu, ale zapobiegniesz przypadkowemu opublikowaniu projektu niepublicznego.

Oto przykład package.json:

{
"name": "yourProject"
,"version": "1.0.0"
,"dependencies": { "express" : ">=2.1.0" }
,"private": true
}

Uruchomienie npm installzainstaluje expresssię w systemie lokalnym, jeśli jeszcze nie istnieje; działanie npm publishpowoduje błąd z powodu rozszerzenia "private": true.

Ty i Twój zespół możecie wewnętrznie używać tagu wersji, aby śledzić zmiany zależności w czasie - za każdym razem, gdy zmieniacie zależność, zwiększajcie wersję. Aby zobaczyć, którą wersję zainstalowałeś, użyj npm ls installed.

Trevor Burnham
źródło
Myślę, że nie powinieneś cytować truei że to działa tylko dlatego, że łańcuchy są prawdziwymi wartościami (to znaczy !!"false" === true).
Camilo Martin,
1

Opublikuj również swoją aplikację npmw programie i wypisz jej zależności w pliku package.json.

Gdy ktoś użyje npmdo zainstalowania twojego pakietu, npmzajmie się rozwiązaniem jego zależności.

Specyfikacja pakietów: http://wiki.commonjs.org/wiki/Packages/1.0

Dan Grossman
źródło
Tak, ale to nie jest aplikacja internetowa typu open source. Jeśli masz pomysł, który nie obejmuje publikacji aplikacji, edytuj swoją odpowiedź lub utwórz inną.
Daniel Beardsley
1
Następnie opublikuj pakiet, taki jak „myapp-dependencies”, którego użytkownicy mogą użyć npmdo zainstalowania przed zainstalowaniem aplikacji. Myślę, że nie ma innego gemodpowiednika dla node.js.
Dan Grossman