Jaka jest różnica między Bower a npm?

1763

Jaka jest podstawowa różnica między boweri npm? Po prostu chcę coś prostego i prostego. Widziałem, jak niektórzy z moich kolegów używają boweri npmzamiennie w swoich projektach.

Games Brainiac
źródło
7
Powiązana odpowiedź stackoverflow.com/a/21199026/1310070
sachinjain024
7
Odpowiedź na to pytanie wydaje się nieaktualna. Czy ktoś może nam powiedzieć, co robić w 2016 r., Jeśli użyjemy npm 3, które obsługują stałą zależność? Jaka jest różnica w porównaniu do npm3 i altany i jaka jest teraz najlepsza praktyka?
amdev
2
Podsumowując, @amdev: altana jest teraz przestarzała. npm (lub Przędza, która jest tylko niewielką różnicą) jest tam, gdzie jest. Nie znam żadnych realnych alternatyw.
XML,

Odpowiedzi:

1914

Wszyscy menedżerowie pakietów mają wiele wad. Musisz tylko wybrać, z kim możesz żyć.

Historia

npm rozpoczął zarządzanie modułów node.js (dlatego pakiety wchodzić node_modulesdomyślnie), ale działa na front-end też w połączeniu z Browserify lub WebPack .

Bower został stworzony wyłącznie z myślą o interfejsie użytkownika i został zoptymalizowany pod tym kątem.

Rozmiar repo

npm jest znacznie, dużo większy niż altana, włączając w to JavaScript ogólnego przeznaczenia (np. country-datado informacji o kraju lub sortsdo funkcji sortowania, które można wykorzystać na interfejsie lub na zapleczu).

Bower ma znacznie mniejszą liczbę paczek.

Obsługa stylów itp

Bower zawiera style itp.

npm koncentruje się na JavaScript. Style są pobierane osobno lub wymagane przez coś takiego jak npm-sasslub sass-npm.

Obsługa zależności

Największą różnicą jest to, że npm robi zagnieżdżone zależności (ale domyślnie jest płaska), podczas gdy Bower wymaga płaskiego drzewa zależności (nakłada na użytkownika ciężar rozwiązywania zależności) .

Zagnieżdżone drzewo zależności oznacza, że ​​twoje zależności mogą mieć własne zależności, które mogą mieć swoje własne i tak dalej. Dzięki temu dwa moduły wymagają różnych wersji tej samej zależności i nadal działają. Zauważ, że od npm v3, drzewo zależności domyślnie będzie płaskie (oszczędność miejsca) i zagnieżdżone tylko tam, gdzie będzie to potrzebne, np. Jeśli dwie zależności potrzebują własnej wersji podkreślenia.

Niektóre projekty używają obu, ponieważ używają Bowera do pakietów frontonu i npm do narzędzi programistycznych takich jak Yeoman, Grunt, Gulp, JSHint, CoffeeScript itp.


Zasoby

Sindre Sorhus
źródło
37
Dlaczego zagnieżdżone drzewo zależności nie działa tak dobrze w interfejsie?
Lars Nyström,
24
Czy przedni pakiet NPM może nie być również płaskim drzewem zależności? Mam do czynienia z „dlaczego potrzebujemy 2 menedżerów pakietów?” dylemat.
Steven Vachon
38
Co rozumiesz przez „płaskie drzewo zależności”? Płaskie drzewo to co - lista? To nie jest drzewo.
mvmn
14
W rzeczywistości ścieżka jest także drzewem. To tylko specjalny przypadek. Z WikiPedia: „W matematyce, a dokładniej w teorii grafów, drzewo jest grafem bezkierunkowym, w którym dowolne dwa wierzchołki są połączone dokładnie jedną ścieżką”.
Jørgen Fogh,
42
npm 3 obsługuje teraz płaskie drzewo zależności.
vasa
361

Ta odpowiedź jest dodatkiem do odpowiedzi Sindre Sorhus. Główną różnicą między npm i Bower jest sposób, w jaki traktują zależności rekurencyjne. Pamiętaj, że można ich używać razem w jednym projekcie.

Na npm FAQ : (archive.org powiązanie z 6 wrz 2015)

