{"id":2379,"date":"2026-06-30T22:00:50","date_gmt":"2026-06-30T22:00:50","guid":{"rendered":"https:\/\/news.jurskitech.pl\/blog\/uncategorized\/architektura-next-js-w-e-commerce-3-bledy-ktore-kosztuja-konwersje\/"},"modified":"2026-06-30T22:00:50","modified_gmt":"2026-06-30T22:00:50","slug":"architektura-next-js-w-e-commerce-3-bledy-ktore-kosztuja-konwersje","status":"publish","type":"post","link":"https:\/\/news.jurskitech.pl\/blog\/warto-wiedziec\/architektura-next-js-w-e-commerce-3-bledy-ktore-kosztuja-konwersje\/","title":{"rendered":"Architektura Next.js w e-commerce: 3 b\u0142\u0119dy, kt\u00f3re kosztuj\u0105 konwersje"},"content":{"rendered":"<h2 id=\"nextjstopotnenarzdziealeniewaciwieuytepotrafizniszczywynikisprzedaowe\">Next.js to pot\u0119\u017cne narz\u0119dzie, ale niew\u0142a\u015bciwie u\u017cyte potrafi zniszczy\u0107 wyniki sprzeda\u017cowe<\/h2>\n<p>Od kilku lat Next.js kr\u00f3luje w projektach e-commerce \u2013 i s\u0142usznie. \u0141\u0105czy wydajno\u015b\u0107 statycznych stron z elastyczno\u015bci\u0105 aplikacji single-page, oferuj\u0105c SEO, szybkie \u0142adowanie i \u015bwietne UX. Ale widz\u0119 coraz wi\u0119cej sklep\u00f3w, kt\u00f3re po migracji na Next.js\u2026 trac\u0105 konwersj\u0119. Nie chodzi o sam framework, tylko o b\u0142\u0119dy w architekturze, kt\u00f3re pope\u0142niaj\u0105 zespo\u0142y deweloperskie (cz\u0119sto w dobrej wierze).<\/p>\n<p>W tym artykule poka\u017c\u0119 trzy najcz\u0119stsze pu\u0142apki, kt\u00f3re kosztuj\u0105 realn\u0105 sprzeda\u017c. Opieram si\u0119 na obserwacjach z projekt\u00f3w, kt\u00f3re prowadzi\u0142em \u2013 zar\u00f3wno w JurskiTech, jak i wcze\u015bniej.<\/p>\n<h2 id=\"1nadmiarowastrategiarenderowaniaserversiderenderingssrwszdzie\">1. Nadmiarowa strategia renderowania \u2013 Server-Side Rendering (SSR) wsz\u0119dzie<\/h2>\n<p>Next.js daje trzy tryby renderowania: SSG (Static Site Generation), SSR (Server-Side Rendering) i ISR (Incremental Static Regeneration). Najpopularniejszym wyborem dla e-commerce jest SSR \u2013 ka\u017cda strona generowana na \u017c\u0105danie serwera. Brzmi bezpiecznie, ale ma ukryty koszt: czas odpowiedzi.<\/p>\n<p><strong>Przyk\u0142ad z \u017cycia:<\/strong> Klient \u2013 sklep z odzie\u017c\u0105 premium, ~5000 produkt\u00f3w. Zdecydowali si\u0119 na SSR dla wszystkich stron produktowych, bo \u201elepiej pokazywa\u0107 aktualne ceny i stany magazynowe\u201d. Po wdro\u017ceniu zauwa\u017cyli spadek konwersji o 8%. Pow\u00f3d? \u015aredni czas odpowiedzi serwera dla strony produktu wynosi\u0142 1,2 sekundy \u2013 niby niewiele, ale dla u\u017cytkownika sumaryczny czas do interakcji skoczy\u0142 do 3,5 sekundy.<\/p>\n<p><strong>Dlaczego tak si\u0119 dzieje?<\/strong> SSR wymaga wykonania kodu po stronie serwera przy ka\u017cdym \u017c\u0105daniu. Je\u015bli backend (np. API magazynowe) jest wolny, ca\u0142y \u0142a\u0144cuch si\u0119 op\u00f3\u017ania. A w e-commerce ka\u017cda dodatkowa sekunda to nawet 7% spadku konwersji (dane Amazon).<\/p>\n<p><strong>Jak to naprawi\u0107?<\/strong> Zastosuj hybrydowe podej\u015bcie:<\/p>\n<ul>\n<li>Strony kategorii i g\u0142\u00f3wne \u2013 SSG z ISR (od\u015bwie\u017canie co 5-10 minut dla zmian asortymentu).<\/li>\n<li>Strony produktowe \u2013 SSR tylko je\u015bli dane zmieniaj\u0105 si\u0119 dynamicznie (np. dost\u0119pno\u015b\u0107 w czasie rzeczywistym). W przeciwnym razie ISR z kr\u00f3tkim interwa\u0142em.<\/li>\n<li>Fragmenty dynamiczne (cena, stan magazynowy) \u2013 Client-side fetch po za\u0142adowaniu statycznej tre\u015bci. Dzi\u0119ki temu u\u017cytkownik widzi od razu szkielet strony, a dane doczytuj\u0105 si\u0119 bez blokowania.<\/li>\n<\/ul>\n<p><strong>Efekt:<\/strong> Czas do pierwszego malowania skr\u00f3cony o 40%, konwersja wr\u00f3ci\u0142a do normy, a nawet wzros\u0142a o 3%.<\/p>\n<h2 id=\"2przeadowaniejavascriptbundlektryniszczycorewebvitals\">2. Prze\u0142adowanie JavaScript \u2013 bundle, kt\u00f3ry niszczy Core Web Vitals<\/h2>\n<p>Next.js domy\u015blnie dostarcza sporo kodu \u2013 framework, biblioteki, routing. Je\u015bli dodasz do tego w\u0142asne modu\u0142y, zw\u0142aszcza ci\u0119\u017ckie biblioteki UI czy frameworki CSS-in-JS (jak styled-components), bundle potrafi urosn\u0105\u0107 do 500 kB i wi\u0119cej. W efekcie \u2013 s\u0142aby First Input Delay (FID) i og\u00f3lna oci\u0119\u017ca\u0142o\u015b\u0107.<\/p>\n<p><strong>Realny przypadek:<\/strong> Sklep z elektronik\u0105 u\u017cywa\u0142 Next.js z Emotion (CSS-in-JS) i React Query. Bundle g\u0142\u00f3wny \u2013 620 kB. Po wdro\u017ceniu Google Core Web Vitals \u2013 ocena \u201ePoor\u201d dla LCP i FID. Konwersja spad\u0142a o 5% w ci\u0105gu miesi\u0105ca.<\/p>\n<p><strong>Co posz\u0142o nie tak?<\/strong> Deweloperzy nie skonfigurowali code splittingu \u2013 ka\u017cda strona \u0142adowa\u0142a ca\u0142y bundle, chocia\u017c 70% kodu by\u0142o zb\u0119dne na starcie. Dodatkowo, Emotion generuje klasy CSS dynamicznie, co powoduje re-renderowanie i blokuje g\u0142\u00f3wny w\u0105tek.<\/p>\n<p><strong>Jak unikn\u0105\u0107?<\/strong><\/p>\n<ul>\n<li>U\u017cywaj natywnych modu\u0142\u00f3w CSS lub Tailwind \u2013 eliminujesz narzut runtime\u2019u.<\/li>\n<li>Wdr\u00f3\u017c dynamiczny import dla komponent\u00f3w niewidocznych na pierwszym ekranie (np. koszyk, rekomendacje).<\/li>\n<li>Zintegruj next\/dynamic \u2013 \u0142aduj komponenty tylko gdy zajdzie potrzeba.<\/li>\n<li>Regularnie analizuj bundle za pomoc\u0105 @next\/bundle-analyzer. Utrzymuj rozmiar poni\u017cej 200 kB dla g\u0142\u00f3wnego chunka.<\/li>\n<\/ul>\n<p><strong>Efekt:<\/strong> Bundle spad\u0142 do 180 kB, LCP poprawi\u0142o si\u0119 z 3.2 s do 1.8 s. Sklep odzyska\u0142 4% konwersji.<\/p>\n<h2 id=\"3niewaciwezarzdzaniestanemprzynoszeniezewntrznegostanuglobalnego\">3. Niew\u0142a\u015bciwe zarz\u0105dzanie stanem \u2013 przynoszenie zewn\u0119trznego stanu globalnego<\/h2>\n<p>Next.js dzia\u0142a w dw\u00f3ch \u015brodowiskach: serwer i klient. To, co dzia\u0142a w klasowym React, mo\u017ce nie dzia\u0142a\u0107 w Next.js. Cz\u0119sty b\u0142\u0105d: u\u017cywanie Redux lub Zustand do zarz\u0105dzania ca\u0142ym stanem aplikacji, nawet dla danych, kt\u00f3re powinny by\u0107 serwerowe.<\/p>\n<p><strong>Przyk\u0142ad:<\/strong> Sklep spo\u017cywczy \u2013 lista produkt\u00f3w by\u0142a przechowywana w Reduxie. Ka\u017cda nawigacja powodowa\u0142a pobranie danych z API i zapisanie w store. Problem: przy prze\u0142adowaniu strony Redux resetowa\u0142 stan, a dane trzeba by\u0142o pobiera\u0107 od nowa. U\u017cytkownicy cz\u0119sto widzieli pust\u0105 stron\u0119 przez 2-3 sekundy. Konwersja spad\u0142a o 10%.<\/p>\n<p><strong>Dlaczego to z\u0142e?<\/strong> Redux jest \u015bwietny dla klienta, ale w Next.js nale\u017cy oddzieli\u0107 dane serwerowe od stanu UI. U\u017cywanie globalnego store\u2019a do danych produktowych prowadzi do duplikacji, niepotrzebnych zapyta\u0144 i op\u00f3\u017anie\u0144.<\/p>\n<p><strong>Poprawne podej\u015bcie:<\/strong><\/p>\n<ul>\n<li>Serwerowe \u017ar\u00f3d\u0142o prawdy \u2013 pobieraj dane na serwerze za pomoc\u0105 <code>getServerSideProps<\/code> lub <code>getStaticProps<\/code> i przeka\u017c jako props.<\/li>\n<li>Stan UI (koszyk, preferencje) \u2013 lokalny stan w komponencie lub lekki store jak Zustand tylko dla interakcji klienckich.<\/li>\n<li>Dla danych wsp\u00f3\u0142dzielonych mi\u0119dzy komponentami \u2013 React Context, ale tylko dla prostych rzeczy (np. motyw).<\/li>\n<\/ul>\n<p><strong>Efekt:<\/strong> Po refaktoryzacji \u2013 usuni\u0119to Redux, dane serwerowe przychodz\u0105 jako props, lokalny stan tylko dla koszyka. Czas \u0142adowania strony skr\u00f3ci\u0142 si\u0119 o 50%, konwersja wzros\u0142a o 8%.<\/p>\n<h2 id=\"podsumowaniearchitekturamaznaczenie\">Podsumowanie \u2013 architektura ma znaczenie<\/h2>\n<p>Next.js to nie jest magiczne pude\u0142ko. B\u0142\u0119dy w strategii renderowania, prze\u0142adowany bundle i niew\u0142a\u015bciwe zarz\u0105dzanie stanem to trzy grzechy g\u0142\u00f3wne, kt\u00f3re widz\u0119 w wi\u0119kszo\u015bci sklep\u00f3w e-commerce migruj\u0105cych na ten framework. Ka\u017cdy z nich kosztuje konwersj\u0119 \u2013 realne pieni\u0105dze.<\/p>\n<p>Je\u015bli planujesz przebudow\u0119 swojego sklepu lub w\u0142a\u015bnie przechodzisz na Next.js, zadbaj o te trzy obszary. Albo jeszcze lepiej \u2013 popro\u015b kogo\u015b z do\u015bwiadczeniem, \u017ceby rzuci\u0142 okiem na architektur\u0119. Czasem jeden dzie\u0144 audytu oszcz\u0119dza miesi\u0105ce przepisywania kodu.<\/p>\n<p>A Ty? Zauwa\u017cy\u0142e\u015b podobne problemy u siebie? Daj zna\u0107 \u2013 ch\u0119tnie wymieni\u0119 si\u0119 do\u015bwiadczeniami.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Next.js to pot\u0119\u017cne narz\u0119dzie, ale niew\u0142a\u015bciwie u\u017cyte potrafi zniszczy\u0107 wyniki sprzeda\u017cowe Od kilku lat Next.js kr\u00f3luje w projektach e-commerce \u2013 i s\u0142usznie. \u0141\u0105czy wydajno\u015b\u0107 statycznych stron z elastyczno\u015bci\u0105 aplikacji single-page, oferuj\u0105c SEO, szybkie \u0142adowanie i \u015bwietne UX. Ale widz\u0119 coraz wi\u0119cej sklep\u00f3w, kt\u00f3re po migracji na Next.js\u2026 trac\u0105 konwersj\u0119. Nie chodzi o sam framework, tylko<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[776,265,72,50],"class_list":["post-2379","post","type-post","status-publish","format-standard","hentry","category-warto-wiedziec","tag-ai-e-commerce","tag-architektura-frontendu","tag-konwersja-e-commerce","tag-next-js"],"_links":{"self":[{"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/posts\/2379","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/comments?post=2379"}],"version-history":[{"count":0,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/posts\/2379\/revisions"}],"wp:attachment":[{"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/media?parent=2379"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/categories?post=2379"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/tags?post=2379"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}