Localhost to nie środowisko produkcyjne: diagnozowanie aplikacji React, które przestają działać podczas wdrożenia
Dowiedz się, dlaczego aplikacja React, która działa poprawnie na twoim komputerze, zawodzi po wdrożeniu, oraz jak prześledzić URL-y API, zmienne środowiskowe, CORS, routowanie, zasoby i mechanizmy autoryzacji aż do warstwy powodującej błąd.
Źródła: Why Your React App Works Locally but Breaks After Deployment: 10 Common Problems and How to Fix Them
Aplikacja React, która działa perfekcyjnie na localhost, a potem przestaje funkcjonować zaraz po wdrożeniu, to jeden z najczęściej spotykanych problemów w pracy nad interfejsami użytkownika. Zapytania przestają zwracać dane, odświeżanie strony skutkuje błędem 404, obrazy znikają, logowanie bezgłośnie się nie udaje, albo platforma hostingowa odmawia zbudowania kodu, który kompilował się bez problemów na twoim laptopie. Prawie żaden z tych problemów nie wynika bezpośrednio z samego Reacta. Pochodzą one z różnic pomiędzy środowiskiem, w którym rozwijasz aplikację, a tym, z którego korzystają twoi użytkownicy. Ten przewodnik omawia dziesięć najczęstszych przyczyn tych problemów, pokazuje, w jaki sposób się one objawiają, oraz kończy się metodą debugowania i listą kontrolną przed wdrożeniem, której możesz używać przy każdym wydaniu aplikacji.
Dlaczego ten sam kod zachowuje się inaczej w środowisku produkcyjnym
Frontend w React rzadko stanowi całe aplikację. Komunikuje się z API, a API komunikuje się z bazą danych; każdy element tego łańcucha zależy od konfiguracji: zmiennych środowiskowych, nazw domen, reguł sieciowych, ustawień autoryzacji oraz tego, co platforma hostingowa robi z przychodzącymi żądaniami. Na swoim komputerze kontrolujesz to wszystko w sposób domyślny – wiesz, na którym porcie słucha backend, który plik .env jest ładowany oraz jakie pakiety znajdują się w katalogu node_modules. W środowisku produkcyjnym każde z tych założeń jest zastępowane czymś wyraźnym, a jakakolwiek niezgodność może sprawić, że poprawny kod będzie wyglądał na uszkodzony.
Miej to na uwadze podczas czytania poniższych sekcji – większość napraw polega na zmianach konfiguracji, a nie kodu.
1. Adres URL API nadal wskazuje na localhost
Gdy wdrożona aplikacja nie pokazuje żadnych danych, pierwszą rzeczą, którą warto sprawdzić, jest to, dokąd trafiają jej żądania. Podczas rozwoju naturalne jest uruchamianie backendu lokalnie i umieszczanie jego adresu w kodzie frontendu:
const API_URL = "http://localhost:8080/api";
To działa, ponieważ przeglądarka i backend działają na tym samym komputerze. Gdy frontend zostanie wdrożony na adresie takim jak https://my-app.example.com, ta sama linia kodu nadal wysyła żądania do http://localhost:8080/api. Problem polega na tym, że localhost jest rozwiązywany przez przeglądarkę, która uruchamia kod. Dla odwiedzającego oznacza to jego własny komputer, a nie twoją maszynę do rozwoju. Ścieżka żądania faktycznie staje się:
User's Browser
↓
localhost:8080
↓
User's computer
Chyba że ten odwiedzający akurat ma swój backend uruchomiony na porcie 8080, każde żądanie zawodzi.
Rozwiązaniem jest zaprzestanie ręcznego wpisywania adresu i odczytywanie go z zmiennej środowiskowej. W projekcie Vite wartość tę deklaruje się w pliku env:
VITE_API_URL=https://your-backend.example.com/api
a odczytuje się ją w kodzie za pomocą import.meta.env:
const API_URL = import.meta.env.VITE_API_URL;
Teraz wersja rozwojowa może odwoływać się do http://localhost:8080/api, podczas gdy wersja produkcyjna – do czegoś w rodzaju https://api.example.com/api, przy czym nie ma konieczności zmiany kodu w żadnej z wersji. To niewielka refaktoryzacja, ale eliminuje jeden z najczęstszych błędów podczas wdrażania: próbę skierowania przeglądarki kogoś obcego do komputera osobistego.
Inną skuteczną metodą ochrony jest głośne wykrywanie braku zmiennej. Jeśli API_URL ma wartość undefined, żądania trafiają do adresów takich jak undefined/users, co utrudnia diagnozę problemu. Jednolinijowa weryfikacja podczas uruchamiania, która loguje błąd lub rzuca wyjątek w przypadku braku wartości, oszczędza czas później.
2. Zmienne środowiskowe w środowisku produkcyjnym nigdy nie zostały skonfigurowane
Zmienne środowiskowe są kolejnym typowym źródłem problemów. Lokalnie prawdopodobnie masz plik .env, który zawiera wszystko, czego potrzebuje aplikacja:
VITE_API_URL=http://localhost:8080/api
VITE_APP_NAME=MyApp
Te wartości istnieją tylko na twoim komputerze. Platforma hostingowa nie czyta twojego lokalnego pliku .env (i tak nie powinna, ponieważ taki plik zazwyczaj jest wykluczany z kontroli wersji). Twoja wersja aplikacji dla środowiska produkcyjnego musi otrzymywać własne wartości, skonfigurowane w ustawieniach zmiennych środowiskowych dostawcy:
VITE_API_URL=https://your-backend.example.com/api
Po dodaniu lub zmianie wartości tam musisz uruchomić nową implementację. W przypadku Vite ten krok nie jest opcjonalny: tylko zmienne poprzedzone przedrostkiem VITE_ są dostępne dla kodu klienta, a Vite podstawia je do pliku bundle w momencie budowania. Zmiana zmiennej w panelu sterowania nie ma żadnego wpływu na plik bundle, który został już zbudowany przy użyciu starej wartości.
Zmienne frontendu nie są tajemnicami
Kryje się w tym lekcja z zakresu bezpieczeństwa. Umieszczenie wartości w pliku .env nie czyni jej poufną. Wszystko, co jest dostępne dla klienta, jest kompilowane do JavaScriptu, który każdy odwiedzający może pobrać i odczytać. Hasła do bazy danych, prywatne klucze API oraz inne dane uwierzytelniające po stronie serwera nigdy nie powinny znajdować się w zmiennych VITE_*. Przechowuj je po stronie backendu lub za funkcją serwerową i pozwól frontendowi wywoływać endpoint, który będzie je używał w jego imieniu.
3. Zasady CORS pozwalają jedynie na twoją domenę rozwojową
Błędy związane z wymianą zasobów między różnymi domenami to kolejne klasyczne niespodzianki po wdrożeniu. Wyobraź sobie frontend serwowany z:
https://myapp.example.com
a backend serwowany z:
https://api.example.com
Są to różne domeny, ponieważ domena składa się z schematu, hosta i portu. Przeglądarki stosują zasadę tej samej domeny, więc aby frontend mógł odczytywać odpowiedzi z API, backend musi odpowiadać nagłówkami CORS, które wyraźnie zezwalają na domenę frontendu.
W trakcie rozwoju backend był prawdopodobnie skonfigurowany tak, aby przyjmować żądania od serwera rozwojowego Vite:
http://localhost:5173
Wszystko działało, więc łatwo jest założyć, że kwestia CORS została rozwiązana. Jednak po wdrożeniu domena frontendu jest:
https://myapp.example.com
Dla przeglądarki jest to zupełnie nowy źródło. Jeśli backend nadal wymienia jedynie http://localhost:5173, wdrożony frontend zostaje zablokowany. W przypadku backendu Spring Boot umożliwienie dostępu z produkcji w kontrolerze może wyglądać w ten sposób (fragment jest napisany w Javie):
@CrossOrigin(origins = "https://myapp.example.com")
@RestController
public class UserController {
// ...
}
Adnotowanie każdego kontrolera sprawdza się w małych usługach, ale w większym kodzie jedna centralna konfiguracja CORS jest łatwiejsza do utrzymania i trudniejsza do zapomnienia podczas dodawania punktów końcowych. Niezależnie od stosu technologicznego zasada jest taka sama: dozwolone źródła muszą dokładnie odpowiadać rzeczywistemu źródłu frontendu z produkcji, włączając https oraz wszelkie poddomeny. Powszechnym i skutecznym rozwiązaniem jest odczytywanie listy dozwolonych źródeł z własnej konfiguracji środowiskowej backendu, dzięki czemu środowisko rozwojowe, testowe i produkcyjne każde umożliwia dostęp odpowiedniemu frontendowi.
Należy pamiętać, że CORS to mechanizm przeglądarki. Zapytanie, które zawodzi z błędem CORS w przeglądarce, może odnieść sukces przy użyciu curl lub Postman, dlatego testowanie API poza przeglądarką może dać myląco pozytywny wynik.
4. Odświeżanie trasy po stronie klienta zwraca 404
To problem, który często zmusza programistów do analizy kodu routera, mimo że router działa poprawnie. Załóżmy, że aplikacja ma taką trasę:
/dashboard
Trafia się na stronę główną, kliknie w link do panelu sterowania i ten wyświetla się idealnie. Można swobodnie przemieszczać się po stronie bez żadnych problemów. Następnie odświeża się stronę, a serwer odpowiada:
404 Not Found
Wyjaśnienie leży w sposobie działania aplikacji jednostronicowych. Gdy klikasz w link, React Router aktualizuje adres URL i renderuje odpowiadającą komponentę w pełni w przeglądarce; żadne żądanie do /dashboard nie trafia do serwera. Gdy odświeżasz stronę lub otwierasz ten adres bezpośrednio, przeglądarka żąda pliku /dashboard od serwera hostującego. Jeśli serwer zna tylko rzeczywiste pliki, szuka zasobu o takiej ścieżce, nic nie znajduje i zwraca błąd 404.
Rozwiązaniem jest reguła awaryjna w serwerze: każde żądanie do trasy frontendowej, która nie odpowiada rzeczywistemu plikowi, powinno zostać przepisane lub przekierowane do index.html. Następnie przeglądarka ładuje aplikację, a React Router odczytuje adres URL i wyświetla odpowiedni ekran. Dokumentacja dotycząca wdrażania React Routera opisuje to wymaganie, a większość serwerów statycznych oferuje odpowiednią ustawienie lub mały plik konfiguracyjny do tego celu. Dlatego, gdy klikanie działa, ale odświeżanie nie, nie ingeruj w swoje trasy i najpierw sprawdź konfigurację przepisywania SPA w serwerze. Jeśli chcesz ponownie zapoznać się z tym, jak deklarowane są trasy, przejdź do podstaw React Routera.
5. Ścieżki importu z niewłaściwą wielkością liter
Część błędów pozostaje niewidoczna, dopóki proces budowania nie zostanie przeprowadzony na innym systemie operacyjnym. Wyobraź sobie plik komponentu o nazwie:
Header.jsx
Importowane w ten sposób:
import Header from "./components/header";
Jedyną różnicą jest jedna wielka litera, którą łatwo przeoczyć podczas przeglądania kodu. Systemy plikowe nie są zgodne co do tego, czy ma to znaczenie. Domyślne ustawienia w macOS i Windows są niewrażliwe na wielkość liter, więc import się udaje i aplikacja działa. Większość serwerów budowania i kontenerów uruchamia Linux, którego systemy plikowe są wrażliwe na wielkość liter, więc Header.jsx i header.jsx to dwa odrębne nazwy, co powoduje niepowodzenie budowania z błędem braku modułu.
Rozwiązaniem jest proste dopasowanie każdego importu do pliku na dysku, litera po literze. Biorąc pod uwagę:
components/Header.jsx
Napisz import w następujący sposób:
import Header from "./components/Header";
Należy z taką samą starannością podchodzić do nazw katalogów. Jeszcze jedna pułapka, o której warto wiedzieć: zmiana nazwy pliku tylko ze względu na różnicę w wielkości liter może nie zostać zauważona przez Git na systemie plików niewrażliwym na wielkość liter, więc repozytorium może nadal używać starej nazwy, mimo że edytor pokazuje nową. Sprawdzenie nazwy faktycznie śledzonej przez Git szybko rozwiązuje tę zagadkę.
6. Obrazy i statyczne zasoby znikają
Czasami sama aplikacja się ładuje, ale jej obrazy, czcionki lub ikony nie. Zazwyczaj oznacza to, że zasoby są odwoływane za pomocą ścieżek, które działały na serwerze rozwojowym, ale nie istnieją w wersji produkcyjnej.
Vite oferuje dwa różne mechanizmy, a warto wiedzieć, który z nich używasz. Pierwszym jest importowanie zasobu z kodu źródłowego:
import logo from "./assets/logo.png";
i użycie zaimportowanej wartości jako źródła obrazu:
function App() {
return <img src={logo} alt="Logo" />;
}
Ponieważ plik przechodzi przez graf modułów, Vite przetwarza go podczas budowania, kopiuje do plików wyjściowych z generowaną nazwą pliku i dostarcza właściwą adresację URL. Nigdy nie musisz zgadywać końcowej ścieżki.
Drugim mechanizmem jest katalog public, przeznaczony dla plików, które powinny być serwowane bez żadnego przetwarzania:
public/
└── logo.png
Pliki z tego katalogu są kopiowane do korzenia plików wyjściowych, więc odwołujesz się do nich za pomocą bezwzględnej ścieżki URL:
<img src="/logo.png" alt="Logo" />
Zasadą jest różnica pomiędzy ścieżką na dysku a adresem URL, który przeglądarka może pobrać. Twój edytor może dokładnie wiedzieć, gdzie znajduje się plik src/assets/logo.png, ale przeglądarka rozumie tylko te adresy URL, które faktycznie serwuje uruchomiony serwer. Jeśli aplikacja jest hostowana pod podścieżką zamiast w korzeniu domeny, ścieżki bezwzględne takie jak /logo.png również mogą przestać działać, i właśnie do tego ma służyć opcja base w Vite.
Gdy jakiś plik zasobu znika, otwórz kartę Network w przeglądarce i sprawdź nieudaną prośbę. Zazwyczaj zobaczysz albo ścieżkę, która nie istnieje w wygenerowanej wersji aplikacji, albo błąd 404 od serwera – to pokaże ci, który z tych mechanizmów wymaga korekty.
7. Serwer rozwojowy to nie wersja produkcyjna
Aby uruchomić aplikację, należy:
npm run dev
uruchamia serwer rozwojowy z możliwością dynamicznego wymiany modułów, szczegółowymi ostrzeżeniami oraz transformacją modułów na żądanie. To, co jest wdrażane, to coś innego: spakowany, zoptymalizowany zestaw plików statycznych. W przypadku projektu Vite tworzy się go za pomocą:
npm run build
a serwer hostujący dostarcza uzyskany wynik. Ponieważ te dwa ścieżki przetwarzają kod w inny sposób, zupełnie możliwe jest, że aplikacja będzie działać pod:
npm run dev
a jednak zawiedzie pod:
npm run build
Taka awaria to dobra wiadomość, jeśli sam ją wykryjesz, ponieważ możesz ją naprawić, zanim cokolwiek dotrze do użytkowników. Vite umożliwia również lokalne serwowanie gotowego wyniku za pomocą:
npm run preview
To jest o wiele bliższe temu, co otrzymają odwiedzający, niż serwer deweloperski. Uczyń z budowania i przeglądania projektu lokalnie nawyk przed każdym wdrożeniem, zamiast pozwalać platformie hostingowej być pierwszym miejscem, gdzie uruchamiana jest wersja produkcyjna. Połączenie polecenia npm run build z procesem CI zapewnia ci tę samą gwarancję automatycznie przy każdym pull requestu.
8. Twoje lokalne node_modules ukrywają brakujące zależności
Direktoria node_modules, która istnieje przez długi czas, może sprawić wrażenie, że projekt jest lepiej zarządzany, niż w rzeczywistości. W trakcie tygodni pracy nad projektem gromadzą się tam różne pakiety: te, które zainstalowałeś raz w celu przetestowania, zależności pośrednie innych pakietów oraz pozostałości z porzuconych gałęzi. Twój kod może je importować i działać właśnie dlatego, że akurat się tam znajdują.
Środowisko wdrażania zaczyna się od czystej bazy. Instaluje dokładnie to, co opisują plik package.json oraz plik lockfile, nic więcej. Dlatego jeśli twój kod zawiera:
import axios from "axios";
wtedy Axios musi zostać zadeklarowany jako rzeczywista zależność projektu, na przykład:
{
"dependencies": {
"axios": "^1.0.0",
"react": "^19.0.0",
"react-router-dom": "^7.0.0"
}
}
Liczby wersji w tym fragmencie służą jedynie do ilustracji; użyj tych, których faktycznie potrzebuje twój projekt. Celem jest to, aby po nowym sklonowaniu i instalacji w projekcie znajdowało się wszystko niezbędne do zbudowania i uruchomienia aplikacji. Zapisz zarówno plik package.json, jak i plik lockfile oraz utrzymuj między nimi synchronizację, aby przy każdej instalacji używano tych samych wersji.
Aby odtworzyć lokalnie warunki rozruchu aplikacji, usuń katalog node_modules i zainstaluj go ponownie, najlepiej za pomocą npm ci, który instaluje elementy ściśle na podstawie pliku lockfile i zwraca błąd, jeśli ten plik oraz package.json są sprzeczne. Jeśli po tym procesie budowy pojawią się problemy, odkryłeś nieodeklarowaną zależność przed samym serwerem.
9. Frontend działa poprawnie, a backend zawodzi
Jest kuszące obwiniać React za każdy błąd wyglądu ekranu, ale przyczyna często leży gdzieś dalej w łańcuchu zdarzeń. Załóżmy, że rozrzucony frontend ładuje się pomyślnie pod adresem:
https://myapp.example.com
Otwierasz panel sterowania i okazuje się on pusty. W karcie Network znajdujesz:
GET https://api.example.com/api/dashboard
500 Internal Server Error
To zdanie mówi wiele. Aplikacja React wykonała swoją funkcję i wysłała żądanie; serwer backendowy je otrzymał, ale później napotkał błąd podczas jego przetwarzania. Do możliwych przyczyn należą uszkodzony połączenie z bazą danych, brak zmiennej środowiskowej po stronie serwera, problem z autoryzacją, nieobsłużona wyjątek lub konfiguracja różniąca się od tej używanej lokalnie.
Typowe żądanie typu full-stack przechodzi przez te warstwy:
React Frontend
↓
REST API
↓
Backend
↓
Database
Błąd na dole odbija się na górze. Jeśli do bazy danych nie można uzyskać dostępu, panel sterowania wygląda na uszkodzony, mimo że każdy wiersz kodu frontendowego jest poprawny. Dlatego diagnoza nie powinna kończyć się na przeglądarce. Gdy wywołanie API zawodzi, sprawdź zakładkę Network, a następnie logi serwera backendowego. Jeśli przeglądarka zgłasza błąd 500, a logi serwera mówią:
Database connection failed
Masz do czynienia z problemem backendu lub infrastruktury, a nie błędem renderowania. Frontend, który pokazuje wyraźny stan błędu dla nieudanych żądań zamiast pustej strony, ułatwia rozróżnienie tym zarówno użytkownikom, jak i programistom.
10. Autoryzacja działa lokalnie, ale zawodzi po wdrożeniu
Procesy logowania są szczególnie wrażliwe na różnice środowiskowe. Lokalnie sekwencja może wyglądać następująco:
localhost → Login → Dashboard
W środowisku produkcyjnym wygląda to tak:
Production → Login → Dashboard doesn't load
Kilka wcześniejszych problemów może samo w sobie spowodować tę sytuację. Frontend nadal może wywoływać niewłaściwą adres URL API, zasady CORS backendu mogą nie obejmować domeny produkcyjnej, lub tokeny mogą nie być poprawnie skonfigurowane dla nowego środowiska. Najczęstszym winowajcą są jednak pliki cookie.
Dlaczego pliki cookie zachowują się inaczej w środowisku produkcyjnym
Czy przeglądarka przechowuje i wysyła plik cookie zależy od jego atrybutów: Secure, HttpOnly, SameSite, Domain oraz Path. W środowisku lokalnym wszystko często korzysta z tego samego hosta, więc te atrybuty rzadko mają znaczenie. W środowisku produkcyjnym frontend i API mogą znajdować się na różnych domenach, przez HTTPS, i wtedy przeglądarka zaczyna egzekwować te zasady. Na przykład plik cookie oznaczony jako SameSite=None jest akceptowany tylko wtedy, gdy jest również oznaczony jako Secure.
Zapytania międzydomenowe, które przekazują dane uwierzytelniające, wymagają również współpracy obu stron. Klient musi wyraźnie zgodzić się na wysyłanie tych danych, a serwer musi jasno zezwolić na ich użycie dla danej domeny; domena typu wildcard nie jest akceptowana w takich zapytaniach. Jeśli jedna ze stron nie wypełni swojej roli, próba logowania może wydawać się udana, podczas gdy plik cookie sesji nigdy nie zostanie wysłany przy kolejnych wywołaniach.
Wniosek: proces logowania, który działa na localhost, został przetestowany tylko w najprostszym możliwym środowisku. Należy go ponownie przetestować w warunkach zbliżonych do produkcji, z użyciem HTTPS, domen, ustawień cookie oraz reguł CORS.
Metoda debugowania warstwa po warstwie
Gdy wystąpi problem podczas wdrażania, najmniej skutecznym rozwiązaniem jest edytowanie losowych elementów i liczenie na najlepsze. Skutecznym podejściem jest ustalenie, która warstwa nie działa poprawnie, zanim zaczniemy edytować jakikolwiek kod.
Zacznij od konsoli
Otwórz narzędzia deweloperskie przeglądarki (zwykle F12) i sprawdź konsolę. Komunikaty takie jak Failed to fetch, naruszenia zasad CORS, nieprzechwycone wyjątki JavaScript oraz błędy 404 dotyczące skryptów lub zasobów wskazują na różne przyczyny problemu.
Przeczytaj zakładkę Network
Przejdź do zakładki Network i ponownie załadowaj stronę. Dla każdej żądania możesz zobaczyć dokładny adres URL, metodę HTTP, kod stanu, treść odpowiedzi oraz często nagłówki. W przypadku problemów z API jest to najbardziej informacyjny widok. Możesz zobaczyć:
GET /api/users
Status: 404
lub:
GET /api/users
Status: 401
lub:
GET /api/users
Status: 500
Każdy kod stanu zawęża zakres poszukiwań:
404: żądany zasób lub ścieżka nie istnieje pod tym adresem URL.401: wymagana jest autoryzacja, lub wysłane dane uwierzytelniające są niekompletne lub nieważne.
403: serwer zrozumiał, kim jesteś, ale odmawia autoryzacji tej czynności.500: serwer napotkał błąd wewnętrzny podczas przetwarzania żądania.Nie ufaj temu, co sądzisz, że robi kod źródłowy; sprawdź żądanie, które rzeczywiście wysłała przeglądarka. Jeśli w produkcji wywoływane jest:
http://localhost:8080/api/users
podczas gdy backend faktycznie znajduje się pod adresem:
https://api.example.com/api/users
prawie na pewno znalazłeś problem – jest to kwestia URL API z sekcji 1.
500 oznacza, że odpowiedź znajduje się na serwerze. Łogi backendu mogą ujawnić nieudane połączenie z bazą danych, brakującą zmienną lub wyjątek, którego frontend nie jest w stanie zgłosić. To właśnie nawyk przechodzenia do kolejnego poziomu, gdy dowody na to wskazują, sprawia, że debugowanie wdrożeń przebiega szybko.
Analiza rzeczywistego błędu
Rozważmy aplikację typu full-stack, która wdraża się bez błędów, a mimo to panel sterowania wyświetla się pusty. Instynktowną reakcją jest założenie, że w komponencie panelu sterowania znajduje się błąd:
"Coś musi być nie tak z komponentem panelu sterowania."
Zamiast otwierać ten komponent, otwórz kartę Network. Tam znajdziesz:
GET https://api.example.com/api/dashboard
Status: 500
To już wyklucza frontend jako przyczynę podstawową: żądanie zostało wysłane. Następnie Łogi backendu pokazują:
Database connection failed
Dzięki obu tym dowodom cały łańcuch staje się jasny:
React Frontend
↓
API request
↓
Backend
↓
Database connection failed
↓
500 response
Komponent panelu sterowania nigdy nie był przyczyną problemów. Dziesięć minut spędzonych na analizie narzędzi przeglądarki oraz logów serwera zastąpiło godziny pracy nad refaktoryzacją kodu. Umiejętność jednoczesnej analizy błędów przeglądarki, ruchu sieciowego i logów serwera to jedna z najcenniejszych umiejętności w codziennej pracy nad oprogramowaniem.
Listwa kontrolna przed wdrożeniem
Najskuteczniejszym sposobem na uniknięcie niespodzianek podczas wdrażania jest prześledzenie, przed wysłaniem aplikacji, każdego kroku, jaki żądanie przebywa od przeglądarki do bazy danych. Oto praktyczna lista kontrolna:
- Zainstaluj i uruchom lokalnie
npm run build, upewniając się, że operacja zakończyła się pomyślnie, a następnie sprawdź to za pomocąnpm run preview. - Upewnij się, że ustawiona jest poprawna URL API produkcyjnego i że żadne żądanie nie adresuje się do
localhost.
Żaden lista kontrolna nie gwarantuje bezbłędnego wdrożenia, ale ta pomaga wykryć większość powszechnych problemów, gdy ich naprawa jest jeszcze tania. Aby uzyskać szerszy obraz tego, co solidne ustawienie projektu powinno obejmować od samego początku, produkcyjna baza Reacta omawia aspekty związane z narzędziami.
Dlaczego stwierdzenie „działa lokalnie” mówi tak niewiele
Twój komputer stanowi kontrolowane, wyrozumiałe środowisko. Wiesz, gdzie działa backend, jakie zmienne są zdefiniowane, co jest zainstalowane w node_modules oraz jaką bazę danych używa aplikacja. Środowisko produkcyjne zmienia niemal wszystko: inny domen, inna adresa API, inne zmienne środowiskowe, inna baza danych, surowsze zasady CORS i plików cookie, serwer, któremu trzeba podać instrukcje dotyczące obsługi tras po stronie klienta, a często także inny system operacyjny. Kod może być w pełni poprawny, podczas gdy konfiguracja wokół niego jest błędna.
Dlatego właśnie implementację należy traktować jako kolejne środowisko, w którym przeprowadza się testy, a nie jako ostatni krok po zakończeniu rozwoju. Środowiska testowe, budowanie w ramach CI oraz wersje prezentacyjne istnieją po to, by przenieść te testy na wcześniejszy etap.
Główne wnioski
- Gdy coś się zepsuje po wdrożeniu, najpierw sprawdź, który warstwa nie działa, zanim zaczniesz pytać o problemy z Reactem.
- Jeśli nic się nie ładuje, sprawdź wyniki kompilacji oraz pliki; jeśli strona się ładuje, ale dane nie, sprawdź zakładkę Network oraz adres URL API.
- Błąd
500kieruje na logi backendu; błąd CORS pokazuje dozwolone źródła dla backendu. - Trasa, która działa po kliknięciu, ale wyświetla błąd 404 przy odświeżeniu, wymaga rozwiązania typu SPA na serwerze, a nie zmian w routerze.
- Brakujące wartości zazwyczaj oznaczają, że zmienne środowiskowe w produkcji nigdy nie zostały ustawione lub aplikacja nie została ponownie skompilowana po ich ustawieniu.
- Błędy autoryzacji często wiążą się z adresami URL API, problemami CORS oraz atrybutami plików cookie, więc sprawdź wszystkie trzy elementy.
Potknięcia z tymi problemami nie są oznaką słabych umiejętności programistycznych; to właśnie w ten sposób wszyscy uczą się, z czego składają się rzeczywiste systemy. Celem nie jest unikanie błędów, lecz szybkie znajdowanie ich źródła.