Kurs JavaScript i React · Moduł 1: Podstawy React

Konfiguracja środowiska

5 min czytania
W tej lekcji6

Szykując się do podróży przez wszechświat React, potrzebujemy odpowiedniego statku kosmicznego, który zabierze nas w tę fascynującą przygodę. Tym statkiem będzie nasze środowisko programistyczne, które musimy poprawnie skonfigurować, aby nasza podróż przebiegała sprawnie.

Zacznijmy od problemu. Przeglądarka nie rozumie składni JSX, którą zobaczyłeś w komponentach. Nie wie też, jak połączyć dziesiątki plików w jedną szybką aplikację. Ktoś musi przetłumaczyć i spakować nasz kod, zanim trafi do użytkownika. Tym kimś są narzędzia deweloperskie, a właśnie ich przygotowaniem zajmiemy się w tej lekcji. Tłumaczeniem JSX zajmuje się kompilator, np. Babel: najpierw parsuje kod do drzewa składni (AST, Abstract Syntax Tree), potem przekształca to drzewo za pomocą pluginów i presetów, a na końcu generuje zwykły JavaScript zrozumiały dla przeglądarek.

Dlaczego konfiguracja środowiska jest ważna?

Dobrze skonfigurowane środowisko programistyczne to fundament efektywnej pracy z React. Pozwala na:

  • Szybkie tworzenie i testowanie komponentów
  • Automatyczne odświeżanie strony po wprowadzeniu zmian (Hot Reloading)
  • Wykrywanie błędów na wczesnym etapie
  • Optymalizację kodu przed wdrożeniem produkcyjnym

Co do drugiego punktu: w Vite ten mechanizm nazywa się HMR (Hot Module Replacement), a w projektach React działa w wersji Fast Refresh. Po zapisaniu pliku zmienia się tylko edytowany komponent, a stan pozostałych części aplikacji zostaje zachowany.

Wyobraź sobie próbę budowy zaawansowanego statku kosmicznego bez odpowiednich narzędzi - byłoby to niezwykle trudne i czasochłonne. Podobnie jest z tworzeniem aplikacji React bez właściwego środowiska.

Wymagania wstępne

Zanim zaczniemy konfigurować nasze środowisko React, upewnijmy się, że mamy zainstalowane wszystkie niezbędne narzędzia:

  1. Edytor kodu - Polecamy Visual Studio Code, który oferuje świetne wsparcie dla React dzięki wielu rozszerzeniom
  2. Przeglądarka internetowa - Najlepiej Chrome lub Firefox z zainstalowanymi React Developer Tools
  3. Terminal - Wbudowany terminal w systemie operacyjnym lub zintegrowany z edytorem kodu

Gdy mamy już te podstawowe narzędzia, możemy przejść do konfiguracji środowiska React.

Node.js - silnik w maszynowni

Jest jeszcze czwarty, najważniejszy element: Node.js, czyli środowisko uruchamiające JavaScript poza przeglądarką. Sam React działa w przeglądarce użytkownika, więc Node.js nie jest częścią gotowej aplikacji. Potrzebujemy go na naszym komputerze, żeby uruchamiać narzędzia deweloperskie: serwer podglądu, kompilator JSX i proces budowania wersji produkcyjnej. Razem z Node.js instaluje się menedżer pakietów npm, którym pobierzemy Reacta i Vite.

Po instalacji (krok po kroku przejdziemy ją w następnej lekcji) sprawdzisz w terminalu, czy silnik działa:

1node -v
2npm -v

Każde polecenie powinno wypisać numer wersji. Jeśli terminal odpowie, że nie zna polecenia, Node.js nie jest jeszcze zainstalowany albo terminal trzeba uruchomić ponownie. Nic w twoim projekcie się przy tym nie zmienia, to tylko kontrola przed startem.

Wybór podejścia do konfiguracji

Istnieją dwa główne podejścia do konfiguracji środowiska React:

  1. Narzędzia budujące od zera - Konfiguracja Webpack, Babel i innych narzędzi ręcznie
  2. Gotowe rozwiązania - Użycie narzędzi takich jak Vite, Next.js czy Remix

Dla początkujących zdecydowanie zalecamy drugie podejście, ponieważ pozwala skupić się na nauce React, a nie na detalach konfiguracyjnych.

