← Wszystkie tematy W 72% ogłoszeń · 34 z 47 ogłoszeń frontend React

Architektura frontendu

Plan miasta z klocków

Architektura pojawia się w 34 z 47 ogłoszeń, zwykle jako „frontend architecture” albo „component-based application architecture”. Na rozmowie chodzi o to, czy umiesz podzielić dużą aplikację i uzasadnić decyzje.

Opanowane 0 z 4 pytań

Co piszą w ogłoszeniach

Scena · zależności między modułami

Miasto z klocków

Duża aplikacja to miasto. Każdy budynek to moduł: koszyk, produkty, płatności. Strzałka znaczy „ten budynek korzysta z tamtego”. Kliknij budynek, żeby go przebudować, i zobacz, ile innych budynków trzeba wtedy sprawdzić. W mieście-spaghetti każdy łączy się z każdym. W mieście z dzielnicami są porządne drogi i jeden wjazd do każdej dzielnicy.

 
kliknij budynek

Kliknij „Koszyk” w obu miastach i porównaj.

Porównajmy

Spaghetti czy dzielnice?

Warstwy / spaghettiDzielnice / feature-based
Gdzie leży kod koszyka? Po kawałku w każdym folderze.components/, hooks/, services/, utils/ W jednej dzielnicy.features/cart/ z komponentami, hookami i API razem.
Kto może wejść do środka? Każdy, każdymi drzwiami.Importy z głębi innych modułów. Tylko przez bramę.Publiczne API: features/cart/index.ts, reguły ESLint (boundaries) zabraniają głębokich importów.
Kręcenie się w kółko Koszyk woła produkty, a produkty koszyk.Cykliczne zależności, kruche testy, dziwne błędy kolejności importów. Drogi idą w jedną stronę.Kierunek: app → features → shared. Wspólne rzeczy schodzą do shared/.
Zmiana w jednym budynku Trzeba sprawdzać pół miasta.Duży „blast radius”, trudne code review. Sprawdzasz dzielnicę i jej sąsiadów.Mały zasięg zmian, łatwiej podzielić pracę między zespoły.
Kiedy wystarczy? Mała aplikacja na kilka ekranów.Prosto na start. Gdy rośnie liczba funkcji i ludzi.Skaluje się na zespoły, przygotowuje grunt pod monorepo i mikrofrontendy.

Dzielnice

Wszystko o koszyku mieszka razem, w jednej dzielnicy.

Brama

Do dzielnicy wchodzi się tylko przez bramę (index.ts), nie przez okno.

Jednokierunkowe drogi

Strzałki płyną w dół: aplikacja → funkcje → wspólne klocki. Nigdy w kółko.

Sprawdź się

Pytania z rozmów

