Polub bloga na fejsie!

Publikacja komponentu ReactJS w npm

6

W repozytorium npm dostępnych jest całe mnóstwo re-używalnych komponentów ReactJS. Pod tym względem „ekosystem” Reacta jest bardzo rozwinięty. Pracując w tej technologii na codzień, sami tworzymy mnóstwo przydatnych komponentów. Dlaczego by więc nie opublikować swoich rozwiązań w tym repozytorium, tak aby każdy mógł wykorzystać naszą pracę? Dzięki temu każdy z nas może stać się kontrybutorem open-soure! Brzmi kusząco prawda? Sam to swego czasu zrobiłem – tutaj możecie podziwiać moje „dzieło”. Dzięki temu, że przetarłem już ten szlak, mogę teraz podzielić się swoimi doświadczeniami… I stąd właśnie wziął pomysł na dzisiejszy wpis – przedstawię Ci jak w praktyce wygląda publikacja komponentu ReactJS w npm!

P.S. Ostatnio na „fejsie” ktoś się przyczepił, że bezczelnie zrzynam teksty z innego bloga… Oczywiście chodziło o Front-End Insights czyli mojego własnego bloga anglojęzycznego. Myślę, że nie jest żadną tajemnicą, że część tekstów z tamtego bloga pojawia się, oczywiście przetłumaczona, tutaj (tłumaczenia w drugą stronę też są możliwe, choć na razie projekt anglojęzyczny leży odłogiem). Tak jest i w tym przypadku więc mam nadzieję, że tym razem nikt się nie przyczepi… Takich wpisów (tłumaczonych) będzie w przyszłości coraz mniej ponieważ, na tę chwilę blog po polsku jest dla mnie priorytetem!

Tworzenie projektu dla komponentu

Przy tworzeniu komponentu ReactJS w celu jego późniejszej publikacji w npm, pierwszym problem przed jakim staniesz jest to, jaką strukturę powinien mieć projekt zawierający ten komponent. Wątpliwości budzić może również to, co powinno znaleźć się na wyjściu takiego projektu. Tutaj chodzi mi głównie o to, jaki format powinien przyjąć wynikowy kod, tak aby był on łatwo używalny w innych projektach.

Co do drugiej z wątpliwości to w sumie wiadomo – rezultatem naszego projektu ma być komponent ReactJS. Kod tego komponentu powinien przyjąć postać ES5. Dzięki temu będzie on mógł być wykorzystany zarówno w projektach napisanych z użyciem ES5 jak i ES6. Jednocześnie w projekcie komponentu wolę użyć ES6 aby móc wykorzystać wszystkie jego zalety. Z tego też powodu myślę, że wykorzystanie webpacka i babela nasuwa się jako „oczywista oczywistość”.

Kolejna sprawa to testowanie. Jest to bardzo istotne jeśli chcesz swój komponent opublikować w npm. W końcu miliardy programistów z całego świata może potencjalnie chcieć użyć Twojego super komponentu w swoich projektach…

A może generator?

Co więc zrobiłem by rozwiać swoje wątpliwości? Jak zwykle przed rozpoczęciem nowego projektu, zanim zacznę coś samodzielnie dziergać, sprawdzam czy dla mojego problemu dostępne są jakieś generatory Yeomana. I nie zgadniesz… oczywiście, że są! Dzięki temu, aby zacząć projekt wystarczy, że zrobię to:

Kod wygenerowany przez ten generator jest przygotowany pod tworzenie komponentów posiadających jakiś widok. Stąd też obecność skryptów npm, które uruchamiają webpack-dev-server. Miło ze strony tego generatora – może Ci się to przydać kiedy będziesz tworzyć tego typu komponenty.

Niestety, generator ten jest już trochę stary i brakuje mu pewnych paczek npm. Aby to naprawić wystarczy je zainstalować:

Struktura projektu

