11 marca 2025 (updated: 11 marca 2025)

Ułatwienie i obniżenie kosztów konfiguracji Twojego projektu dzięki szablonom ogólnym i monorepo.

Chapters

      Duzi goście nie mylą się, gdy używają monorepo dla swoich projektów. Monorepo wraz z ogólnym szablonem mogą przyspieszyć konfigurację Twojego projektu (i obniżyć koszty). Dzielimy się naszym podejściem. 

      Wraz z ciągłym wzrostem złożoności aplikacji pojawia się problem - jak utrzymać wszystkie potrzeby i obniżyć koszty projektu, który wymaga tak wielu zależności od samego początku? W tym artykule omówimy sposób na zaoszczędzenie dni pracy zespołu przy rozpoczynaniu nowego projektu.

      Nie ma jednego prostego sposobu, aby to zrobić, ale z latami doświadczeń i poszukiwaniem najlepszych praktyk z firm takich jak Google, w EL Passion opracowaliśmy rozwiązanie, które drastycznie skraca czas potrzebny na skonfigurowanie nowego projektu.

      W tym artykule omówimy koncepcje szablonu projektu, monorepo oraz nasze własne podejście do tego tematu.

      Dlaczego monorepo?

      Istnieje powszechne przekonanie, że trzymanie całego kodu w jednym repozytorium wiąże się ze wszystkimi wadami aplikacji monolitycznych - nie skaluje się, zmusza nas do wydawania aplikacji razem… Jeśli tak, to dlaczego firmy takie jak Google czy Facebook używają monorepo? Prawda jest w rzeczywistości całkowicie odwrotna. Powód, dla którego podejście z jednym repozytorium na projekt jest tak popularne, to autonomia - zespoły mogą pracować w izolacji, podejmując decyzje oddzielnie. Chodzi o to, że przy odpowiednich narzędziach monorepo mogą mieć wszystkie zalety oddzielnych repozytoriów, a nawet więcej.

      Oto niektóre z funkcji, które oferuje monorepo:

      • Udostępnianie kodu - zamiast tworzyć oddzielne repozytoria dla wspólnego kodu lub nawet duplikować go w każdym repozytorium, możemy po prostu udostępniać wszystko między naszymi projektami.
      • Spójność - wszystkie projekty są budowane przy użyciu tych samych narzędzi
      • Widoczność i refaktoryzacja - pracując z mikroserwisami, łatwiej jest spojrzeć na kod w jednym miejscu niż szukać go w wielu repozytoriach

      Co jest unikalnego w naszym podejściu?

      Używanie monorepo samo w sobie może obniżyć koszty rozwoju, ale poszliśmy o krok dalej i korzystając z monorepo, stworzyliśmy ogólny szablon dla naszych nadchodzących projektów.

      Większość aplikacji zaczyna się w dość podobny sposób. Zawsze istnieje potrzeba skonfigurowania architektury i podstawowej konfiguracji aplikacji. Nawet bardziej specyficzne dla aplikacji moduły, takie jak autoryzacja, często mają wspólną logikę.

      Mając to wszystko na uwadze, pojawia się pomysł stworzenia pewnego rodzaju szablonu, który można wykorzystać w różnych projektach, oszczędzając dni lub tygodnie pracy całego zespołu.

      Aby udowodnić, że istnieje znacząca różnica w czasie między tworzeniem nowego projektu a korzystaniem z ogólnego, postanowiłem dać sobie 2 dni na skonfigurowanie projektu backendowego NestJS od podstaw.

      Na początku skorzystałem z NestJS CLI i wygenerowałem projekt startowy, który zawierał kilka podstawowych konfiguracji. Następnie, mimo że pracuję z NestJS na co dzień, zajęło mi kilka godzin skonfigurowanie połączenia z bazą danych i prostej walidacji zmiennych środowiskowych. Po kolejnych kilku godzinach udało mi się uruchomić podstawowe testy i stworzyć pipeline CI w Github Actions, aby uruchamiać je automatycznie.

      Zajęło mi trochę czasu, aby zdać sobie sprawę z popełnionych błędów, więc musiałem je naprawić. I oto byłem, po prawie 2 dniach zmagania się z podstawową konfiguracją aplikacji. Dlaczego tak się stało?

      Konfiguracja Twojego projektu zazwyczaj odbywa się raz na kilka miesięcy lub nawet rzadziej. Niezależnie od tego, ile lat doświadczenia lub wiedzy można mieć, niemożliwe jest zapamiętanie wszystkich małych szczegółów, które są niezbędne do stworzenia funkcjonalnej aplikacji komercyjnej.

      Nawet jeśli w jakiś sposób zapamiętałbym wszystko, co trzeba zrobić, zajęłoby to wieczność, aby doprowadzić to do etapu, w którym ma wszystkie funkcje i pomocniki, które my w EL Passion opracowaliśmy w naszym projekcie Flounder.

      Jak już wspomniałem, większość konfiguracji projektów jest podobna - ale nie do końca taka sama. Powiedzmy, że mamy nasz projekt startowy monorepo gotowy… ale czy naprawdę? Mimo że przygotowaliśmy architekturę i podstawowe funkcje, nie jest on właściwie dostosowywalny. Nie chcemy przeszukiwać wszystkich plików i zmieniać wartości nazw, ścieżek itp. za każdym razem, gdy zaczynamy nowy projekt.

      Aby to rozwiązać, opracowaliśmy rozwiązanie, które przekształca projekt w ogólny szablon, zastępując każdą wartość specyficzną dla projektu zmiennymi, aby można było go łatwo dostosować do różnych projektów.

      Możesz się zastanawiać, dlaczego nie zaczynamy od zmiennych od samego początku. Ponieważ projekt Flounder jest ciągle aktualizowany, potrzebujemy, aby był w pełni funkcjonalny, aby deweloperzy mogli go uruchamiać i rozwijać jak normalny projekt.

      Aby zautomatyzować procesy, stworzyliśmy pipeline CI, który najpierw uruchamia nasz skrypt, a następnie publikuje szablon w rejestrze pakietów Github, aby można go było wykonać za pomocą wiersza poleceń, zastępując wszystkie zmienne wartościami specyficznymi dla projektu lub nawet pomijając zasoby, których nie potrzebujemy w danym projekcie.

      Przewodnik krok po kroku, jak stworzyć ogólny szablon projektu monorepo

      Stworzymy w pełni funkcjonalny szablon projektu z wszystkimi wymienionymi powyżej funkcjami. Zacznijmy od utworzenia pustego środowiska roboczego Nx monorepo za pomocą Terminala.

      npx create-nx-workspace@latest

       

      Nx Startup

      Powinieneś zobaczyć nowo utworzony projekt. Teraz chcemy zainstalować preset NestJS jako zależność deweloperską w naszym projekcie.

      yarn add –dev @nrwl/nest

       

      Gdy zostanie zainstalowany, możemy wygenerować nową aplikację.

      nx generate @nrwl/nest:app backend

       

      Stworzymy również aplikację node jako bibliotekę

      yarn add –dev @nrwl/node

      nx generate @nrwl/node:lib utils

       

      Nx wygenerował całą konfigurację dla nas. Teraz możemy łatwo importować wszystko z biblioteki utils do każdego innego projektu. Poniżej możesz zobaczyć, jak zaimportowałem przykładową metodę z utils do usługi aplikacji w aplikacji NestJS.

      Jak widać, nasza aplikacja działa doskonale i jest gotowa do rozwoju. Nx zajął się wszystkim za nas i możemy korzystać ze wszystkich zalet monorepo.

      Nx Monorepo running projectUruchamianie projektu

      Następnym krokiem jest uczynienie aplikacji ogólną, aby mogła być używana jako startowa dla każdego innego projektu. Stwórzmy folder “template-setup” w głównym katalogu naszego projektu oraz plik “revert-to-template.js” wewnątrz niego. Stworzymy również plik “config.js”, w którym przechowamy kilka pomocniczych wartości. Struktura powinna wyglądać następująco:

      Struktura folderów projektuStruktura folderów projektu

      Co chcemy teraz zrobić, to skopiować pliki projektu i zastąpić wartości, które chcemy, aby były konfigurowalne, zmiennymi EJS. Musimy również dodać prefiks “_” do wszystkich plików zawierających zmienne, aby mogły być oceniane jako pliki EJS.

      Teraz, jeśli uruchomisz “node revert-to-template.js”, powinieneś zobaczyć nowo utworzony folder z zastąpionymi nazwami plików i naszą zmienną w package.json. Nie będziemy jednak uruchamiać tej komendy ręcznie, powinna być obsługiwana w przepływie pracy Github Actions, ale omówimy to później.

      Z szablonem przygotowanym, napiszemy kod, który może go wykorzystać i wygenerować projekt. Zacznijmy od stworzenia prostego pliku package.json z dwoma pakietami i właściwością “bin”, abyśmy mogli go uruchomić jako plik wykonywalny. Upewnij się, że w właściwości “name” zawrzesz swój profil lub nazwę organizacji na GitHubie, ponieważ będzie to używane później w przepływie CI do publikacji kodu.

      Na koniec skorzystamy z pakietu “commander”, aby stworzyć nasz program CLI. Będzie on przyjmował parametry podane przez użytkownika i generował nowy projekt przy użyciu pakietu “scaffe”.

      Możemy teraz przetestować przepływ, uruchamiając pliki ręcznie. Najpierw uruchom “node revert-to-template.js”, tak jak wcześniej. Teraz zmień katalog na nowo wygenerowany szablon, zainstaluj pakiety (“yarn install”) i wpisz “node index.js ~/path-to-project -p ProjectName”. Powinieneś zobaczyć projekt z zastąpioną wartością właściwości “name” w pliku package.json.

      Ostatnią rzeczą, którą musimy zrobić, jest stworzenie potoku CI, który publikuje nasz szablon do npm.

      Jeśli nie jesteś zaznajomiony z tym, co dzieje się w tym fragmencie, zachęcam do przeczytania więcej na temat dokumentacji Github Actions. Zasadniczo użyłem akcji “setup-node”, która tworzy plik “.nprmc” (więcej tutaj: Publikowanie pakietów Node.js), uruchomiłem nasz skrypt revert-to-template i opublikowałem go, używając automatycznie wygenerowanego sekretu GITHUB_TOKEN. Dodatkowo użyłem akcji do automatycznego zwiększania wersji package.json, aby uniknąć konfliktów.

      Teraz, jeśli wypchniemy nasz kod do repozytorium, powinniśmy zobaczyć działający przepływ pracy, a następnie nasz opublikowany pakiet.

      widok przepływu pracy github-actionsPodsumowanie widoku przepływu pracy Github Actions

      Spróbujmy go zainstalować i zobaczyć, czy wszystko działa! Pamiętaj, aby zalogować się do rejestru podczas instalacji prywatnych pakietów.

      Ustawienie i generacja nowego szablonu projektuUstawienie i generacja nowego szablonu projektu

      I to wszystko! Powinieneś zobaczyć w pełni funkcjonalny wygenerowany projekt z zastąpioną wartością nazwy w package.json.

      Ostateczne przemyślenia

      Znakiem dobrego procesu rozwoju oprogramowania jest stałe dążenie do uczynienia rzeczy bardziej elastycznymi i skalowalnymi, co bezpośrednio przekłada się na oszczędności kosztów i czasu. Przykładem jest nasz ogólny projekt szablonu.

      Przykład z tego artykułu dotyczył tylko prostej wygenerowanej aplikacji z jedną zmienną, jaką jest nazwa aplikacji. W naszym wewnętrznym rozwiązaniu w EL Passion przygotowaliśmy wiele aplikacji (frontend i backend) z modułami do ponownego użycia, a nawet konfigurację terraform dla infrastruktury AWS, co oszczędza dni pracy wielu deweloperów.

      Śledź nas, aby zobaczyć więcej treści!

      Sprawdź także

      Paweł Sierant

      Backend Developer

      Może to początek pięknej przyjaźni?

      Jesteśmy dostępni dla nowych projektów.

      Contact us