Najpierw odpowiedz na głos, dopiero potem rozwiń odpowiedź.

  1. Jak dzielisz dużą aplikację React na moduły i foldery? Feature-based czy layer-based?

    Moja odpowiedź

    Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

    Pokaż odpowiedź

    Dla przedszkolaka: Wszystko o koszyku mieszka w jednej dzielnicy, a nie po kawałku w każdym budynku miasta.

    Na rozmowę: Przy małej aplikacji wystarczą warstwy (components, hooks, services). Gdy rośnie, przechodzę na feature-based: features/cart z komponentami, hookami, API i testami razem, plus shared/ na rzeczy naprawdę wspólne i app/ na routing i providery. Każdy feature wystawia publiczne API przez index.ts. Zmiany są wtedy lokalne, a łatwiej dzielić pracę między zespoły. Wzorcem może być Feature-Sliced Design.

    Umiem?
    Zapytaj Claude RozwińPrzepytaj mniePytania pogłębiające
  2. Gdzie kończy się komponent prezentacyjny, a zaczyna logika? Jak wydzielasz custom hooki?

    Moja odpowiedź

    Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

    Pokaż odpowiedź

    Dla przedszkolaka: Klocek pokazuje, a pomocnik w środku myśli. Pomocnika możesz wsadzić do innego klocka.

    Na rozmowę: Komponent prezentacyjny dostaje dane i callbacki przez propsy i nie wie, skąd pochodzą, więc łatwo go testować i pokazać w Storybooku. Logikę (pobieranie danych, stan formularza, efekty, subskrypcje) wyciągam do custom hooka, np. useCart() zwracający {items, add, total}. Hook wydzielam, gdy logika się powtarza albo komponent miesza dwie odpowiedzialności. Nie robię tego na siłę dla 3 linijek.

    Umiem?
    Zapytaj Claude RozwińPrzepytaj mniePytania pogłębiające
  3. Jak zapobiegasz temu, żeby moduły zależały od siebie nawzajem w kółko?

    Moja odpowiedź

    Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

    Pokaż odpowiedź

    Dla przedszkolaka: Drogi w mieście idą w jedną stronę: z centrum na przedmieścia, nigdy w kółko.

    Na rozmowę: Ustalam kierunek zależności: app → features → shared, a features nie importują się nawzajem przez głębokie ścieżki, tylko przez publiczne API. Pilnuje tego narzędzie: eslint-plugin-boundaries lub import/no-cycle, dependency-cruiser albo reguły Nx. Gdy dwa moduły czegoś potrzebują od siebie nawzajem, wspólną część przenoszę niżej (do shared albo nowego modułu) albo odwracam zależność przez zdarzenie lub callback.

    Umiem?
    Zapytaj Claude RozwińPrzepytaj mniePytania pogłębiające
  4. Opowiedz o decyzji architektonicznej, którą podjąłeś: alternatywy, koszty, efekt.

    Moja odpowiedź

    Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

    Pokaż odpowiedź

    Na rozmowę: Struktura odpowiedzi (STAR + trade-off): kontekst i problem (np. kilka zespołów blokowało się na jednym repo), rozważane opcje (monorepo z Nx, Module Federation, zostawić jak jest) i ich koszty, decyzja i jak ją wprowadzałem (migracja krok po kroku, ADR, rozmowy z zespołami), efekt w liczbach (czas buildu, liczba konfliktów, czas wdrożenia). Na koniec, co zrobiłbym dziś inaczej. Ważne, żeby mówić o swoim wkładzie, a nie o decyzji „zespołu”.

    Umiem?
    Zapytaj Claude RozwińPrzepytaj mniePytania pogłębiające
Poziom wyżej

Wersja dla seniora

Tak wyglądają pytania na seniora i leada: nie ma jednej dobrej odpowiedzi, liczy się to, jak ważysz kompromisy i czy mówisz o skali, ryzyku i ludziach.

Przypadek 1

Jeden monolit frontendowy, sześć zespołów i ciągłe konflikty

Sklep internetowy to jedna aplikacja React, nad którą pracuje 6 zespołów (katalog, koszyk, płatności, konto, wyszukiwarka, CMS). Merge conflicty są codziennością, wdrożenie raz w tygodniu wymaga koordynacji wszystkich, a zmiana w jednym miejscu psuje inne. Zaproponuj docelową architekturę i drogę do niej.

Zanim rozwiniesz: powiedz na głos, jak byś to rozwiązał, i nazwij co najmniej jeden kompromis.

Moje rozwiązanie

Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

Pokaż, czego szuka rekruter, i modelową odpowiedź

Co sprawdza rekruter

  • Czy dobierasz granice modułów do domen i zespołów
  • Czy porównujesz opcje (modularny monolit, monorepo, mikrofrontendy) z kosztami
  • Czy planujesz przejście bez zatrzymania rozwoju
  • Czy myślisz o własności kodu i procesie

Odpowiedź seniora

Problemem nie jest jedna aplikacja, tylko brak granic. Najpierw modularny monolit: moduły według domen (features/catalog, features/cart…) z publicznym API przez index.ts, granicami pilnowanymi przez eslint-plugin-boundaries lub reguły Nx oraz CODEOWNERS, więc każdy zespół ma swój obszar i swoje review.

Następnie monorepo (Nx lub Turborepo) z modułami jako paczkami: build i testy tylko dotkniętych projektów, cache, wspólne paczki design systemu i klienta API. Niezależne wdrożenia uzyskuję przez trunk-based development, feature flags i częste, małe deploye, zamiast wydań raz w tygodniu.