Spójrz teraz na strukturę projektu, który się wygenerował. Możesz w nim znaleźć katalog lib. To jest właśnie miejsce, w którym powinieneś umieścić swój komponent. Na razie znajduje się tam komponent przykładowy, który możesz usunąć lub zmodyfikować. Oprócz przykładowego komponentu, w katalogu lib znajduje się też plik index.js. Jest to punkt wejściowy naszego projektu – spójrzmy na jego zawartość:

Jak widzisz, mamy tutaj definicję modułu w stylu node.js – nic nie stoi na przeszkodzie aby przerobić to na ES6. Moduł ten importuje komponent znajdujący się w katalogu lib. Spójrzmy teraz jak on wygląda:

Tutaj mamy z kolei jakiś dziwny miks ES6 (importy) i definicję klasy ReactJS w stylu ES5. Oczywiście tutaj również warto przerobić kod na ES6.

Testowanie komponentu

Ok, skoro mamy już gotową strukturę projektu, warto jeszcze sprawdzić jakie mamy możliwości testowania naszego komponentu. W zasadzie to widzę tutaj dwie opcje: testy jednostkowe oraz testowanie komponentu jako pakietu npm. Na początek rozważmy pierwszą opcję.

Testowanie za pomocą testów jednostkowych

Generator, którego użyłem do wygenerowania struktury projektu posiada wsparcie dla testów jednostkowych tworzonego komponentu, dostępne z pudełka! Wedle tej struktury, wszystkie testy jednostkowe powinny znaleźć się w katalogu spec. Jest już tam oczywiście przykładowy test, spójrzmy więc na niego:

POLUB BLOGA NA FACEBOOKU!

Chcesz być na bieżąco informowany o nowościach na blogu oraz innych ciekawych treściach? Polub fanpage bloga na Facebooku!

Jak widzisz, jest to bardzo prosty test sprawdzający czy komponent zawiera element DOM o określonej wartości atrybutu className. Myślę, że testowanie komponentów ReactJS to temat na osobny wpis, dlatego na tym dziś poprzestanę.

W omawianym projekcie, do testowania użyto narzędzi: Jasmine oraz Karma. Mamy też dostępne komendy, które pozwalają nam łatwo uruchamiać testy jednostkowe. Poniżej komenda uruchamiające testy jednorazowo:

Jest też opcja uruchomienia testów, a następnie oczekiwania na zmiany (w przypadku wykrycia zmian w testowanym kodzie, testy uruchamiają się ponownie):

To w zasadzie wszystko co musisz wiedzieć, na temat testów jednostkowych zanim nastąpi publikacja komponentu ReactJS w npm. Myślę, że nie muszę nikogo przekonywać do tworzenia takich testów – skoro chcesz się podzielić swoim kodem z innymi, warto mieć pewność, że wszystko działa.

Testowanie komponentu jako pakietu npm

Zanim opublikujesz swój komponent w npm warto przetestować, jak przygotowany przez Ciebie pakiet zachowa się w jakimś Twoim lokalnym, przykładowym projekcie. Aby to zrobić, musimy na podstawie naszego projektu wygenerować testową paczkę npm.

Konfiguracja webpacka

W tym celu zmienimy co nieco konfigurację webpacka w naszym projekcie. Nie jest to absolutnie konieczne, ale lepiej to zrobić aby nasz pakiet spełniał standardy. Otwórzmy więc plik konfiguracyjny webpacka czyli webpack.config.js znajdujący się w głównym katalogu projektu. Jeśli spojrzysz na obiekt przypisany do właściwości output to zauważysz, że plik wynikowy ustawiony jest na wartość react-component-npm.js. Moim zdaniem dobrą praktyką jest, aby plik ten zawsze nazywał się index.js. Od razu wtedy wiadomo, że to punkt wejścia do naszej biblioteki. Druga rzecz do zmiany to ścieżka wyjściowa. Zmieńmy ją na /dist:

Jeśli chcesz, możesz też oczywiście zmienić nazwę swojej biblioteki na taką, która bardziej Ci odpowiada. Służy do tego właściwość library. Spróbujmy teraz zbudować nasz projekt:

Po wykonaniu tego polecania, wszystko powinno się ładnie zbudować, a w głównym katalogu projektu powinien pojawić się katalog dist zawierający plik index.js.

Konfiguracja npm

Przejdźmy teraz do pliku package.json. Jak wiadomo znajduje się w nim konfiguracja projektu npm. To co trzeba tutaj zrobić, zanim opublikujemy nasz projekt w repozytorium npm, to zmiana opcji main, tak aby wskazywała ona na plik dist/index.js. Wynika to z tego, że przed momentem zmieniliśmy trochę konfigurację webpacka – ścieżka do pliku wyjściowego i jego nazwa zmieniły się.

Jeśli nie wiesz do czego służy opcja main pliku package.json to śpieszę z wyjaśnieniem! Otóż wskazuje ona na punkt wejścia naszej biblioteki. Gdy ktoś zainstaluje nasz komponent z repozytorium npm, to przy imporcie to właśnie w tym pliku będzie szukał dostępnych modułów.

Publikacja lokalna

Ok, całą niezbędną konfigurację mamy już za sobą. Czas teraz przystąpić do wygenerowania lokalnie paczki z naszym komponentem. Umożliwi nam to zainstalowanie tego pakietu w innym projekcie i użycie naszego komponentu, w celu jego przetestowania.

Sama publikacja lokalna jest bardzo prosta – wystarczy wywołać poniższą komendę w głównym katalogu projektu:

Wywołanie powyższej komendy spowoduje utworzenie pliku react-component-npm-1.0.0.tgz w głównym katalogu projektu.

Zwróć uwagę na nazwę tego pliku. Powstaje ona z połączenia wartości opcji name oraz version ustawionych w pliku package.json. Z tego wniosek, że jeśli chcesz zmienić nazwę swojego pakietu, to właśnie w tym pliku możesz to zrobić.

No dobra. Pakiet lokalny mamy już utworzony. Czas teraz zainstalować nasz pakiet w innym naszym lokalnym projekcie. Aby to zrobić, przejdź w konsoli do głównego katalogu tamtego projektu i wywołaj poniższą komendę:

W tym momencie zadzieje się „magia” i pakiet zostanie zainstalowany. Możesz to sprawdzić zaglądając do katalogu node_modules swojego lokalnego, testowego projektu. Powinien się tam znajdować katalog o nazwie zgodnej z nazwą Twojego pakietu. Oprócz tego, w pliku package.json tego projektu, lista dependencies powinna zostać zaktualizowana o wpis z nazwą Twojego komponentu.

I to tyle – możesz teraz spróbować zaimportować stworzony przez siebie komponent i testowo go wykorzystać.

Eksport komponentu do npm

No dobra. Mamy już utworzony i dobrze przetestowany komponent. Ostatnia rzecz, która nam została to właściwa publikacja komponentu ReactJS w npm. W tym celu musimy wykonać kilka kroków…

Aby móc publikować w npm, musisz skonfigurować swoje dane autora. Wymaga to wywołania poniższych komend w konsoli:

Ok. Teraz należy zainstalować globalnie pakiet pakmanager:

Kiedy to zrobimy, możemy użyć tego narzędzia do sprawdzenia czy nie brakuje nam w projekcie żadnych zależności:

Jeśli narzędzie to wykaże jakieś brakujące pakiety, należy je zainstalować lub dodać je do sekcji dependencies w pliku package.json.

Ostatnia rzecz przed publikacją – dodaj plik .npmignore! Plik ten działa tak samo jak inne pliki tego typu (na przykład .gitignore). Wypisz w nim wszystko co nie powinno znaleźć się w wynikowym pakiecie npm. Najważniejsze, to żebyś w pliku tym nie umieszczał katalogu dist ani pliku package.json. One musza koniecznie znaleźć się w eksportowanym pakiecie. Inaczej pakiet nie będzie działać! Poniżej przykład takiego pliku, dla mojego komponentu, o którym wspominałem na początku wpisu:

Pamiętaj też, aby dodać plik README.md do projektu Twojego komponentu i dobrze opisać w nim sposób jego użycia! To ułatwi, potencjalnym odbiorcom Twojej biblioteki, zorientowanie się jak działa Twój komponent oraz czy spełnia on ich wymagania i potrzeby. Zawartość tego pliku będzie, po publikacji, wyświetlała się na stronie Twojego pakietu dostępnej w serwisie nmpjs.org. Dlatego też nazwa tego pliku ten nie może być wyszczególniona w pliku .npmignore.

Alright! Czas wreszcie opublikować nasz komponent! Żeby to zrobić, wywołaj poniższą komendę z poziomu głównego katalogu projektu tego komponentu:

I gotowe! Możesz teraz przejść na stronę npmjs.org i sprawdzić czy Twój pakiet się tam pojawił…

Publikacja komponentu ReactJS w npm – podsumowanie

Wydaje mi się, że publikacja komponentu ReactJS w npm jest dość prosta. Mam nadzieję, że powyższy poradnik będzie dla Ciebie w tym procesie pomocny! Myślę, że warto dzielić się ze społecznością dobrymi pomysłami. A zaistnienie jako autor pakietów npm może być całkiem przydatnym atutem, na przykład, na rynku pracy… Jak więc widzisz, może to być z pożytkiem zarówno dla Ciebie jak i dla innych.

REACT, REDUX, REACT-ROUTER - KURSY ON-LINE

Chcesz od podstaw poznać tajniki React, Redux oraz react-router? Zapraszam do moich szkoleń on-line:

Przejdź do szkoleń

Uwaga! Obecnie trwa przedsprzedaż kursów - premiera 1 sierpnia 2017!

  • Czy nie lepiej zamiast budować paczkę lokalnie i ją instalować zastosować npm link i sprawdzić jak dany pakiet zachowuje się jakby był normalnie zainstalowanym pakietem npm? IMO o wiele prostsze.

    Co do .npmignore: IMO lepiej jest zrobić whitelistę plików przy pomocy pola files w pliku package.json (https://github.com/BEMQuery/bemquery-core/blob/master/package.json#L48-L51 ). Warto tutaj zauważyć, że npm zawsze załącza package.json, README.md czy LICENSE.

    • faktycznie, npm-link wygląda na fajną opcję (nie znałem jej wcześniej więc dzięki za hint) ale z tego co rozumiem to jest to tylko link do folderu z projektem biblioteki… budowanie paczki lokalnie i tak jest przydatne żeby przetestować jak będzie wyglądać paczka po publikacji

      • No tak, ale nic nie stoi na przeszkodzie, żeby zrobić npm link i po prostu zapuścić npm run build w folderze z projektem. Przecież wychodzi na to samo (require będzie szukał pliku dist/index.js). Plus jest taki, że zmiany można testować niemal na żywo.

        • właśnie o to mi chodziło – npm-link do pracy nad projektem + lokalne generowanie paczki na koniec, chociażby żeby przetestować czy nie wycieliśmy za dużo .npmignore czy tam tą Twoją whitelistą

  • Wojtek

    Ciekawa sprawa z tą transpilacją, bo widziałem już biblioteki których kod w repo był dostępny wyłącznie w ES6. Twórcy upierali się, że to już nie ich sprawa by się zajmować zmianą do ES5. Trzeba było potem procesie budowania kombinować dookoła, by babel ingorował node_modules za wyjątkiem 3 czy 4 bibliotek 😉

    • no więc właśnie – wydaje mi się, że w npm kod powinien w takim stanie, żeby można go było użyć możliwie wszędzie… pewnie wciąż istnieją projekty w React napisane bez ES6, to wtedy co? olać takich ludzi i niech się sami martwią jeśli chcą użyć naszego komponentu?

Google Analytics Alternative