Warto wiedzieć, co dokładnie mówi dziś dokumentacja na react.dev. Dla nowych aplikacji zaleca ona start od frameworka, takiego jak Next.js, React Router (w wersji 7, do której przeniesiono rozwój Remixa) albo Expo dla aplikacji mobilnych. Jeśli budujesz aplikację bez frameworka, dokumentacja wskazuje narzędzia budujące Vite, Parcel i Rsbuild.

W naszym kursie będziemy korzystać z Vite - nowoczesnego, szybkiego narzędzia budującego, które dokumentacja React wymienia wśród zalecanych sposobów tworzenia projektu bez frameworka. Wybieram je celowo: nie dokłada własnych reguł routingu ani pobierania danych, więc widzisz czysty React. Create React App (CRA) został wycofany i nie jest już rozwijany - zespół React ogłosił to w lutym 2025 roku, więc jeśli trafisz na tutorial z create-react-app, traktuj go jako archiwalny.

Co dostaniesz w projekcie Vite

Projekt utworzony przez Vite ma w pliku package.json gotowe skrypty. To one uruchamiają narzędzia działające na Node.js:

1{
2  "scripts": {
3    "dev": "vite",
4    "build": "vite build",
5    "preview": "vite preview"
6  }
7}

Polecenie npm run dev startuje serwer podglądu z Fast Refresh, npm run build tworzy zoptymalizowaną wersję produkcyjną w folderze dist, a npm run preview pozwala ją obejrzeć lokalnie. Twój kod komponentów pozostaje ten sam we wszystkich trzech przypadkach, zmienia się tylko sposób, w jaki narzędzia go przygotowują.

Pierwszy rzut oka przez React Developer Tools

Rozszerzenie React Developer Tools pokaże ci drzewo komponentów działającej aplikacji. Zobaczysz w nim ważną zasadę Reacta: jednokierunkowy przepływ danych. Dane płyną z komponentu nadrzędnego do potomnego przez propsy, nigdy odwrotnie:

1function Bridge() {
2  return <FuelGauge fuel={80} />;
3}

Tutaj Bridge przekazuje wartość fuel w dół do FuelGauge. Dziecko może ją wyświetlić, ale nie może jej zmienić u rodzica - w DevTools zobaczysz ją jako props komponentu FuelGauge. Więcej o tym przepływie dowiesz się, gdy zaczniemy budować własne komponenty.

Moja rekomendacja: zainstaluj od razu VS Code, aktualną wersję LTS Node.js i React Developer Tools, a projekty twórz przez Vite. Ten zestaw wystarczy na cały kurs. W następnej lekcji przejdziemy krok po kroku przez instalację Node.js i npm.

W piaskownicy poniżej możesz rozwinąć karty różnych narzędzi i porównać ich wady oraz zalety.

Zapamiętaj: Node.js to silnik w maszynowni, który napędza narzędzia deweloperskie, a Vite to statek, którym wygodnie wystartujesz z Reactem.

