Renderização do lado do servidor ReactJS versus renderização do lado do cliente

120

Acabei de começar a estudar o ReactJS e descobri que ele oferece 2 maneiras de renderizar páginas: do lado do servidor e do lado do cliente. Mas, não consigo entender como usá-lo juntos. São duas maneiras diferentes de criar o aplicativo ou podem ser usadas juntas?

Se podemos usá-lo juntos, como fazê-lo - precisamos duplicar os mesmos elementos no lado do servidor e no lado do cliente? Ou podemos apenas construir as partes estáticas de nosso aplicativo no servidor e as partes dinâmicas no lado do cliente, sem nenhuma conexão com o lado do servidor que já foi pré-renderizada?

Simcha
fonte
1
Resposta curta, NÃO - você pode desacoplar, enviar html estático e alterá-lo completamente na renderização do cliente. Adicionei detalhes na minha resposta.
Kira de

Respostas:

108

Para um dado / aplicação web site, você pode usar reagir, quer do lado do cliente , do lado do servidor ou ambos .

Cliente

Aqui, você está executando completamente o ReactJS no navegador. Esta é a configuração mais simples e inclui a maioria dos exemplos (incluindo aqueles em http://reactjs.org ). O HTML inicial renderizado pelo servidor é um espaço reservado e toda a IU é renderizada no navegador quando todos os seus scripts são carregados.

Servidor

Pense no ReactJS como um mecanismo de modelagem do lado do servidor (como jade, guidão, etc ...). O HTML renderizado pelo servidor contém a IU como deveria ser e você não espera que nenhum script seja carregado. A sua página pode ser indexada por um motor de busca (se não executar nenhum javascript).

Como a IU é renderizada no servidor, nenhum de seus manipuladores de eventos funcionaria e não há interatividade (você tem uma página estática).

Ambos

Aqui, a renderização inicial está no servidor. Portanto, o HTML recebido pelo navegador tem a IU como deveria ser. Depois que os scripts são carregados, o DOM virtual é renderizado novamente para configurar os manipuladores de eventos de seus componentes.

Aqui, você precisa ter certeza de renderizar novamente o mesmo DOM virtual (componente raiz ReactJS) com o mesmo propsque você usou para renderizar no servidor. Caso contrário, o ReactJS reclamará que os DOMs virtuais do lado do servidor e do lado do cliente não correspondem.

Uma vez que ReactJS diffs os DOMs virtuais entre re-renderizadores, o DOM real não sofre mutação. Apenas os manipuladores de eventos estão vinculados aos elementos DOM reais.

Gautham Badhrinathan
fonte
1
Portanto, no caso de "ambos", preciso escrever o mesmo código duas vezes "um para renderização do servidor e outro para reproduzir este DOM no cliente? Certo?
Simcha
10
Você precisa executar o mesmo código duas vezes. Uma vez no servidor e uma vez no cliente. No entanto, você precisa escrever seus componentes para levar isso em conta - por exemplo, você não deve fazer nenhuma busca assíncrona de dados componentWillMount(), pois isso irá executar o cliente e o servidor. Você também precisará de uma estratégia para buscar dados antecipadamente no servidor e disponibilizá-los para renderização inicial no cliente, para ter certeza de obter a mesma saída.
Jonny Buchanan
3
Você também pode verificar se o código que está sendo executado está no lado do servidor ou no lado do cliente usando typeof window == "undefined"e, em seguida, buscar seus dados de acordo.
Gautham Badhrinathan
Você tem um link para um exemplo que se encaixa na sua implementação?
Sawtaytoes de
1
@IanW Normalmente, neste caso, o HTML retornado pelo servidor é muito "básico", simplesmente importando seu JavaScript e estilos e contendo um no <div>qual o React irá gravar.
Matt Holland
48

Fonte da imagem: Blog de engenharia do Walmart Labs

SSR

CSR

NB: SSR (Server Side Rendering), CSR (Client Side Rendering).

A principal diferença é que com o SSR, a resposta do servidor ao navegador do cliente inclui o HTML da página a ser renderizada. Também é importante notar que, embora, com SSR, a página seja renderizada mais rapidamente. A página não estará pronta para interação do usuário até que os arquivos JS sejam baixados e o navegador execute o React.

Uma desvantagem é que o SSR TTFB (Time to First Byte) pode ser um pouco mais longo. Compreensivelmente, porque o servidor leva algum tempo para criar o documento HTML, o que, por sua vez, aumenta o tamanho da resposta do servidor.

JSON C11
fonte
4

Na verdade, eu estava me perguntando o mesmo pesquisando um pouco e embora a resposta que você está procurando tenha sido dada nos comentários, mas acho que deveria ser mais proeminente, portanto, estou escrevendo este post (que atualizarei assim que puder encontrar um melhor maneira, pois acho a solução arquiteturalmente pelo menos questionável).

Você precisaria escrever seus componentes com ambas as maneiras em mente, portanto, basicamente colocando ifinterruptores em todos os lugares para determinar se você está no cliente ou no servidor e, em seguida, fazer uma consulta ao banco de dados (ou o que for apropriado no servidor) ou uma chamada REST (no cliente). Então você teria que escrever endpoints que geram seus dados e os expõem ao cliente e pronto.

Mais uma vez, fico feliz em aprender sobre uma solução mais limpa.

SGD
fonte
2

São duas maneiras diferentes de criar o aplicativo ou podem ser usadas juntas?

Eles podem ser usados ​​juntos.

Se podemos usá-lo juntos, como fazê-lo - precisamos duplicar os mesmos elementos no lado do servidor e no lado do cliente? Ou podemos apenas construir as partes estáticas de nosso aplicativo no servidor e as partes dinâmicas no lado do cliente, sem nenhuma conexão com o lado do servidor que já foi pré-renderizada?

É melhor ter o mesmo layout sendo renderizado para evitar operações de refluxo e redesenho, menos cintilação / pisca, sua página ficará mais lisa. No entanto, não é uma limitação. Você poderia muito bem armazenar em cache o html SSR (algo que o Electrode faz para reduzir o tempo de resposta) / enviar um html estático que é sobrescrito pelo CSR (renderização do lado do cliente).

Se você está apenas começando com SSR, recomendo começar simples, SSR pode se tornar muito complexo muito rapidamente. Construir html no servidor significa perder o acesso a objetos como janela, documento (você os tem no cliente), perder a capacidade de incorporar operações assíncronas (pronto para uso) e, geralmente, muitas edições de código para tornar seu código compatível com SSR ( já que você terá que usar o webpack para embalar seu bundle.js). Coisas como importações CSS, require vs import repentinamente começam a incomodar você (este não é o caso no aplicativo React padrão sem webpack).

O padrão geral do SSR é assim. Um servidor expresso atendendo a solicitações:

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));
}

Minha sugestão para quem está começando com SSR seria servir html estático. Você pode obter o html estático executando o aplicativo CSR SPA:

document.getElementById('root').innerHTML

Não se esqueça, os únicos motivos para usar o SSR devem ser:

  1. SEO
  2. Carregamentos mais rápidos (eu descontaria isso)

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

Kira
fonte