Mikrofrontendy rozważam dopiero, gdy zespoły naprawdę potrzebują niezależnych cykli wydań lub różnych technologii, bo kosztują: duplikację zależności, spójność UI, komunikację między aplikacjami i złożoną infrastrukturę. Migracja idzie od najbardziej konfliktowego obszaru, z metrykami: liczba konfliktów, czas od merge do produkcji, liczba incydentów po wdrożeniu.

Typowe wpadki

  • Od razu mikrofrontendy jako odpowiedź na problem organizacyjny
  • Podział na foldery bez wymuszenia granic
  • Brak metryk, po których poznamy, że jest lepiej

Dopytają o

  • Jak zespoły współdzielą komponenty bez blokowania się?
  • Kto jest właścicielem modułów wspólnych?
  • Jak wygląda routing między modułami?
Zapytaj Claude Rozwiń caseZagraj interviewera
Przypadek 2

Warstwa danych, która uniezależni frontend od chaosu w backendzie

Frontend korzysta z trzech backendów o różnych konwencjach (snake_case, różne formaty dat i błędów, paginacja offsetowa i kursorowa). Komponenty same mapują odpowiedzi, więc zmiana jednego endpointu wymaga poprawek w 20 miejscach.

Zanim rozwiniesz: powiedz na głos, jak byś to rozwiązał, i nazwij co najmniej jeden kompromis.

Moje rozwiązanie

Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

Pokaż, czego szuka rekruter, i modelową odpowiedź

Co sprawdza rekruter

  • Czy wydzielasz warstwę dostępu do danych z modelem domenowym
  • Czy rozważasz BFF i jego koszt
  • Czy myślisz o testowalności i stopniowym wdrożeniu

Odpowiedź seniora

Wprowadzam warstwę danych z jasnym kontraktem: per domena moduł api (np. orders/api.ts), który woła backend, waliduje odpowiedź i mapuje ją na model domenowy frontendu (camelCase, Date zamiast stringów, jeden format błędu, jednolita paginacja). Komponenty i hooki (useOrders na TanStack Query) znają tylko model domenowy.

Jeśli niespójności jest dużo i dotyczą kilku klientów (web, mobile), proponuję BFF w Node.js, który agreguje i normalizuje dane po stronie serwera, ogranicza liczbę żądań i ukrywa wewnętrzne API. Koszt to kolejna usługa do utrzymania, więc BFF ma właściciela we frontendzie.

Migracja: nowe użycia od razu przez warstwę, stare przepinam przy zmianach. Testy mapperów jednostkowo na zapisanych odpowiedziach, a komponentów z MSW na modelu domenowym.

Typowe wpadki

  • Mapowanie odpowiedzi w każdym komponencie
  • Generyczny „ApiService” z jedną metodą fetch(url) bez modelu
  • BFF bez właściciela i monitoringu

Dopytają o

  • Gdzie umieścisz obsługę autoryzacji i odświeżania tokenu?
  • Jak przetestujesz zgodność z prawdziwym API?
  • Kiedy BFF to przesada?
Zapytaj Claude Rozwiń caseZagraj interviewera
Przypadek 3

Aplikacja dla serwisantów, która musi działać bez zasięgu

Serwisanci pracują w piwnicach i halach bez internetu. Aplikacja ma pozwolić przeglądać zlecenia, robić zdjęcia i wypełniać protokoły offline, a potem zsynchronizować dane. Dziś bez sieci pokazuje biały ekran.

Zanim rozwiniesz: powiedz na głos, jak byś to rozwiązał, i nazwij co najmniej jeden kompromis.

Moje rozwiązanie

Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

Pokaż, czego szuka rekruter, i modelową odpowiedź

Co sprawdza rekruter

  • Czy znasz elementy architektury offline-first
  • Czy rozumiesz problem konfliktów przy synchronizacji
  • Czy umiesz ocenić ograniczenia przeglądarek

Odpowiedź seniora

Architektura offline-first: aplikacja jako PWA z Service Workerem (Workbox) cache'ującym shell i zasoby, a dane w IndexedDB (Dexie) jako lokalne źródło prawdy. UI czyta z lokalnej bazy, a nie bezpośrednio z API.