O wiele trudniej jest unikać konfliktów zależności bez zagnieżdżania zależności. Ma to zasadnicze znaczenie dla sposobu działania npm i okazało się, że jest to niezwykle skuteczne podejście.

Na stronie głównej Bower :

Altana jest zoptymalizowana pod kątem interfejsu. Bower używa płaskiego drzewa zależności, wymagając tylko jednej wersji dla każdego pakietu, co zmniejsza obciążenie strony do minimum.

Krótko mówiąc, npm dąży do stabilności. Bower dąży do minimalnego obciążenia zasobów. Jeśli narysujesz strukturę zależności, zobaczysz to:

npm:

project root
[node_modules] // default directory for dependencies
 -> dependency A
 -> dependency B
    [node_modules]
    -> dependency A

 -> dependency C
    [node_modules]
    -> dependency B
      [node_modules]
       -> dependency A 
    -> dependency D

Jak widać instaluje rekurencyjnie niektóre zależności. Zależność A ma trzy zainstalowane instancje!

Altana:

project root
[bower_components] // default directory for dependencies
 -> dependency A
 -> dependency B // needs A
 -> dependency C // needs B and D
 -> dependency D

Tutaj widzisz, że wszystkie unikalne zależności są na tym samym poziomie.

Po co więc męczyć się z użyciem npm?

Być może zależność B wymaga innej wersji zależności A niż zależność C. npm instaluje obie wersje tej zależności, więc i tak będzie działać, ale Bower da ci konflikt, ponieważ nie lubi duplikacji (ponieważ ładowanie tego samego zasobu na stronie jest bardzo nieefektywne i kosztowne, może również powodować poważne błędy). Będziesz musiał ręcznie wybrać wersję, którą chcesz zainstalować. Może to spowodować uszkodzenie jednej z zależności, ale i tak trzeba to naprawić.

Tak więc, powszechnym zastosowaniem jest Bower dla pakietów, które chcesz publikować na swoich stronach internetowych (np. Środowisko wykonawcze , w którym unikasz powielania) i używaj npm do innych rzeczy, takich jak testowanie, budowanie, optymalizacja, sprawdzanie itp. (Np. Czas programowania , gdzie powielanie jest mniej istotne).

Aktualizacja dla npm 3:

npm 3 nadal robi rzeczy inaczej niż Bower. Zainstaluje zależności globalnie, ale tylko dla pierwszej napotkanej wersji. Pozostałe wersje są zainstalowane w drzewie (moduł nadrzędny, a następnie moduły_węzła).

  • [node_modules]
    • dep A v1.0
    • dep B v1.0
      • dep A v1.0 (używa wersji root)
    • dep C v1.0
      • dep A v2.0 (ta wersja różni się od wersji root, więc będzie to instalacja zagnieżdżona)

Aby uzyskać więcej informacji, sugeruję przeczytanie dokumentacji npm 3

Justus Romijn
źródło
4
To już prawie stereotyp, że „w tworzeniu oprogramowania chodzi o kompromisy”. To dobry przykład. Należy wybrać albo większą stabilność, npm albo minimalne obciążenie zasobów bower.
jfmercer
6
@Shrek Pośrednio twierdzę, że faktycznie możesz używać obu. Mają różne cele, jak stwierdzam w ostatnim akapicie. To nie jest kompromis w moich oczach.
Justus Romijn,
Ahh, rozumiem, że cię źle zrozumiałem. Albo nie przeczytałem wystarczająco uważnie. Dziękuję za wyjaśnienie. :-) Dobrze, że oba mogą być używane bez kompromisu.
jfmercer
4
@AlexAngas Dodałem aktualizację dla npm3. Nadal ma kilka istotnych różnic w porównaniu do Bowera. npm prawdopodobnie zawsze będzie obsługiwał wiele wersji zależności, podczas gdy Bower nie.
Justus Romijn
npm 3 coraz bliżej altany;)
ni3
269

TL; DR: Największą różnicą w codziennym użytkowaniu nie są zależności zagnieżdżone ... to różnica między modułami a globałami.

