Patrząc na komentarze do zaakceptowanej odpowiedzi i ogólny charakter tego pytania („nie pracuj”), pomyślałem, że może to być dobre miejsce na kilka ogólnych wyjaśnień na temat związanych z tym problemów. Tak więc ta odpowiedź ma stanowić dodatkowe informacje / opracowanie dotyczące konkretnego przypadku zastosowania PO. Proszę o wyrozumiałość.
Po stronie serwera a po stronie klienta
Pierwszą ważną rzeczą, którą należy zrozumieć, jest to, że są teraz 2 miejsca, w których adres URL jest interpretowany, podczas gdy kiedyś było tylko 1 w „dawnych czasach”. W przeszłości, gdy życie było proste, niektórzy użytkownicy wysyłali żądania http://example.com/about
do serwera, który sprawdzał część adresu URL ścieżki, ustalał, że użytkownik prosi o stronę z informacjami, a następnie odsyła tę stronę.
Dzięki routingowi po stronie klienta, który zapewnia React-Router, rzeczy są mniej proste. Początkowo klient nie ma jeszcze załadowanego kodu JS. Tak więc pierwsze żądanie zawsze będzie skierowane do serwera. Zwróci to stronę zawierającą potrzebne znaczniki skryptu, aby załadować React i React Router itp. Dopiero po załadowaniu tych skryptów rozpoczyna się faza 2. W fazie 2, gdy użytkownik kliknie na przykład link nawigacyjny „O nas”, adres URL jest zmieniany tylko lokalnie na http://example.com/about
(możliwe dzięki History API ), ale nie jest wysyłane żadne żądanie do serwera. Zamiast tego React Router działa po stronie klienta, określa, który widok React ma być renderowany i renderuje go. Zakładając, że strona o stronie nie musi wykonywać żadnych wywołań REST, jest już zrobiona. Zmieniłeś się z Home do About About bez zwolnienia żądania serwera.
Zasadniczo po kliknięciu łącza niektóre skrypty JavaScript zmieniają adres URL na pasku adresu, nie powodując odświeżania strony , co z kolei powoduje, że React Router wykonuje przejście strony po stronie klienta .
Ale teraz zastanów się, co się stanie, jeśli skopiujesz i wkleisz adres URL w pasku adresu i wyślesz go e-mailem do znajomego. Twój przyjaciel nie załadował jeszcze Twojej witryny. Innymi słowy, wciąż znajduje się w fazie 1 . Na jej komputerze nie działa jeszcze React Router. Więc jej przeglądarka zrobi wysyła żądanie serwera do http://example.com/about
.
I tu zaczynają się twoje problemy. Do tej pory można było uniknąć umieszczania statycznego kodu HTML w katalogu głównym serwera. Ale to dawałoby 404
błędy dla wszystkich innych adresów URL na żądanie z serwera . Te same adresy URL działają dobrze po stronie klienta , ponieważ tam React Router wykonuje routing za Ciebie, ale zawodzą po stronie serwera, chyba że sprawisz, że serwer je zrozumie.
Łączenie routingu po stronie serwera i klienta
Jeśli chcesz http://example.com/about
adres URL działał zarówno po stronie serwera, jak i klienta, musisz skonfigurować trasy dla niego zarówno po stronie serwera, jak i klienta. Czy ma to sens, prawda?
I tu zaczynają się twoje wybory. Rozwiązania obejmują obejście problemu całkowicie, poprzez trasę typu catch-all, która zwraca kod ładujący HTML, aż do pełnego podejścia izomorficznego, w którym zarówno serwer, jak i klient uruchamiają ten sam kod JS.
.
Całkowite obejście problemu: Historia mieszania
W przypadku Historii mieszania zamiast Historii przeglądarki adres URL strony z informacjami mógłby wyglądać mniej więcej tak:
http://example.com/#/about
Część po #
symbolu skrótu ( ) nie jest wysyłana na serwer. Tak więc serwer widzi http://example.com/
i wysyła stronę indeksu zgodnie z oczekiwaniami. React-Router odbierze #/about
część i wyświetli prawidłową stronę.
Wady :
- „brzydkie” adresy URL
- Przy takim podejściu renderowanie po stronie serwera nie jest możliwe. Jeśli chodzi o Search Engine Optimization (SEO), twoja strona składa się z jednej strony, na której nie ma prawie żadnych treści.
.
Złap wszystkie
Dzięki takiemu podejściu używasz historii przeglądarki, ale wystarczy założyć catch-all na serwerze, który wysyła /*
do index.html
, skutecznie daje dużo takiej samej sytuacji jak z Hash Historii. Masz jednak czyste adresy URL i możesz ulepszyć ten schemat później, bez konieczności unieważniania wszystkich ulubionych użytkowników.
Wady :
- Bardziej skomplikowany w konfiguracji
- Nadal nie ma dobrego SEO
.
Hybrydowy
W podejściu hybrydowym rozwijasz scenariusz catch-all, dodając określone skrypty dla określonych tras. Możesz wykonać kilka prostych skryptów PHP, aby zwrócić najważniejsze strony witryny z zawartością, aby Googlebot mógł przynajmniej zobaczyć, co jest na twojej stronie.
Wady :
- Jeszcze bardziej skomplikowany w konfiguracji
- Tylko dobre SEO dla tych tras, które dajesz specjalnemu traktowaniu
- Duplikowanie kodu do renderowania treści na serwerze i kliencie
.
Izomorficzny
Co jeśli użyjemy Node JS jako naszego serwera, abyśmy mogli uruchomić ten sam kod JS na obu końcach? Teraz wszystkie nasze trasy są zdefiniowane w jednej konfiguracji routera reagującego i nie musimy powielać naszego kodu renderowania. To jest „święty Graal”, że tak powiem. Serwer wysyła dokładnie takie same znaczniki, jak w przypadku, gdyby nastąpiło przeniesienie strony na kliencie. To rozwiązanie jest optymalne pod względem SEO.
Wady :
- Serwer musi (być w stanie) uruchomić JS. Eksperymentowałem z Java icw Nashorn, ale to nie działa dla mnie. W praktyce oznacza to głównie, że musisz użyć serwera opartego na Node JS.
- Wiele trudnych problemów środowiskowych (używanie
window
po stronie serwera itp.)
- Stroma krzywa uczenia się
.
Z którego powinienem korzystać?
Wybierz ten, z którego możesz uciec. Osobiście uważam, że catch-all jest wystarczająco prosty do skonfigurowania, więc byłoby to moje minimum. Ta konfiguracja pozwala poprawić rzeczy w miarę upływu czasu. Jeśli używasz już Node JS jako platformy serwerowej, zdecydowanie zbadałbym aplikację izomorficzną. Tak, na początku jest ciężko, ale kiedy już to zrozumiesz, jest to bardzo eleganckie rozwiązanie problemu.
Zasadniczo dla mnie byłby to decydujący czynnik. Gdyby mój serwer działał na Node JS, wybrałbym izomorficzny; inaczej wybrałbym rozwiązanie Catch-all i rozwinąłem je (rozwiązanie hybrydowe) w miarę upływu czasu i wymagań SEO.
Jeśli chcesz dowiedzieć się więcej na temat renderowania izomorficznego (zwanego również „uniwersalnym”) za pomocą React, znajdziesz kilka dobrych samouczków na ten temat:
Na początek warto też zapoznać się z niektórymi zestawami startowymi. Wybierz taki, który pasuje do twojego wyboru stosu technologii (pamiętaj, React to tylko V w MVC, potrzebujesz więcej rzeczy, aby zbudować pełną aplikację). Zacznij od obejrzenia tego opublikowanego przez Facebooka:
Lub wybierz jeden z wielu przez społeczność. Jest teraz fajna strona, która próbuje zaindeksować wszystkie:
Zacząłem od tych:
Obecnie używam domowej wersji uniwersalnego renderingu, która została zainspirowana dwoma powyższymi zestawami startowymi, ale są już nieaktualne.
Powodzenia w twojej misji!