Zapisy offline trafiają do kolejki operacji (outbox) z id generowanym na kliencie (UUID) i znacznikiem czasu. Po powrocie sieci synchronizator wysyła operacje po kolei, serwer jest idempotentny po id operacji. Konflikty rozwiązuję zależnie od danych: protokół serwisanta należy do jednej osoby, więc wystarczy wersjonowanie i odrzucenie z prośbą o decyzję, a przy wspólnych danych last-write-wins per pole albo CRDT, jeśli edycji równoległych jest dużo.

Zdjęcia zapisuję jako Blob w IndexedDB z kompresją, pilnuję limitów (navigator.storage.estimate, persist). Background Sync nie działa w Safari, więc synchronizację uruchamiam też przy starcie i zdarzeniu online. W UI jasny status: „3 protokoły czekają na wysłanie”.

Typowe wpadki

  • Cache API odpowiedzi w Service Workerze jako całe rozwiązanie
  • Brak id po stronie klienta, przez co powstają duplikaty
  • Ignorowanie limitów pamięci i Safari

Dopytają o

  • Jak zmigrujesz schemat IndexedDB przy nowej wersji aplikacji?
  • Co, jeśli serwisant wyloguje się z niewysłanymi danymi?
  • Jak przetestujesz synchronizację?
Zapytaj Claude Rozwiń caseZagraj interviewera
Przypadek 4

Konfigurowalny produkt dla 40 klientów i rosnąca liczba if-ów

Sprzedajecie ten sam system 40 firmom. Każda chce trochę inny formularz, inne kolumny i inne kroki procesu. Kod jest pełen warunków typu if (client === 'acme'), a każde wdrożenie nowego klienta trwa tygodnie.

Zanim rozwiniesz: powiedz na głos, jak byś to rozwiązał, i nazwij co najmniej jeden kompromis.

Moje rozwiązanie

Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

Pokaż, czego szuka rekruter, i modelową odpowiedź

Co sprawdza rekruter

  • Czy rozpoznajesz problem konfiguracji vs kustomizacji
  • Czy znasz wzorce: feature flags, konfiguracja z serwera, rozszerzenia
  • Czy dbasz o testowalność wariantów

Odpowiedź seniora

Zamieniam warunki na nazwane możliwości: zamiast if (client === 'acme') pytam if (features.has('approvalStep')). Konfiguracja klienta (flagi, kolumny, pola formularza, teksty) przychodzi z serwera jako walidowany JSON, a frontend ma schemat tej konfiguracji w zod.

Dla formularzy i tabel stosuję podejście schema-driven: definicja pól z typem, walidacją i warunkami widoczności, a komponent renderuje ją przez rejestr typów pól. Prawdziwie unikalne potrzeby obsługują punkty rozszerzeń (sloty, rejestr komponentów), a nie forki kodu.

Testy: kontraktowe dla schematu konfiguracji i E2E dla kilku reprezentatywnych zestawów flag. Ograniczam liczbę wariantów rozmową z produktem, bo każda flaga to koszt na zawsze, i usuwam martwe flagi.

Typowe wpadki

  • Osobna gałąź kodu dla każdego klienta
  • Konfiguracja bez schematu i walidacji
  • Silnik formularzy tak ogólny, że nikt go nie rozumie

Dopytają o

  • Gdzie kończy się konfiguracja, a zaczyna kod?
  • Jak wersjonujesz konfigurację klientów?
  • Jak sprzątasz stare flagi?
Zapytaj Claude Rozwiń caseZagraj interviewera

Skróty klawiszowe

/
szukaj tematu
Enter
w wyszukiwarce: otwórz pierwszy wynik
N
notatki do tematu
[ ]
poprzedni / następny temat
G potem T
lista tematów
G potem P
powtórka
G potem N
wszystkie notatki
D
jasny / ciemny motyw
?
ta ściąga
Spacja, 1, 2, 3
w powtórce: pokaż, oceń

Pod każdym pytaniem są też skróty do Claude: rozwinięcie tematu, próbna rozmowa i ocena Twojej odpowiedzi z notatki.