Myślę, że poprzednie plakaty dobrze opisywały niektóre podstawowe wyróżnienia. (użycie zagnieżdżonych zależności przez npm jest naprawdę bardzo pomocne w zarządzaniu dużymi, złożonymi aplikacjami, choć nie sądzę, że jest to najważniejsze rozróżnienie).

Dziwi mnie jednak fakt, że nikt nie wyjaśnił jednoznacznie jednej z najbardziej podstawowych różnic między Bower a npm. Jeśli przeczytasz powyższe odpowiedzi, zobaczysz słowo „moduły” używane często w kontekście npm. Ale wspomina się o tym od niechcenia, jakby to była tylko różnica w składni.

Ale to rozróżnienie modułów na globale (lub modułów na „skrypty”) jest prawdopodobnie najważniejszą różnicą między Bower a npm. Podejście NPM polegające na umieszczaniu wszystkiego w modułach wymaga zmiany sposobu pisania Javascript dla przeglądarki, prawie na pewno na lepsze.

Podejście Bower: globalne zasoby, takie jak <script>tagi

W katalogu głównym Bower polega na ładowaniu zwykłych plików skryptów. Cokolwiek zawierają te pliki skryptów, Bower je załaduje. Co w zasadzie oznacza, że ​​Bower jest po prostu włączeniem wszystkich twoich skryptów do zwykłych starych <script>w <head>twoim HTML.

Więc to samo podstawowe podejście, do którego jesteś przyzwyczajony, ale masz kilka fajnych udogodnień automatyzacji:

  • W repozytorium projektu trzeba było uwzględniać zależności JS (podczas opracowywania) lub uzyskiwać je za pośrednictwem CDN. Teraz możesz pominąć tę dodatkową wagę pobierania w repozytorium, a ktoś może zrobić szybko bower installi natychmiast mieć to, czego potrzebuje, lokalnie.
  • Jeśli zależność Bowera określa w niej własne zależności bower.json, zostaną one również pobrane dla Ciebie.

Ale poza tym Bower nie zmienia sposobu, w jaki piszemy javascript . Nic, co znajduje się w plikach ładowanych przez Bowera, nie musi się w ogóle zmieniać. W szczególności oznacza to, że zasoby dostarczone w skryptach ładowanych przez Bowera (zwykle, ale nie zawsze) będą nadal definiowane jako zmienne globalne , dostępne z dowolnego miejsca w kontekście wykonywania przeglądarki.

Podejście npm: wspólne moduły JS, jawne wstrzykiwanie zależności

Cały kod w obszarze Node (a więc cały kod ładowany przez npm) ma strukturę modułów (w szczególności jako implementację formatu modułu CommonJS lub teraz jako moduł ES6). Tak więc, jeśli używasz NPM do obsługi zależności po stronie przeglądarki (poprzez Browserify lub coś innego, co wykonuje tę samą pracę), ustrukturyzujesz swój kod w ten sam sposób, co robi Node.

Ludzie mądrzejsi ode mnie poradzili sobie z pytaniem „Dlaczego moduły?”, Ale oto podsumowanie kapsułek:

  • Wszystko wewnątrz modułu ma efektywną przestrzeń nazw , co oznacza, że ​​nie jest już zmienną globalną i nie można przypadkowo odwoływać się do niej bez zamiaru.
  • Wszystko wewnątrz modułu musi być celowo wstrzykiwane w określony kontekst (zwykle inny moduł), aby z niego skorzystać
  • Oznacza to, że możesz mieć wiele wersji tej samej zależności zewnętrznej (powiedzmy lodash) w różnych częściach aplikacji i nie będą one kolidować / konfliktować. (Zdarza się to zaskakująco często, ponieważ twój własny kod chce użyć jednej wersji zależności, ale jedna z zewnętrznych zależności określa inną, która powoduje konflikt. Lub masz dwie zależności zewnętrzne, z których każda chce innej wersji).
  • Ponieważ wszystkie zależności są ręcznie wstrzykiwane do określonego modułu, bardzo łatwo jest je zrozumieć. Wiesz na pewno : „Jedynym kodem, który muszę wziąć pod uwagę, pracując nad tym, jest to, co celowo wybrałem tutaj .
  • Ponieważ nawet zawartość wstrzykiwanych modułów jest zamknięta za zmienną, do której ją przypisujesz, a cały kod jest wykonywany w ograniczonym zakresie, niespodzianki i kolizje stają się bardzo nieprawdopodobne. Jest o wiele, znacznie mniej prawdopodobne, że coś z jednej z twoich zależności przypadkowo przedefiniuje zmienną globalną, nie zdając sobie z tego sprawy, lub że to zrobisz. (Może się to zdarzyć, ale zwykle musisz zrobić wszystko, aby to zrobić, z czymś takim window.variable. Jedynym wypadkiem, który wciąż ma miejsce, jest przypisanie this.variable, nie zdając sobie sprawy, że thistak naprawdę jest windoww obecnym kontekście.)
  • Kiedy chcesz przetestować pojedynczy moduł, możesz bardzo łatwo wiedzieć: co dokładnie (zależności) wpływa na kod działający w module? A ponieważ jawnie wstrzykujesz wszystko, możesz łatwo wyśmiewać te zależności.

