Renderowanie po stronie serwera ReactJS a renderowanie po stronie klienta

120

Właśnie zacząłem studiować ReactJS i odkryłem, że daje ci 2 sposoby renderowania stron: po stronie serwera i po stronie klienta. Ale nie rozumiem, jak używać tego razem. Czy są to 2 oddzielne sposoby tworzenia aplikacji, czy mogą być używane razem?

Jeśli możemy go używać razem, jak to zrobić - czy musimy powielać te same elementy po stronie serwera i klienta? A może możemy po prostu zbudować statyczne części naszej aplikacji na serwerze, a dynamiczne części po stronie klienta, bez żadnego połączenia z serwerem, który został już wstępnie wyrenderowany?

Simcha
źródło
1
Krótka odpowiedź, NIE - można odłączyć, wysłać statyczny html i całkowicie zmienić go w renderowaniu klienta. Dodałem szczegóły w mojej odpowiedzi.
Kira

Odpowiedzi:

108

Dla danej strony / web-aplikacji, można użyć reagują zarówno po stronie klienta , po stronie serwera lub oba .

Strona klienta

Tutaj całkowicie uruchamiasz ReactJS w przeglądarce. To jest najprostsza konfiguracja i zawiera większość przykładów (w tym te na http://reactjs.org ). Początkowy kod HTML renderowany przez serwer jest symbolem zastępczym, a cały interfejs użytkownika jest renderowany w przeglądarce po załadowaniu wszystkich skryptów.

Po stronie serwera

Pomyśl o ReactJS jako o silniku szablonów po stronie serwera (jak jadeit, kierownica itp.). HTML renderowany przez serwer zawiera interfejs użytkownika tak, jak powinien, a Ty nie czekasz na załadowanie jakichkolwiek skryptów. Twoja strona może być zindeksowana przez wyszukiwarkę (jeśli nie wykonuje ona żadnego javascript).

Ponieważ interfejs użytkownika jest renderowany na serwerze, żaden z programów obsługi zdarzeń nie działałby i nie ma interaktywności (masz stronę statyczną).

Obie

Tutaj początkowe renderowanie znajduje się na serwerze. W związku z tym kod HTML odebrany przez przeglądarkę ma interfejs użytkownika tak, jak powinien. Po załadowaniu skryptów wirtualny DOM jest ponownie renderowany, aby skonfigurować procedury obsługi zdarzeń komponentów.

Tutaj musisz upewnić się, że ponownie wyrenderujesz dokładnie ten sam wirtualny DOM (główny komponent ReactJS) z tym samym props, którego użyłeś do renderowania na serwerze. W przeciwnym razie ReactJS będzie narzekać, że wirtualne DOM po stronie serwera i klienta nie pasują do siebie.

Ponieważ ReactJS porównuje wirtualne DOM pomiędzy kolejnymi renderowaniami, prawdziwy DOM nie jest mutowany. Tylko programy obsługi zdarzeń są powiązane z rzeczywistymi elementami DOM.

Gautham Badhrinathan
źródło
1
Więc w przypadku "obu" muszę napisać ten sam kod dwa razy "jeden do renderowania serwera, a drugi do odtworzenia tego DOM na kliencie? Prawda?
Simcha
10
Musisz dwukrotnie uruchomić ten sam kod. Raz na serwerze i raz na kliencie. Musisz jednak napisać komponenty, aby to uwzględnić - np. Nie powinieneś pobierać żadnych danych asynchronicznych componentWillMount(), ponieważ będzie to działać zarówno na kliencie, jak i na serwerze. Będziesz także potrzebować strategii pobierania danych z góry na serwer i udostępniania ich do początkowego renderowania na kliencie, aby upewnić się, że uzyskasz te same dane wyjściowe.
Jonny Buchanan
3
Możesz również sprawdzić, czy wykonywany kod znajduje się po stronie serwera lub klienta, typeof window == "undefined"a następnie odpowiednio pobrać dane.
Gautham Badhrinathan,
Czy masz link do przykładu pasującego do Twojej realizacji?
Sawtaytoes
1
@IanW Zazwyczaj w tym przypadku kod HTML zwrócony przez serwer jest bardzo „nagim kością”, po prostu importując twój JavaScript i style oraz zawierający kod, do <div>którego zapisze React.
Matt Holland,
48

Źródło obrazu: Blog inżynieryjny Walmart Labs

SSR

CSR

Uwaga: SSR (renderowanie po stronie serwera), CSR (renderowanie po stronie klienta).

Główną różnicą jest to, że w przypadku SSR, odpowiedź serwerów na przeglądarkę klienta zawiera kod HTML strony, która ma być renderowana. Należy również zauważyć, że chociaż w przypadku SSR strona renderuje się szybciej. Strona nie będzie gotowa do interakcji użytkownika, dopóki pliki JS nie zostaną pobrane, a przeglądarka nie wykona Reakcji.

Jedną wadą jest to, że SSR TTFB (czas do pierwszego bajtu) może być nieco dłuższy. Jest to zrozumiałe, ponieważ serwer potrzebuje trochę czasu na utworzenie dokumentu HTML, co z kolei zwiększa rozmiar odpowiedzi serwera.

JSON C11
źródło
4

Właściwie zastanawiałem się trochę nad tymi samymi badaniami i chociaż odpowiedź, której szukasz, została podana w komentarzach, ale uważam, że powinna być bardziej widoczna, dlatego piszę ten post (który zaktualizuję, gdy będę mógł wymyślić lepszy sposób, ponieważ uważam, że rozwiązanie jest co najmniej wątpliwe pod względem architektonicznym).

Musiałbyś napisać swoje komponenty mając na uwadze oba sposoby, więc zasadniczo umieszczaj ifprzełączniki wszędzie, aby określić, czy jesteś na kliencie, czy na serwerze, a następnie wykonaj zapytanie do bazy danych (lub cokolwiek odpowiedniego na serwerze) lub wywołanie REST (na serwerze klient). Następnie musiałbyś napisać punkty końcowe, które generują twoje dane i udostępniają je klientowi i gotowe.

Ponownie, chętnie dowiemy się o czystszym rozwiązaniu.

SGD
źródło
2

Czy są to 2 oddzielne sposoby tworzenia aplikacji, czy mogą być używane razem?

Mogą być używane razem.

Jeśli możemy go używać razem, jak to zrobić - czy musimy powielać te same elementy po stronie serwera i klienta? A może możemy po prostu zbudować statyczne części naszej aplikacji na serwerze, a dynamiczne części po stronie klienta, bez żadnego połączenia z serwerem, który został już wstępnie wyrenderowany?

Lepiej jest renderować ten sam układ, aby uniknąć operacji ponownego malowania i ponownego malowania, mniej migotania / migania, a Twoja strona będzie gładsza. Jednak to nie jest ograniczenie. Możesz bardzo dobrze buforować SSR html (coś, co robi Electrode , aby skrócić czas odpowiedzi) / wysłać statyczny html, który zostanie nadpisany przez CSR (renderowanie po stronie klienta).

Jeśli dopiero zaczynasz od SSR, polecam zacząć od prostego, SSR może bardzo szybko się skomplikować. Budowanie html na serwerze oznacza utratę dostępu do obiektów takich jak okno, dokument (masz je na kliencie), utratę możliwości włączenia operacji asynchronicznych (po wyjęciu z pudełka) i ogólnie wiele edycji kodu w celu uzyskania kompatybilności z SSR kodu ( ponieważ do spakowania pliku bundle.js będziesz musiał użyć pakietu webpack). Rzeczy takie jak import CSS, wymagają vs import nagle zaczynają Cię gryźć (nie ma to miejsca w domyślnej aplikacji React bez pakietu webpacka).

Ogólny wzorzec SSR wygląda następująco. Serwer Express obsługujący żądania:

const app = Express();
const port = 8092;

// This is fired every time the server side receives a request
app.use(handleRender);
function handleRender(req, res) {
    const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
    console.log('fullUrl: ', fullUrl);
    console.log('req.url: ', req.url);

    // Create a new Redux store instance
    const store = createStore(reducerFn);

    const urlToRender = req.url;
    // Render the component to a string
    const html = renderToString(
        <Provider store={store}>
            <StaticRouter location={urlToRender} context={{}}>
                {routes}
            </StaticRouter>
        </Provider>
    );
    const helmet = Helmet.renderStatic();

    // Grab the initial state from our Redux store
    const preloadedState = store.getState();

    // Send the rendered page back to the client
    res.send(renderFullPage(helmet, html, preloadedState));
}

Moja sugestia dla osób zaczynających od SSR to wyświetlanie statycznego html. Możesz pobrać statyczny html, uruchamiając aplikację CSR SPA:

document.getElementById('root').innerHTML

Nie zapominaj, że jedynymi powodami, dla których warto używać SSR, powinny być:

  1. SEO
  2. Szybsze ładowanie (zdyskontowałbym to)

Hack: https://medium.com/@gagan_goku/react-and-server-side-rendering-ssr-444d8c48abfc

Kira
źródło