Kod do tej lekcji: App.jsx
1import React from 'react';
2
3// Komponent do demonstracji różnych narzędzi
4function DevelopmentTool({ name, logo, type, description, pros, cons, difficulty }) {
5  const [isExpanded, setIsExpanded] = React.useState(false);
6
7  const getDifficultyColor = (level) => {
8    switch(level) {
9      case 'Łatwy': return '#4caf50';
10      case 'Średni': return '#ff9800';
11      case 'Trudny': return '#f44336';
12      default: return '#666';
13    }
14  };
15
16  const getTypeColor = (toolType) => {
17    switch(toolType) {
18      case 'Narzędzie CLI': return '#2196f3';
19      case 'Narzędzie budowania': return '#9c27b0';
20      case 'Framework': return '#ff5722';
21      default: return '#666';
22    }
23  };
24
25  return (
26    <div style={{
27      border: '2px solid #e0e0e0',
28      borderRadius: '12px',
29      margin: '15px 0',
30      overflow: 'hidden',
31      transition: 'all 0.3s ease',
32      boxShadow: isExpanded ? '0 8px 25px rgba(0,0,0,0.15)' : '0 2px 8px rgba(0,0,0,0.1)'
33    }}>
34      <div
35        style={{
36          padding: '20px',
37          backgroundColor: 'white',
38          cursor: 'pointer',
39          display: 'flex',
40          alignItems: 'center',
41          justifyContent: 'space-between'
42        }}
43        onClick={() => setIsExpanded(!isExpanded)}
44      >
45        <div style={{ display: 'flex', alignItems: 'center', gap: '15px' }}>
46          <div style={{ fontSize: '48px' }}>{logo}</div>
47          <div>
48            <h3 style={{ margin: '0 0 5px 0', color: '#333' }}>{name}</h3>
49            <div style={{ display: 'flex', gap: '10px' }}>
50              <span style={{
51                padding: '4px 12px',
52                backgroundColor: getTypeColor(type),
53                color: 'white',
54                borderRadius: '15px',
55                fontSize: '12px',
56                fontWeight: 'bold'
57              }}>
58                {type}
59              </span>
60              <span style={{
61                padding: '4px 12px',
62                backgroundColor: getDifficultyColor(difficulty),
63                color: 'white',
64                borderRadius: '15px',
65                fontSize: '12px',
66                fontWeight: 'bold'
67              }}>
68                {difficulty}
69              </span>
70            </div>
71          </div>
72        </div>
73        <div style={{
74          fontSize: '20px',
75          color: '#666',
76          transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)',
77          transition: 'transform 0.3s ease'
78        }}>
79          ▼
80        </div>
81      </div>
82
83      {isExpanded && (
84        <div style={{
85          padding: '20px',
86          backgroundColor: '#f8f9fa',
87          borderTop: '1px solid #e0e0e0'
88        }}>
89          <p style={{
90            marginBottom: '20px',
91            color: '#666',
92            lineHeight: '1.6',
93            fontSize: '16px'
94          }}>
95            {description}
96          </p>
97
98          <div style={{
99            display: 'grid',
100            gridTemplateColumns: '1fr 1fr',
101            gap: '20px'
102          }}>
103            <div>
104              <h4 style={{ color: '#4caf50', marginBottom: '10px' }}>Zalety</h4>
105              <ul style={{ margin: 0, paddingLeft: '20px', color: '#333' }}>
106                {pros.map((pro, index) => (
107                  <li key={index} style={{ marginBottom: '5px' }}>{pro}</li>
108                ))}
109              </ul>
110            </div>
111
112            <div>
113              <h4 style={{ color: '#f44336', marginBottom: '10px' }}>Wady</h4>
114              <ul style={{ margin: 0, paddingLeft: '20px', color: '#333' }}>
115                {cons.map((con, index) => (
116                  <li key={index} style={{ marginBottom: '5px' }}>{con}</li>
117                ))}
118              </ul>
119            </div>
120          </div>
121        </div>
122      )}
123    </div>
124  );
125}
126
127// Komponent do demonstracji procesu konfiguracji
128function SetupProcess() {
129  const [currentStep, setCurrentStep] = React.useState(0);
130  const [selectedTool, setSelectedTool] = React.useState('Vite');
131
132  const steps = {
133    CRA: [
134      {
135        title: "Sprawdź Node.js",
136        command: "node --version",
137        expected: "v20.19.0 lub nowszy",
138        description: "Upewnij się, że masz zainstalowany Node.js"
139      },
140      {
141        title: "Utwórz nowy projekt",
142        command: "npx create-react-app moja-aplikacja",
143        expected: "Projekt zostanie utworzony",
144        description: "Create React App automatycznie skonfiguruje wszystko"
145      },
146      {
147        title: "Przejdź do projektu",
148        command: "cd moja-aplikacja",
149        expected: "Zmiana katalogu",
150        description: "Wejdź do folderu z nowym projektem"
151      },
152      {
153        title: "Uruchom serwer",
154        command: "npm start",
155        expected: "Aplikacja otwiera się na localhost:3000",
156        description: "Uruchom serwer deweloperski z hot reloading"
157      }
158    ],
159    Vite: [
160      {
161        title: "Sprawdź Node.js",
162        command: "node --version",
163        expected: "v20.19.0 lub nowszy",
164        description: "Vite wymaga Node.js 20.19+ albo 22.12+"
165      },
166      {
167        title: "Utwórz projekt z Vite",
168        command: "npm create vite@latest moja-aplikacja -- --template react",
169        expected: "Projekt Vite zostanie utworzony",
170        description: "Vite jest szybszy i bardziej nowoczesny"
171      },
172      {
173        title: "Zainstaluj zależności",
174        command: "cd moja-aplikacja && npm install",
175        expected: "Zależności zainstalowane",
176        description: "Zainstaluj wszystkie potrzebne pakiety"
177      },
178      {
179        title: "Uruchom serwer",
180        command: "npm run dev",
181        expected: "Aplikacja otwiera się na localhost:5173",
182        description: "Vite używa innego portu niż CRA"
183      }
184    ]
185  };
186
187  const currentSteps = steps[selectedTool];
188  const currentStepData = currentSteps[currentStep];
189
190  const nextStep = () => {
191    if (currentStep < currentSteps.length - 1) {
192      setCurrentStep(currentStep + 1);
193    }
194  };
195
196  const prevStep = () => {
197    if (currentStep > 0) {
198      setCurrentStep(currentStep - 1);
199    }
200  };
201
202  const resetSteps = () => {
203    setCurrentStep(0);
204  };
205
206  const changeTool = (tool) => {
207    setSelectedTool(tool);
208    setCurrentStep(0);
209  };
210
211  return (
212    <div style={{
213      backgroundColor: '#f3e5f5',
214      padding: '25px',
215      borderRadius: '12px',
216      margin: '20px 0'
217    }}>
218      <h3 style={{ color: '#7b1fa2', marginBottom: '20px', textAlign: 'center' }}>
219        Interaktywny Przewodnik Konfiguracji
220      </h3>
221
222      <div style={{
223        display: 'flex',
224        justifyContent: 'center',
225        gap: '10px',
226        marginBottom: '25px'
227      }}>
228        <button
229          onClick={() => changeTool('CRA')}
230          style={{
231            padding: '10px 20px',
232            backgroundColor: selectedTool === 'CRA' ? '#9c27b0' : 'white',
233            color: selectedTool === 'CRA' ? 'white' : '#333',
234            border: '2px solid #9c27b0',
235            borderRadius: '8px',
236            cursor: 'pointer',
237            fontWeight: 'bold'
238          }}
239        >
240          Create React App
241        </button>
242
243        <button
244          onClick={() => changeTool('Vite')}
245          style={{
246            padding: '10px 20px',
247            backgroundColor: selectedTool === 'Vite' ? '#9c27b0' : 'white',
248            color: selectedTool === 'Vite' ? 'white' : '#333',
249            border: '2px solid #9c27b0',
250            borderRadius: '8px',
251            cursor: 'pointer',
252            fontWeight: 'bold'
253          }}
254        >
255          Vite
256        </button>
257      </div>
258
259      <div style={{
260        backgroundColor: 'white',
261        padding: '25px',
262        borderRadius: '8px',
263        minHeight: '200px'
264      }}>
265        <div style={{
266          display: 'flex',
267          alignItems: 'center',
268          marginBottom: '20px'
269        }}>
270          <div style={{
271            width: '50px',
272            height: '50px',
273            backgroundColor: '#9c27b0',
274            color: 'white',
275            borderRadius: '50%',
276            display: 'flex',
277            alignItems: 'center',
278            justifyContent: 'center',
279            fontWeight: 'bold',
280            fontSize: '18px',
281            marginRight: '15px'
282          }}>
283            {currentStep + 1}
284          </div>
285          <h4 style={{ margin: 0, color: '#333', fontSize: '1.3rem' }}>
286            {currentStepData.title}
287          </h4>
288        </div>
289
290        <p style={{
291          color: '#666',
292          marginBottom: '20px',
293          fontSize: '16px',
294          lineHeight: '1.5'
295        }}>
296          {currentStepData.description}
297        </p>
298
299        <div style={{
300          backgroundColor: '#1e1e1e',
301          color: '#00ff00',
302          padding: '15px',
303          borderRadius: '6px',
304          fontFamily: 'Monaco, monospace',
305          marginBottom: '15px',
306          fontSize: '14px',
307          overflow: 'auto'
308        }}>
309          <div style={{ marginBottom: '5px', color: '#888' }}>$ {currentStepData.command}</div>
310          <div style={{ color: '#00ff00' }}>{currentStepData.expected}</div>
311        </div>
312
313        <div style={{
314          display: 'flex',
315          justifyContent: 'space-between',
316          alignItems: 'center'
317        }}>
318          <div style={{
319            display: 'flex',
320            gap: '10px'
321          }}>
322            <button
323              onClick={prevStep}
324              disabled={currentStep === 0}
325              style={{
326                padding: '8px 16px',
327                backgroundColor: currentStep === 0 ? '#ccc' : '#666',
328                color: 'white',
329                border: 'none',
330                borderRadius: '4px',
331                cursor: currentStep === 0 ? 'not-allowed' : 'pointer'
332              }}
333            >
334              ← Poprzedni
335            </button>
336
337            <button
338              onClick={nextStep}
339              disabled={currentStep === currentSteps.length - 1}
340              style={{
341                padding: '8px 16px',
342                backgroundColor: currentStep === currentSteps.length - 1 ? '#ccc' : '#9c27b0',
343                color: 'white',
344                border: 'none',
345                borderRadius: '4px',
346                cursor: currentStep === currentSteps.length - 1 ? 'not-allowed' : 'pointer'
347              }}
348            >
349              Następny →
350            </button>
351
352            <button
353              onClick={resetSteps}
354              style={{
355                padding: '8px 16px',
356                backgroundColor: '#f44336',
357                color: 'white',
358                border: 'none',
359                borderRadius: '4px',
360                cursor: 'pointer'
361              }}
362            >
363              Reset
364            </button>
365          </div>
366
367          <div style={{ display: 'flex', gap: '5px', alignItems: 'center' }}>
368            {currentSteps.map((_, index) => (
369              <div
370                key={index}
371                style={{
372                  width: '12px',
373                  height: '12px',
374                  borderRadius: '50%',
375                  backgroundColor: index <= currentStep ? '#9c27b0' : '#ddd',
376                  transition: 'background-color 0.3s'
377                }}
378              />
379            ))}
380            <span style={{ marginLeft: '10px', color: '#666', fontSize: '14px' }}>
381              {currentStep + 1} / {currentSteps.length}
382            </span>
383          </div>
384        </div>
385      </div>
386    </div>
387  );
388}
389
390// Komponent do porównania narzędzi
391function ToolComparison() {
392  const tools = [
393    {
394      name: 'Create React App',
395      speed: 70,
396      ease: 95,
397      flexibility: 40,
398      popularity: 90
399    },
400    {
401      name: 'Vite',
402      speed: 95,
403      ease: 85,
404      flexibility: 80,
405      popularity: 75
406    },
407    {
408      name: 'Next.js',
409      speed: 85,
410      ease: 60,
411      flexibility: 90,
412      popularity: 85
413    },
414    {
415      name: 'Ręczna konfiguracja',
416      speed: 30,
417      ease: 20,
418      flexibility: 100,
419      popularity: 30
420    }
421  ];
422
423  return (
424    <div style={{
425      backgroundColor: '#e3f2fd',
426      padding: '25px',
427      borderRadius: '12px',
428      margin: '20px 0'
429    }}>
430      <h3 style={{ color: '#1976d2', textAlign: 'center', marginBottom: '25px' }}>
431        Porównanie Narzędzi do Konfiguracji React
432      </h3>
433
434      <div style={{
435        display: 'grid',
436        gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
437        gap: '20px'
438      }}>
439        {tools.map((tool, index) => (
440          <div key={index} style={{
441            backgroundColor: 'white',
442            padding: '20px',
443            borderRadius: '8px',
444            boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
445          }}>
446            <h4 style={{ color: '#1976d2', marginBottom: '15px', textAlign: 'center' }}>
447              {tool.name}
448            </h4>
449
450            <div style={{ marginBottom: '12px' }}>
451              <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px' }}>
452                <span style={{ fontSize: '14px' }}>Szybkość</span>
453                <span style={{ fontSize: '14px' }}>{tool.speed}%</span>
454              </div>
455              <div style={{
456                height: '8px',
457                backgroundColor: '#e0e0e0',
458                borderRadius: '4px',
459                overflow: 'hidden'
460              }}>
461                <div style={{
462                  height: '100%',
463                  backgroundColor: '#4caf50',
464                  width: `${tool.speed}%`,
465                  transition: 'width 1s ease'
466                }}></div>
467              </div>
468            </div>
469
470            <div style={{ marginBottom: '12px' }}>
471              <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px' }}>
472                <span style={{ fontSize: '14px' }}>Łatwość</span>
473                <span style={{ fontSize: '14px' }}>{tool.ease}%</span>
474              </div>
475              <div style={{
476                height: '8px',
477                backgroundColor: '#e0e0e0',
478                borderRadius: '4px',
479                overflow: 'hidden'
480              }}>
481                <div style={{
482                  height: '100%',
483                  backgroundColor: '#2196f3',
484                  width: `${tool.ease}%`,
485                  transition: 'width 1s ease'
486                }}></div>
487              </div>
488            </div>
489
490            <div style={{ marginBottom: '12px' }}>
491              <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px' }}>
492                <span style={{ fontSize: '14px' }}>Elastyczność</span>
493                <span style={{ fontSize: '14px' }}>{tool.flexibility}%</span>
494              </div>
495              <div style={{
496                height: '8px',
497                backgroundColor: '#e0e0e0',
498                borderRadius: '4px',
499                overflow: 'hidden'
500              }}>
501                <div style={{
502                  height: '100%',
503                  backgroundColor: '#ff9800',
504                  width: `${tool.flexibility}%`,
505                  transition: 'width 1s ease'
506                }}></div>
507              </div>
508            </div>
509
510            <div style={{ marginBottom: '12px' }}>
511              <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px' }}>
512                <span style={{ fontSize: '14px' }}>Popularność</span>
513                <span style={{ fontSize: '14px' }}>{tool.popularity}%</span>
514              </div>
515              <div style={{
516                height: '8px',
517                backgroundColor: '#e0e0e0',
518                borderRadius: '4px',
519                overflow: 'hidden'
520              }}>
521                <div style={{
522                  height: '100%',
523                  backgroundColor: '#9c27b0',
524                  width: `${tool.popularity}%`,
525                  transition: 'width 1s ease'
526                }}></div>
527              </div>
528            </div>
529          </div>
530        ))}
531      </div>
532    </div>
533  );
534}
535
536export default function App() {
537  return (
538    <div style={{
539      fontFamily: 'Arial, sans-serif',
540      maxWidth: '1000px',
541      margin: '0 auto',
542      padding: '20px'
543    }}>
544      <header style={{
545        textAlign: 'center',
546        marginBottom: '30px',
547        padding: '25px',
548        background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
549        color: 'white',
550        borderRadius: '12px'
551      }}>
552        <h1 style={{ margin: '0 0 10px 0', fontSize: '2.2rem' }}>
553          Konfiguracja Środowiska React
554        </h1>
555        <p style={{ margin: 0, fontSize: '1rem', opacity: 0.9 }}>
556          Wszystko co musisz wiedzieć o przygotowaniu środowiska deweloperskiego dla React
557        </p>
558      </header>
559
560      <section style={{ marginBottom: '30px' }}>
561        <h2 style={{
562          color: '#333',
563          borderBottom: '2px solid #667eea',
564          paddingBottom: '10px',
565          marginBottom: '20px'
566        }}>
567          Dostępne Narzędzia
568        </h2>
569
570        <DevelopmentTool
571          name="Create React App"
572          logo="◆"
573          type="Narzędzie CLI"
574          difficulty="Łatwy"
575          description="Dawne oficjalne narzędzie Reacta, wycofane w lutym 2025 i już nierozwijane. Spotkasz je w starszych tutorialach."
576          pros={[
577            "Zero konfiguracji na start",
578            "Oficjalne wsparcie React",
579            "Hot reloading wbudowany",
580            "Optymalizacja dla produkcji",
581            "Wsparcie dla testów"
582          ]}
583          cons={[
584            "Mniej elastyczności",
585            "Większy bundle size",
586            "Trudne do dostosowania",
587            "Może być nadmiarowy dla prostych projektów"
588          ]}
589        />
590
591        <DevelopmentTool
592          name="Vite"
593          logo="↯"
594          type="Narzędzie budowania"
595          difficulty="Średni"
596          description="Nowoczesne narzędzie budujące z natywnym wsparciem ES modules. Błyskawicznie szybkie."
597          pros={[
598            "Bardzo szybki development server",
599            "Natywne ES modules",
600            "Mniejszy bundle size",
601            "Lepsze hot reloading",
602            "Obsługa TypeScript out-of-the-box"
603          ]}
604          cons={[
605            "Młodsza technologia",
606            "Mniejszy ekosystem pluginów",
607            "Może wymagać dodatkowej konfiguracji",
608            "Mniej gotowych szablonów"
609          ]}
610        />
611
612        <DevelopmentTool
613          name="Next.js"
614          logo="▲"
615          type="Framework"
616          difficulty="Średni"
617          description="Full-stack React framework z renderowaniem po stronie serwera, routingiem i wieloma innymi funkcjami."
618          pros={[
619            "Server-side rendering",
620            "Automatyczny routing",
621            "API routes wbudowane",
622            "Optymalizacja obrazów",
623            "Świetna wydajność"
624          ]}
625          cons={[
626            "Może być nadmiarowy dla prostych SPA",
627            "Steeper learning curve",
628            "Opinionated struktura",
629            "Większa złożoność"
630          ]}
631        />
632
633        <DevelopmentTool
634          name="Ręczna konfiguracja"
635          logo="◆"
636          type="Narzędzie budowania"
637          difficulty="Trudny"
638          description="Ręczna konfiguracja Webpack, Babel i innych narzędzi. Maksymalna kontrola, ale wymaga wiedzy."
639          pros={[
640            "Pełna kontrola nad konfiguracją",
641            "Możliwość dostosowania do specyficznych potrzeb",
642            "Głębsze zrozumienie narzędzi",
643            "Optymalna wydajność"
644          ]}
645          cons={[
646            "Bardzo czasochłonne",
647            "Wymaga zaawansowanej wiedzy",
648            "Skomplikowane w utrzymaniu",
649            "Łatwo popełnić błędy"
650          ]}
651        />
652      </section>
653
654      <SetupProcess />
655      <ToolComparison />
656
657      <div style={{
658        backgroundColor: '#e8f5e8',
659        padding: '25px',
660        borderRadius: '12px',
661        marginTop: '30px'
662      }}>
663        <h3 style={{ color: '#2e7d32', textAlign: 'center', marginBottom: '20px' }}>
664          Które Narzędzie Wybrać?
665        </h3>
666
667        <div style={{
668          display: 'grid',
669          gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
670          gap: '20px'
671        }}>
672          <div style={{
673            backgroundColor: 'white',
674            padding: '20px',
675            borderRadius: '8px',
676            textAlign: 'center'
677          }}>
678            <h4 style={{ color: '#2196f3', marginBottom: '10px' }}>Początkujący</h4>
679            <p style={{ margin: 0, color: '#666' }}>
680              <strong>Vite</strong><br/>
681              Szybki start, polecany w tym kursie
682            </p>
683          </div>
684
685          <div style={{
686            backgroundColor: 'white',
687            padding: '20px',
688            borderRadius: '8px',
689            textAlign: 'center'
690          }}>
691            <h4 style={{ color: '#2196f3', marginBottom: '10px' }}>Wydajność</h4>
692            <p style={{ margin: 0, color: '#666' }}>
693              <strong>Vite</strong><br/>
694              Szybkość developmentu
695            </p>
696          </div>
697
698          <div style={{
699            backgroundColor: 'white',
700            padding: '20px',
701            borderRadius: '8px',
702            textAlign: 'center'
703          }}>
704            <h4 style={{ color: '#2196f3', marginBottom: '10px' }}>Full-Stack</h4>
705            <p style={{ margin: 0, color: '#666' }}>
706              <strong>Next.js</strong><br/>
707              SSR, routing, API
708            </p>
709          </div>
710
711          <div style={{
712            backgroundColor: 'white',
713            padding: '20px',
714            borderRadius: '8px',
715            textAlign: 'center'
716          }}>
717            <h4 style={{ color: '#2196f3', marginBottom: '10px' }}>Eksperci</h4>
718            <p style={{ margin: 0, color: '#666' }}>
719              <strong>Ręczna konfiguracja</strong><br/>
720              Pełna kontrola
721            </p>
722          </div>
723        </div>
724      </div>
725    </div>
726  );
727}

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Po co potrzebny jest Node.js w rozwoju React?

  2. 2. Jak działa jednokierunkowy przepływ danych (one-way data flow) w React?

Przydatne artykuły