Dla mnie użycie modułów w kodzie front-end sprowadza się do: pracy w znacznie węższym kontekście, łatwiejszym do przemyślenia i przetestowania, oraz większej pewności co do tego, co się dzieje.


Nauka używania składni modułu CommonJS / Node zajmuje tylko około 30 sekund. Wewnątrz pliku JS, który będzie modułem, najpierw zadeklarujesz zależności zewnętrzne, których chcesz użyć, na przykład:

var React = require('react');

Wewnątrz pliku / modułu robisz wszystko, co zwykle, i tworzysz jakiś obiekt lub funkcję, którą chcesz udostępnić użytkownikom zewnętrznym, być może nazywając to myModule.

Na końcu pliku eksportujesz wszystko, co chcesz udostępnić światu, w następujący sposób:

module.exports = myModule;

Następnie, aby użyć przepływu pracy opartego na CommonJS w przeglądarce, użyjesz narzędzi takich jak Browserify, aby pobrać wszystkie te pojedyncze pliki modułów, obudować ich zawartość w czasie wykonywania i wstrzyknąć je sobie w razie potrzeby.

ORAZ, ponieważ moduły ES6 (które najprawdopodobniej przeniesiesz do ES5 z Babel lub podobnym) zyskują szeroką akceptację i działają zarówno w przeglądarce, jak i w Node 4.0, powinniśmy również wspomnieć o ich dobrym przeglądzie .

Więcej informacji o wzorach do pracy z modułami w tym pokładzie .


EDYCJA (luty 2017): Przędza Facebooka jest obecnie bardzo ważnym potencjalnym zamiennikiem / suplementem dla npm: szybkie, deterministyczne, zarządzanie pakietami offline, które opiera się na tym, co daje ci npm. Warto poszukać każdego projektu JS, zwłaszcza, że ​​tak łatwo jest go zamienić na.


EDYCJA (maj 2019) „Bower jest już przestarzały . Koniec historii”. (h / t: @DanDascalescu, poniżej, dla zwięzłego podsumowania.)

I podczas gdy Przędza jest nadal aktywna , znaczna rozpęd powróciła do npm, kiedy przyjęła niektóre kluczowe cechy Przędzy.

XML
źródło
13
Cieszę się, że ta odpowiedź była tutaj, inne popularne odpowiedzi nie wspominają o tym szczególe. npm zmusza cię do pisania kodu modułowego.
Juan Mendes
Przykro mi, od ludzi, którzy bardzo nie dbają o wszystkie zamieszanie w javascript parlands, ale tak się składa, że ​​prowadzi firmę, która korzysta z małej aplikacji internetowej. Niedawno byliśmy zmuszeni wypróbować npm, od korzystania z altany z zestawem narzędzi, którego używamy do rozwijania rzeczy do cholernej sieci. Mogę powiedzieć, że największą różnicą jest czas oczekiwania, npm trwa wieki. Pamiętaj, że to kompilacja kreskówki xkcd z chłopakami walczącymi na miecze krzyczącymi „kompilującymi” do swojego szefa; to właściwie to, co npm dodało do altany.
Pedro Rodrigues
129

Aktualizacja 2017-paź

Bower został w końcu przestarzały . Koniec opowieści.

Starsza odpowiedź

