Używam routera React i działa dobrze, kiedy klikam przyciski łącza, ale po odświeżeniu strony nie ładuje się, co chcę.
Na przykład jestem w localhost/joblist
środku i wszystko jest w porządku, ponieważ przybyłem tutaj, naciskając link. Ale jeśli odświeżę stronę, otrzymam:
Cannot GET /joblist
Domyślnie tak nie działało. Początkowo miałem URL jak localhost/#/
i localhost/#/joblist
i pracowali perfekcyjnie. Ale nie podoba mi się ten rodzaj adresu URL, więc próbując go usunąć #
, napisałem:
Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(<Handler/>, document.body);
});
Ten problem nie występuje localhost/
, ten zawsze zwraca to, czego chcę.
EDYCJA: Ta aplikacja jest jednostronicowa, więc /joblist
nie trzeba nic pytać na żadnym serwerze.
EDYCJA 2: Cały mój router.
var routes = (
<Route name="app" path="/" handler={App}>
<Route name="joblist" path="/joblist" handler={JobList}/>
<DefaultRoute handler={Dashboard}/>
<NotFoundRoute handler={NotFound}/>
</Route>
);
Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(<Handler/>, document.body);
});
javascript
reactjs
url
react-router
DavidDev
źródło
źródło
#
symbol? Dziękuję Ci!index.html
. Zapewniindex.html
to trafienie bez względu na wszystko.Odpowiedzi:
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 widzihttp://example.com/
i wysyła stronę indeksu zgodnie z oczekiwaniami. React-Router odbierze#/about
część i wyświetli prawidłową stronę.Wady :
.
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
/*
doindex.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 :
.
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 :
.
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 :
window
po stronie serwera itp.).
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!
źródło
/*
i sprawiasz, że odpowiada ona za pomocą strony HTML. Trudność polega na tym, aby nie przechwytywać żądań plików .js i .css tą trasą.createMemoryHistory is not a function
błąd. Masz coś przeciwko? stackoverflow.com/questions/45002573/...Wszystkie odpowiedzi tutaj są niezwykle pomocne, dla mnie działało skonfigurowanie mojego serwera Webpack tak, aby oczekiwał tras.
HistoryApiFallback naprawił dla mnie ten problem. Teraz routing działa poprawnie i mogę odświeżyć stronę lub wpisać adres URL bezpośrednio. Nie musisz się martwić o obejście na serwerze węzła. Ta odpowiedź oczywiście działa tylko w przypadku korzystania z pakietu WWW.
EDYCJA: zobacz moją odpowiedź tutaj, aby uzyskać bardziej szczegółowy powód, dla którego jest to konieczne: https://stackoverflow.com/a/37622953/5217568
źródło
historyApiFallback
jest wystarczający. Podobnie jak w przypadku wszystkich innych opcji, można go również ustawić z poziomu interfejsu CLI za pomocą flagi--history-api-fallback
.Możesz zmienić
.htaccess
plik i wstawić to:Używam
react: "^16.12.0"
ireact-router: "^5.1.2"
ta metoda jest Catch-all i jest prawdopodobnie najłatwiejszym sposobem na rozpoczęcie pracy.źródło
Dla użytkowników React Router V4 :
Jeśli próbujesz rozwiązać ten problem za pomocą techniki Hash History wspomnianej w innych odpowiedziach, zwróć uwagę na to
nie działa w V4,
HashRouter
zamiast tego użyj :Odniesienie: HashRouter
źródło
Router można wywołać na dwa różne sposoby, w zależności od tego, czy nawigacja odbywa się na kliencie, czy na serwerze. Masz skonfigurowane do działania po stronie klienta. Kluczowym parametrem jest drugi do metody uruchomienia , lokalizacja.
Gdy używasz komponentu React Router Link, blokuje on nawigację w przeglądarce i wywołuje przejście, aby wykonać nawigację po stronie klienta. Korzystasz z HistoryLocation, więc używa interfejsu API historii HTML5, aby uzupełnić iluzję nawigacji, symulując nowy adres URL na pasku adresu. Jeśli używasz starszych przeglądarek, to nie zadziała. Musisz użyć komponentu HashLocation.
Po odświeżeniu pomijasz cały kod React i React Router. Serwer otrzymuje żądanie
/joblist
i musi coś zwrócić. Na serwerze musisz przekazać żądaną ścieżkę dorun
metody, aby mogła wyświetlić poprawny widok. Możesz użyć tej samej mapy trasy, ale prawdopodobnie będziesz potrzebować innego połączenia zRouter.run
. Jak zauważa Charles, możesz do tego użyć przepisywania adresów URL. Inną opcją jest użycie serwera node.js do obsługi wszystkich żądań i przekazania wartości ścieżki jako argumentu lokalizacji.Na przykład w ekspresie może to wyglądać tak:
Zauważ, że ścieżka żądania jest przekazywana
run
. Aby to zrobić, musisz mieć silnik widoku po stronie serwera, do którego możesz przekazać renderowany kod HTML. Istnieje wiele innych uwag dotyczących używaniarenderToString
i uruchamiania React na serwerze. Gdy strona zostanie wyrenderowana na serwerze, aplikacja załaduje się na kliencie, wyświetli się ponownie, w razie potrzeby aktualizując renderowany HTML po stronie serwera.źródło
W pliku index.html
head
dodaj następujące dane:Następnie podczas uruchamiania z serwerem dewelopera webpack użyj tego polecenia.
--history-api-fallback
jest ważną częściąźródło
/
wtedyHashRouter
nie będzie działać (jeśli używasz skrótu routing)Właśnie utworzyłem stronę internetową za pomocą aplikacji create-reag-app i przedstawiłem ten sam problem. Używam
BrowserRouting
zreact-router-dom
paczki. Pracuję na serwerze Nginx i tym, co go rozwiązało, było dodanie do/etc/nginx/yourconfig.conf
Co odpowiada dodaniu następujących elementów
.htaccess
w przypadku uruchamiania AppacheTo także wydaje się być rozwiązaniem zaproponowanym przez Facebooka i można je znaleźć tutaj
źródło
To może rozwiązać twój problem
Ten sam problem napotkałem również w aplikacji ReactJS w trybie produkcyjnym. Oto 2 rozwiązanie problemu.
1. Zmień historię routingu na „hashHistory” zamiast browserHistory zamiast
Teraz skompiluj aplikację za pomocą polecenia
Następnie umieść folder kompilacji w folderze var / www /. Teraz aplikacja działa dobrze, dodając tag # w każdym adresie URL. lubić
localhost / # / home localhost / # / aboutus
Rozwiązanie 2: Bez tagu # przy użyciu browserHistory,
Ustaw swoją historię = {browserHistory} w routerze, teraz skompiluj ją, używając sudo npm run build.
Musisz utworzyć plik „conf”, aby rozwiązać stronę 404 nie znaleziono, plik conf powinien wyglądać tak.
otwórz terminal wpisz poniższe polecenia
cd / etc / apache2 / sites-available ls nano sample.conf Dodaj w nim poniższą zawartość.
Teraz musisz włączyć plik sample.conf za pomocą następującego polecenia
następnie poprosi cię o przeładowanie serwera apache, używając usługi sudo apache2 przeładuj lub uruchom ponownie
następnie otwórz folder localhost / build i dodaj plik .htaccess z zawartością poniżej.
Teraz aplikacja działa normalnie.
Uwaga: zmień ip 0.0.0.0 na lokalny adres IP.
W razie jakichkolwiek wątpliwości prosimy o komentarz.
Mam nadzieję, że jest to pomocne dla innych.
źródło
"react-router-dom": "^5.1.2"
?, używam<BrowserRouter>
Jeśli hostujesz aplikację reagującą za pośrednictwem AWS Static S3 Hosting i CloudFront
Problem ten pojawił się, gdy CloudFront odpowiedział komunikatem 403 Odmowa dostępu, ponieważ spodziewał się / niektóre / inne / ścieżki istnieć w moim folderze S3, ale ścieżka ta istnieje tylko wewnętrznie w routingu React z routerem reagującym.
Rozwiązaniem było skonfigurowanie reguły dystrybucji stron błędów. Przejdź do ustawień CloudFront i wybierz swoją dystrybucję. Następnie przejdź do zakładki „Strony błędów”. Kliknij „Utwórz niestandardową odpowiedź na błąd” i dodaj wpis dla 403, ponieważ otrzymujemy taki kod błędu. Ustaw ścieżkę strony odpowiedzi na /index.html, a kod stanu na 200. Wynik końcowy zadziwia mnie swoją prostotą. Strona indeksu jest wyświetlana, ale adres URL jest zachowywany w przeglądarce, więc po załadowaniu aplikacji reagującej wykrywa ścieżkę adresu URL i przechodzi do żądanej trasy.
Błąd Strony 403 Reguła
źródło
Web Dev Dev Server ma opcję, aby to włączyć. Otwórz
package.json
i dodaj--history-api-fallback
. Te rozwiązania działały dla mnie.samouczek dotyczący routera-reakcji
źródło
webpack-dev-server
ale jak to naprawić w przypadku wersji produkcyjnej?Jeśli hostujesz swoją aplikację reagującą na IIS, po prostu dodaj plik web.config zawierający:
Dzięki temu serwer IIS zwróci stronę główną do klienta zamiast błędu 404 i nie trzeba używać historii skrótów.
źródło
Dodaj to do
webpack.config.js
:źródło
Stos produkcyjny: React, React Router v4, BrowswerRouter, Express, Nginx
1) User BrowserRouter dla ładnych adresów URL
2) Dodaj index.html do wszystkich nieznanych żądań za pomocą
/*
3) pakiet webpack z
webpack -p
4) uruchom
nodemon server.js
lubnode server.js
EDYCJA: Możesz pozwolić nginx zająć się tym w bloku serwera i zignorować krok 2:
źródło
import path from 'path
alboconst path = require('path')
/*
) właśnie uratował mi dzień. Dziękuję Ci! :)Jeśli korzystasz z aplikacji Create React:
Jest jednak świetny spacer z tym problemem z rozwiązaniami dla wielu głównych platform hostingowych, które można znaleźć TUTAJ na stronie Utwórz aplikację React. Na przykład używam React Router v4 i Netlify dla mojego kodu frontendowego. Wystarczyło dodać 1 plik do mojego folderu publicznego („_redirects”) i jeden wiersz kodu w tym pliku:
Teraz moja witryna poprawnie renderuje ścieżki takie jak mysite.com/pricing, gdy zostanie wprowadzona do przeglądarki lub gdy ktoś odświeży.
źródło
Spróbuj dodać plik „.htaccess” do folderu publicznego za pomocą poniższego kodu.
źródło
Jeśli masz awarię pliku index.html, upewnij się, że w pliku index.html masz:
Może się to różnić w zależności od projektu.
źródło
head
: <base href = "/">Jeśli używasz Firebase, wszystko, co musisz zrobić, to upewnić się, że masz właściwość rewrites w pliku firebase.json w katalogu głównym aplikacji (w sekcji hostingowej).
Na przykład:
Mam nadzieję, że to ocali komuś frustrację i zmarnowany czas.
Miłego kodowania ...
Dalsze czytanie na ten temat:
https://firebase.google.com/docs/hosting/full-config#rewrites
Firebase CLI: „Skonfiguruj jako aplikację jednostronicową (przepisz wszystkie adresy URL do /index.html)”
źródło
Znalazłem rozwiązanie dla mojego SPA z routerem reagującym (Apache). Wystarczy dodać .htaccess
źródło: https://gist.github.com/alexsasharegan/173878f9d67055bfef63449fa7136042
źródło
Nie korzystam jeszcze z renderowania po stronie serwera, ale napotkałem ten sam problem co OP, w którym Link wydawał się działać przez większość czasu, ale zawiódł, gdy miałem parametr. Udokumentuję tutaj moje rozwiązanie, aby zobaczyć, czy to komukolwiek pomaga.
Mój główny plik jsx zawiera to:
Działa to dobrze dla pierwszego pasującego linku, ale gdy zmienia się: id
<Link>
wyrażeniach zagnieżdżonych na stronie szczegółów tego modelu, adres URL zmienia się na pasku przeglądarki, ale treść strony początkowo nie zmieniła się, aby odzwierciedlić połączony model.Problem polegał na tym, że użyłem go
props.params.id
do ustawienia modelucomponentDidMount
. Komponent jest montowany tylko raz, co oznacza, że pierwszy model jest tym, który przykleja się do strony, a kolejne linki zmieniają rekwizyty, ale pozostawiają stronę niezmienioną.Ustawienie modelu w stanie komponentu zarówno w, jak
componentDidMount
i wcomponentWillReceiveProps
(gdzie jest oparty na następnych rekwizytach) rozwiązuje problem, a zawartość strony zmienia się, odzwierciedlając pożądany model.źródło
props
) iso,componentDidMount
jeśli kiedykolwiek chcesz spróbować renderowania po stronie serwera. PonieważcomponentDidMount
jest wywoływany tylko w przeglądarce. Jego celem jest robienie rzeczy z DOM, takich jak dołączanie detektorów zdarzeń dobody
itp., W których nie można tego zrobićrender
.Ten temat jest nieco stary i rozwiązany, ale chciałbym zaproponować proste, jasne i lepsze rozwiązanie. Działa, jeśli używasz serwera WWW.
Każdy serwer sieciowy ma możliwość przekierowania użytkownika na stronę błędu w przypadku http 404. Aby rozwiązać ten problem, należy przekierować użytkownika na stronę indeksu.
W przypadku korzystania z serwera bazowego Java (tomcat lub dowolnego serwera aplikacji Java) rozwiązaniem może być:
web.xml:
Przykład:
To tyle, nie ma już magicznych potrzeb :)
źródło
const browserHistory = useRouterHistory(createHistory)({ basename: '/<appname>' });
Jeśli używasz Express lub innego frameworka w backend, możesz dodać podobną konfigurację jak poniżej i sprawdzić publiczną ścieżkę Webpack w konfiguracji, powinna działać dobrze nawet przy przeładowaniu, jeśli używasz BrowserRouter
źródło
Naprawianie błędu „nie można uzyskać / adresu URL” przy odświeżaniu lub przy bezpośrednim wywołaniu adresu URL.
Skonfiguruj plik webpack.config.js, aby oczekiwać, że podany link będzie przebiegał w ten sposób.
źródło
Podczas korzystania z .Net Core MVC coś takiego pomogło mi:
Zasadniczo po stronie MVC, wszystkie niepasujące trasy wpadną
Home/Index
zgodnie z opisem wstartup.cs
. WewnątrzIndex
można uzyskać oryginalny adres URL żądania i przekazać go w dowolnym miejscu.źródło
Jeśli prowadzisz hosting w IIS; Dodanie tego do mojej konfiguracji sieci rozwiązało mój problem
Możesz dokonać podobnej konfiguracji dla dowolnego innego serwera
źródło
Na wypadek, gdyby ktoś szukał rozwiązania w React JS SPA z Laravelem. Przyjęta odpowiedź jest najlepszym wyjaśnieniem, dlaczego tak się dzieje. Jak już wyjaśniono, musisz skonfigurować zarówno po stronie klienta, jak i serwera. W szablonie bloku dołącz plik js, upewnij się, że używasz go w
URL facade
ten sposóbNa swoich trasach dodaj to do głównego punktu końcowego, w którym znajduje się szablon bloku. Na przykład,
Powyżej jest głównym punktem końcowym dla szablonu bloku. Teraz dodaj też opcjonalną trasę,
Problem, który się zdarza, polega na tym, że najpierw ładowany jest szablon bloku, a następnie router reagujący. Kiedy ładujesz
'/setting-alerts'
, ładuje html i js. Ale po załadowaniu'/setting-alerts/about'
najpierw ładuje się po stronie serwera. Ponieważ po stronie serwera nie ma nic w tej lokalizacji, zwraca nie znaleziono. Gdy masz ten opcjonalny router, ładuje tę samą stronę i reaguje na załadowanie routera, a następnie reagujący moduł ładujący decyduje, który składnik ma zostać wyświetlony. Mam nadzieję że to pomoże.źródło
/user/{userID}
, muszę tylko zwrócić uniwersalny/user
widok HTML, przynieść identyfikator i wywołać go za pomocą AJAX lub axios. czy jest to możliwe do zrobienia? czy są przyjazne SEO?Dla tych, którzy używają IIS 10, powinieneś to zrobić, aby to zrobić. Upewnij się, że używasz do tego przeglądarki browserHistory. Jeśli chodzi o odniesienie, dam kod do routingu, ale to nie jest ważne, liczy się następny krok po kodzie poniżej:
Ponieważ problem polega na tym, że IIS otrzymuje żądanie od przeglądarki klienta, zinterpretuje adres URL tak, jakby prosi o stronę, a następnie zwraca stronę 404, ponieważ nie ma dostępnej strony. Wykonaj następujące czynności:
I teraz będzie działać dobrze.
Mam nadzieję, że to pomoże. :-)
źródło
Korzystam z WebPack, miałem ten sam problem Rozwiązanie => W twoim pliku server.js
Dlaczego moja aplikacja nie renderuje się po odświeżeniu?
źródło
Używanie
HashRouter
działało również dla mnie z Redux , wystarczy po prostu zastąpić:do:
źródło
Miałem ten sam problem i to rozwiązanie działało dla nas ..
Tło:
Hostujemy wiele aplikacji na tym samym serwerze. Gdy odświeżymy serwer nie będzie wiedział, gdzie szukać naszego indeksu w folderze dist dla tej konkretnej aplikacji. Powyższy link przeniesie Cię do tego, co dla nas zadziałało ... Mam nadzieję, że to pomaga, ponieważ spędziliśmy sporo godzin na wypracowaniu rozwiązania dla naszych potrzeb.
Używamy:
mój webpack.config.js
mój index.js
moja aplikacja.js
źródło
Lubię ten sposób obsługi. Spróbuj dodać: yourSPAPageRoute / * po stronie serwera, aby pozbyć się tego problemu.
Podjąłem to podejście, ponieważ nawet natywny interfejs API historii HTML5 nie obsługuje prawidłowego przekierowania przy odświeżaniu strony (o ile mi wiadomo).
Uwaga: wybrana odpowiedź już rozwiązała ten problem, ale staram się być bardziej szczegółowy.
Droga ekspresowa
Przetestowałem i chciałem się tym podzielić.
Mam nadzieję, że to pomoże.
źródło