Por Rohit Kumar
Aqui está o que vamos construir neste tutorial: um belo cartão React como este.
Neste tutorial, vamos usar renderização do lado do servidor para entregar uma resposta HTML quando um utilizador ou crawler atinge a URL de uma página. Vamos lidar com os últimos pedidos do lado do cliente.
Por que precisamos disso?
Deixe-me guiá-lo à resposta.
- Qual é a diferença entre renderização do lado do cliente e renderização do lado do servidor?
- Cons of Rendering React on the Server
- Quando você deve usar o Server Side Rendering?
- SEO
- Improve performance
- React Rendered on Server
- Reagir Renderizado no Navegador do Cliente
- Como funciona? – (4 Passos Simples)
- Configurando o nosso App
- Por que precisamos de compilar ficheiros fonte?
- Copiar Pré-Codificado &Arquivos estáticos
- Lado do servidor
- src/server.js
- 2. src/template.js
- O lado cliente
- src/bundle.js
- src/client.js
- Pondo tudo junto
- Index.js
- Build & Run
- Pronto para se tornar um React Pro?
- Obrigado por ler isto.
Qual é a diferença entre renderização do lado do cliente e renderização do lado do servidor?
Na renderização do lado do cliente, seu navegador baixa uma página HTML mínima. Ele renderiza o JavaScript e preenche o conteúdo nele.
Renderização do lado do servidor, por outro lado, renderiza os componentes React no servidor. A saída é conteúdo HTML.
Você pode combinar estes dois para criar uma aplicação isomórfica.
Cons of Rendering React on the Server
- SSR pode melhorar a performance se a sua aplicação for pequena. Mas também pode degradar a performance se for pesado.
- Aumenta o tempo de resposta (e pode ser pior se o servidor estiver ocupado).
- Aumenta o tamanho da resposta, o que significa que a página leva mais tempo para carregar.
- Aumenta a complexidade da aplicação.
Quando você deve usar o Server Side Rendering?
Embora estas consequências do SSR, existem algumas situações em que você pode e deve usá-lo.
SEO
Todos os websites querem aparecer nas buscas. Corrija-me se eu estiver errado.
Felizmente, os crawlers do motor de busca ainda não entendem/render JavaScript.
Isso significa que eles vêem uma página em branco, não importa o quão útil o seu site é.
Muita gente diz que o crawler do Google agora renderiza JavaScript.
Para testar isso, eu implementei o aplicativo no Heroku. Aqui está o que vi na Consola de Pesquisa do Google:
Uma página em branco.
Esta foi a maior razão pela qual eu explorei a renderização do lado do servidor. Especialmente quando é uma página de cornerstone como uma página de aterragem, blog, etc.
Para verificar se o Google renderiza o seu site, visite:
Search Console Dashboard > Crawl > Fetch as Google. Digite o URL da página ou deixe-o vazio para a página inicial.
Selecione FETCH AND RENDER. Uma vez completo, clique para ver o resultado.
Improve performance
No SSR, a performance da aplicação depende dos recursos do servidor e da velocidade da rede do utilizador. Isso o torna muito útil para sites de conteúdo pesado.
Por exemplo, digamos que você tenha um telefone celular de preço médio com velocidade de internet lenta. Você tenta acessar um site que baixa 4MB de dados antes que você possa ver qualquer coisa.
Você poderia ver qualquer coisa na sua tela em 2-4 segundos?
Você poderia visitar aquele site novamente?
Eu não acho que você faria.
Outra grande melhoria está no Tempo de Interação do Primeiro Usuário. Esta é a diferença no tempo desde quando um usuário acessa a URL até quando ele vê o conteúdo.
Aqui está a comparação. Eu testei em um Mac.
React Rendered on Server
O primeiro tempo de interação é de 300ms. O Hydrate termina a 400ms. O evento de carga sai a 500ms aproximadamente. Você pode ver isto verificando a imagem acima.
O primeiro tempo de interação é de 400ms. O evento de carga sai a 470ms.
O resultado fala por si. Há uma diferença de 100ms no Primeiro Tempo de Interacção do Utilizador para uma aplicação tão pequena.
Como funciona? – (4 Passos Simples)
- Criar uma nova Loja Redux em cada pedido.
- Despachar algumas ações.
- Retirar o estado da Loja e executar SSR.
- Enviar o estado obtido no passo anterior junto com a resposta.
Usaremos o estado passado na resposta para criar o estado inicial no lado do cliente.
Antes de começar, clone/download o exemplo completo do Github e use-o como referência.
Configurando o nosso App
Primeiro, abra o seu editor e shell favoritos. Crie uma nova pasta para a sua aplicação. Vamos começar.
npm init --yes
Preencher nos detalhes. Depois que package.json
for criado, copie as dependências e scripts abaixo para ele.
Instale todas as dependências executando:
npm install
Você precisa configurar Babel e webpack para que o nosso script de compilação funcione.
Babel transforma o ESM e reage em Node e código compreendido pelo navegador.
Criar um novo arquivo .babelrc
e colocar a linha abaixo nele.
{ "presets": }
webpack agrupa nosso aplicativo e suas dependências em um único arquivo. Crie outro arquivo webpack.config.js
com o seguinte código nele:
const path = require('path');module.exports = { entry: { client: './src/client.js', bundle: './src/bundle.js' }, output: { path: path.resolve(__dirname, 'assets'), filename: ".js" }, module: { rules: }}
Os dois arquivos de saída do processo de compilação:
-
assets/bundle.js
-apartamento do lado do cliente puro. -
assets/client.js
-comparador do lado do cliente para SSR.
>O arquivo src/
folder contém o código fonte. Os arquivos compilados em Babel vão para views/
. views
directório será criado automaticamente se não estiver presente.
Por que precisamos de compilar ficheiros fonte?
A razão é a diferença de sintaxe entre ESM & CommonJS. Enquanto escrevemos React e Redux, nós usamos fortemente importação e exportação em todos os arquivos.
Felizmente, eles não funcionam em Node. Aí vem Babel para resgatar. O script abaixo diz ao Babel para compilar todos os arquivos no diretório src
e colocar o resultado em views.
"babel": "babel src -d views",
Agora, o Nó pode executá-los.
Copiar Pré-Codificado &Arquivos estáticos
Se você já clonou o repositório, copie a partir dele. Caso contrário, baixe o arquivo ssr-static.zip do Dropbox. Extraia-o e mantenha estas três pastas dentro do seu directório de aplicações. Aqui está o que eles contêm.
- Reagir
App
e os componentes residem emsrc/components
. - Arquivos Redux em
src/redux/
. -
assets/ & media/
: Contém arquivos estáticos comostyle.css
e imagens.
Lado do servidor
Criar dois novos arquivos chamados server.js
e template.js
dentro da pasta src/
.
src/server.js
Magic acontece aqui. Este é o código que você tem procurado.
import React from 'react';import { renderToString } from 'react-dom/server';import { Provider } from 'react-redux';import configureStore from './redux/configureStore';import App from './components/app';module.exports = function render(initialState) { // Model the initial state const store = configureStore(initialState); let content = renderToString(<Provider store={store} ><App /></Provider>); const preloadedState = store.getState(); return { content, preloadedState };};
Em vez de renderizar a nossa aplicação, precisamos de embrulhá-la numa função e exportá-la. A função aceita o estado inicial da aplicação.
Aí está como ela funciona.
- Passar
initialState
aconfigureStore()
.configureStore()
Retira uma nova instância da Store. Mantenha-o dentro do métodostore
variável. - Chamar método
renderToString()
, fornecendo nossa App como entrada. Ele renderiza nossa aplicação no servidor e retorna o HTML produzido. Agora, a variávelcontent
armazena o HTML. - Tirar o estado da Redux Store chamando
getState()
emstore
. Mantenha-o em uma variávelpreloadedState
. - Retornar os
content
epreloadedState
. Vamos passar estes para o nosso template para obter a página HTML final.
2. src/template.js
template.js
exporta uma função. Leva title
, state
e content
como entrada. Ele os injeta no template e retorna o documento HTML final.
Para passar ao longo do estado, o template anexa state
a window.__STATE__
dentro de um tag <scri
pt>.
Agora você pode ler state
no lado do cliente acessando window.__STATE__
.
Incluímos também o companheiro SSR assets/client.js
aplicação do lado do cliente em outro tag de script.
Se solicitar a versão cliente pura, apenas coloca assets/bundle.js
dentro da tag do script.
O lado cliente
O lado cliente é bastante simples.
src/bundle.js
É assim que se escreve o React e o Redux Provider
wrap. É a nossa pura aplicação do lado do cliente. Sem truques aqui.
import React from 'react';import { render } from 'react-dom';import { Provider } from 'react-redux';import configureStore from './redux/configureStore';import App from './components/app';const store = configureStore();render( <Provider store={store} > <App /> </Provider>, document.querySelector('#app'));
src/client.js
Parece-lhe familiar? Sim, não há nada de especial excepto window.__STATE__.
Tudo o que precisamos fazer é pegar no estado inicial de window.__STATE__
e passá-lo para a nossa função configureStore()
como estado inicial.
Vejamos o nosso novo ficheiro de cliente:
import React from 'react';import { hydrate } from 'react-dom';import { Provider } from 'react-redux';import configureStore from './redux/configureStore';import App from './components/app';const state = window.__STATE__;delete window.__STATE__;const store = configureStore(state);hydrate( <Provider store={store} > <App /> </Provider>, document.querySelector('#app'));
Vejamos as alterações:
- Substitua
render()
porhydrate()
.hydrate()
é o mesmo querender()
mas é usado para hidratar elementos renderizados porReactDOMServer
. Ele garante que o conteúdo é o mesmo no servidor e no cliente. - Lê o estado do objecto da janela global
window.__STATE__
. Guarda-o numa variável e elimina owindow.__STATE__
. - Cria uma nova loja com
state
como initialState.
Tudo feito aqui.
Pondo tudo junto
Index.js
Este é o ponto de entrada da nossa aplicação. Ele lida com pedidos e templates.
Ele também declara uma variável initialState
. Eu a modelei com dados no arquivo assets/data.json
. Vamos passá-la para a nossa ssr()
function.
Note: Ao referenciar um ficheiro que está dentro src/
de um ficheiro fora de src/
, use normal require()
e substitua src/
por views/
. Você sabe a razão (Babel compile).
Roteamento
-
/
: Por padrão página inicial renderizada ao servidor. -
/client
: Puro exemplo de renderização do lado do cliente. -
/exit
: Botão de paragem do servidor. Apenas disponível em desenvolvimento.
Build & Run
É tempo de construir e executar a nossa aplicação. Podemos fazer isto com uma única linha de código.
npm run build && npm run start
Agora, a aplicação está a correr em http://localhost:3000.
Pronto para se tornar um React Pro?
A partir da próxima segunda-feira estou a iniciar uma nova série para ter as suas capacidades React a brilhar, imediatamente.
Obrigado por ler isto.
Se você gostar e achar útil, siga-me no Twitter & Webflow.