Od Mattias Petter Johansson, programista JavaScript w Spotify :

W prawie wszystkich przypadkach bardziej odpowiednie jest użycie Browserify i npm nad Bower. Jest to po prostu lepsze rozwiązanie do pakowania aplikacji frontowych niż Bower. W Spotify używamy npm do pakowania całych modułów sieciowych (html, css, js) i działa bardzo dobrze.

Bower określa się mianem menedżera pakietów w Internecie. Byłoby wspaniale, gdyby to była prawda - menedżer pakietów, który poprawiłby moje życie jako programista front-end, byłby niesamowity. Problem polega na tym, że Bower nie oferuje do tego celu specjalistycznych narzędzi. Nie oferuje żadnych narzędzi, o których wiem, że nie ma npm, a zwłaszcza żadnego, który jest szczególnie przydatny dla programistów frontonu. Po prostu nie ma korzyści dla frontendowego programisty, który używałby Bowera nad npm.

Powinniśmy przestać używać altany i skonsolidować się wokół npm. Na szczęście tak się dzieje :

Moduł liczy - altana kontra npm

Dzięki Browserify lub webpack bardzo łatwo jest połączyć wszystkie moduły w duże, zminimalizowane pliki, co jest niesamowite pod względem wydajności, szczególnie w przypadku urządzeń mobilnych. Nie w przypadku Bowera, który będzie wymagał znacznie więcej pracy, aby uzyskać ten sam efekt.

npm oferuje również możliwość korzystania z wielu wersji modułów jednocześnie. Jeśli nie opracowałeś dużo aplikacji, może się to początkowo wydawać złe, ale po przejściu kilku ataków piekła Zależności zdasz sobie sprawę, że możliwość posiadania wielu wersji jednego modułu jest dość cholerna świetna funkcja. Zauważ, że npm zawiera bardzo przydatne narzędzie dedupe, które automatycznie upewnia się, że używasz tylko dwóch wersji modułu, jeśli naprawdę musisz - jeśli dwa moduły mogą korzystać z tej samej wersji jednego modułu, to zrobią to. Ale jeśli nie mogą , masz bardzo przydatne.

(Uwaga: pakiet Webpack i pakiet zbiorczy są powszechnie uważane za lepsze niż Browserify od sierpnia 2016 r.)

Dan Dascalescu
źródło
7
<sarkazm> Należy pamiętać, że nawet projekt npm „hello world” potrzebuje ponad 300 modułów do uruchomienia ... </sarkazm>: O
Mariusz Jamro
1
Nie zgadzam się, że „duże zminimalizowane pliki” są „niesamowite pod względem wydajności, szczególnie na urządzenia mobilne”. Wręcz przeciwnie: ograniczona przepustowość wymaga małych plików, ładowanych na żądanie.
Michael Franzl
Niezbyt dobra rada. Większość pakietów npm jest tylko backendem nodejs. Jeśli nie korzystasz z javascript na backendie lub nie masz zainstalowanego systemu modułów, liczba pakietów nie ma znaczenia, ponieważ Bower będzie lepiej pasował do twoich potrzeb
Gerardo Grignoli
4
@GerardoGrignoli: altana już wychodzi .
Dan Dascalescu
45

Bower utrzymuje jedną wersję modułów, stara się jedynie pomóc wybrać odpowiedni / najlepszy dla Ciebie.

Zarządzanie zależnościami JavaScript: npm vs bower vs volo?

NPM jest lepszy dla modułów węzłów, ponieważ istnieje system modułów i pracujesz lokalnie. Bower jest dobry dla przeglądarki, ponieważ obecnie istnieje tylko zasięg globalny i chcesz być bardzo wybiórczy w kwestii wersji, z którą pracujesz.

Sagivf
źródło
4
Wydaje mi się, że Sindre wspomina o tym, gdy mówi o zagnieżdżonej zależności.
Games Brainiac
5
@GamesBrainiac masz rację, pomyślałem, że wstawię to własnymi słowami.
Sagivf,
1
@Sagivf To nie są twoje własne słowa, chyba że jesteś także wheresrhys, który udzielił oryginalnej odpowiedzi tutaj
dayuloli
4
@Sagivf Nie ma nic złego w kopiowaniu ** odpowiednich części odpowiedzi innych, jeśli sami tutaj nie udzielili odpowiedzi. Po prostu trochę mnie to zirytowało, powiedziałeś „po prostu pomyślałem, że napisam to własnymi słowami”. Kredyt powinien iść tam, gdzie jest należny.
dayuloli
2
Nie wiem, dlaczego tak bardzo wybraliście tę odpowiedź. W tej odpowiedzi rzeczywiście są nowe informacje / perspektywy.
Calvin,
33

Mój zespół odszedł od Bowera i przeprowadził się do npm, ponieważ:

  • Programowe użycie było bolesne
  • Interfejs Bowera ciągle się zmieniał
  • Niektóre funkcje, takie jak skróty adresów URL, są całkowicie zepsute
  • Używanie Bower i npm w tym samym projekcie jest bolesne
  • Utrzymywanie synchronizacji pola wersji bower.json z tagami git jest bolesne
  • Kontrola źródła! = Zarządzanie pakietami
  • Obsługa CommonJS nie jest prosta

Aby uzyskać więcej informacji, zobacz „Dlaczego mój zespół używa npm zamiast altany” .

Nick Heiner
źródło
17

Znalazłem to przydatne wyjaśnienie na stronie http://ng-learn.org/2013/11/Bower-vs-npm/

Z jednej strony stworzono npm do instalacji modułów używanych w środowisku node.js lub narzędzi programistycznych zbudowanych przy użyciu node.js takich jak Karma, włókna, minizatory i tak dalej. npm może instalować moduły lokalnie w projekcie (domyślnie w module_węzła) lub globalnie do użytku w wielu projektach. W dużych projektach sposobem określania zależności jest utworzenie pliku o nazwie package.json, który zawiera listę zależności. Ta lista jest rozpoznawana przez npm po uruchomieniu instalacji npm, która następnie pobiera i instaluje je dla ciebie.

Z drugiej strony altana została stworzona do zarządzania twoimi zależnościami frontendowymi. Biblioteki takie jak jQuery, AngularJS, podkreślenie itp. Podobnie jak npm, ma plik, w którym można określić listę zależności o nazwie bower.json. W tym przypadku zależności interfejsu użytkownika są instalowane przez uruchomienie instalacji bower, która domyślnie instaluje je w folderze o nazwie bower_components.

Jak widać, mimo że wykonują podobne zadanie, są skierowane do zupełnie innego zestawu bibliotek.

Henry Neo
źródło
1
Wraz z nadejściem npm dedupejest to nieco przestarzałe. Zobacz odpowiedź Mattiasa .
Dan Dascalescu
7

Dla wielu osób pracujących z node.js główną zaletą bower jest zarządzanie zależnościami, które wcale nie są javascript. Jeśli pracują z językami kompilującymi się w javascript, npm może być użyty do zarządzania niektórymi z ich zależności. jednak nie wszystkie ich zależności będą modułami node.js. Niektóre z tych, które kompilują się do javascript, mogą mieć dziwne zniekształcenie specyficzne dla języka źródłowego, co sprawia, że ​​przekazywanie ich w kompilacji do javascript jest nieelegantną opcją, gdy użytkownicy oczekują kodu źródłowego.

Nie wszystko w pakiecie npm musi być skryptem JavaScript skierowanym do użytkownika, ale w przypadku pakietów biblioteki npm przynajmniej niektóre z nich powinny być.

jessopher
źródło
W blogu npmjs napisano: „Twój pakiet może zawierać wszystko, czy to ES6, JS po stronie klienta, a nawet HTML i CSS. Są to rzeczy, które naturalnie pojawiają się obok JavaScript, więc umieść je tam.”.
Dan Dascalescu
1
Istnieje różnica między może zawierać i powinna obejmować . Oczywiście mogą zawierać wszystko, ale ogólnie powinny zawierać interfejs do commonJS. W końcu jest to „menedżer pakietów węzłów”. Ważna jest część dotycząca rzeczy, które naturalnie pojawiają się wraz ze skryptem Javascript . Istnieje wiele rzeczy, które są stycznie związane z javascript, które naturalnie nie pojawiają się obok niego.
jessopher,