Executando verificação de segurança...
5

Por que usar Server Components? - Uma breve história da web

Esse post é uma tradução do artigo Why Server Components - A Brief History of Web.

Esse post terá apenas a metade inicial do artigo, pois o Tabnews tem um limite de 20000 palavras por post. O restante do artigo estará em um dos comentários logo abaixo.


De acordo com o Stack Overflow survey 2023, Next.js é o terceiro framework web mais desejado atualmente, além de ser o sexto mais admirado entre os desenvolvedores. Apesar de seu antigo Pages Router ser ótimo, eles introduziram um novo App Router na versão 13 do framework. Com essa mudança, eles também migraram para o uso de Server Components que podem ser vistos como um próximo nível de renderização no servidor.

Para entender por que Next.js e Server Components são muito mais do que apenas aplicações React tradicionais do lado do cliente, este artigo guiará você desde o início da web, através de diferentes tipos de renderização no servidor com todos os seus benefícios, até o mais novo estado do desenvolvimento web com Next.js Server Components.

Neste Artigo

De Server Rendering para SPAs e então de volta para o servidor

Para entender melhor os Server Components, nós precisamos falar sobre por que eles foram introduzidos. Para isso, nós vamos precisar de uma pequena aula de história.

Nos dias do desenvolvimento web antigo e tradicional, um site consistia de um servidor renderizando código HTML, enviando-o pela internet para um browser que mostrava o HTML já renderizado ao usuário. Com isso, você tinha CSS e alguns pequenos arquivos de JavaScript para gerenciar as interações do usuário e a navegação para outras páginas no site (e também para mostrar um contador de visitas legal, que era meio que obrigatório).

Tecnologias mais novas surgiram e nós ganhamos smartphones e computadores melhores com muito mais performance. A internet evoluiu e single pages applications (SPAs) passaram a ser o novo padrão, o que basicamente significava que apenas uma página inicial era enviada para o client. Ao navegar ou interagit com a página, requisições REST eram usaads para recuperar dados do servidor e modificar a página sem efetivamente navegar para outra página do site.

Um dos maiores pivôs para essa evolução foi a biblioteca jQuery e seu principio continuou crescendo com frameworks modernos, como React, Angular e Vue que em primeiro lugar renderizavam tudo no lado do cliente, com suporte para usar server side rendering (SSR) opcionalmente. À medida que a web migrou para SPAs nós começamos a chamar sites com funcionalidades avançadas de aplicativos web (web applications).

Mais e mais fremeworks de aplicativos web surgiram e diferentes formas de pré-renderizar esses aplicativos surgiram. Pré-renderizar páginas web em requisições com SSR não era o suficiente, frameworks podiam também adicionar suporte para pré-renderizar páginas em tempo de compilação, assim chamado static site generation (SSG).

Em breve veremos mais de perto SSR e SSG e no fim desse artigo nós vamos discutir prós e contras de renderização no servidor. Mas por hora, vamos esquecer o por que e focar no o quê e como.

Onde nós estamos hoje, não é uma questão sobre renderização no lado do cliente ou servidor, nós chegamos em um ponto onde podemos escolher renderizar pequenas partes do site diferendemente e é aí que Client e Server Components entram.

Client Components vs Server Components

Se você já usou frameworks de SPA como React e Angular, você já deve estar familiarizado com Client Components. Eles são basicamente como um componente React é em sua natureza, um pouco de códico JavaScript que renderiza um componente em uma página logo que chega no navegador.

Por outro lado, Server Components são renderizados em HTML no servidor. Quando eu falo isso, não me refiro a pré-renderizar HTML para uma página completa com SSR ou SSG, eu literalmente quero dizer renderizar um pequeno componente, como um pequeno componente React. Essa é a granularidade oferecida pelo novo App Router do Next.js.

Para ter uma melhor visão disso, vamos olhar para as soluções antigas de pré-renderização e então voltar para os Server Components.

Server Side Rendering (SSR) vs Static Site Generation (SSG)

O básico sobre SSR e SSG são o mesmo: pré-renderizar código HTML no servidor e então buscar (fetching) JavaScript para fazer a página ser interativa, em um processo chamado hydration. Dependendo do framework, a navegação pode resultar na busca de páginas completamente novas do servidor ou ser manipulada por hydration, como faria uma SPA.

Pre-renderizar vai buscar HTML e ele vai ser "hidratado" com JavaScript para fazer a página interativa

Quando usamos SSR como uma solução de pré-renderização, uma página completa é renderizada em HTML no servidor quando uma página é requisitada. O servidor então vai também buscar o JavaScript e iniciar o processo de hydration.

SSR renderiza HTML para uma página quando um navegador está a requisitando

Em vez disso, SSG permite você a pré-renderizar a aplicação já em tempo de compilação, que faz possível enviar a mesma página HTML rapidamente para qualquer usuário sem precisar renderizar uma página em tempo de execução.

SSG renderiza HTML em tempo de compilação e o envia para todas as requisições

Enquanto SSG permite enviar páginas web instantâneamente, ele não permite enviar HTML diferentes para usuários diferentes. Todos os usuários vão receber o mesmo conteúdo. Renderizando dinamicamente baseado nos dados do usuário não é possível com isso.

SSG não permite que você altere o HTML ao longo do tempo, já que todo o código é gerado no tempo de compilação. Para resolver esse problema, Next.js oferece suporte a uma coisa chamada incremental static regeneration (ISR). O que isso faz é permitir que você, manualmente, sob demanda ou periódicamente, regerar uma página estática gerada.

Apesar de ISR existir no antigo Pages Router, ele não está disponível com o novo App Router, pois o seu bastão foi passado para os Server Components.

Revisitando Client Components vs Server Components

Então, agora que sabemos sobre as antigas opções para renderizar páginas no servidor, nós podemos voltar e ver o que Clent e Server Components realmente são. Veja essa imagem, ela mostra uma página web com Client e Server Components de forma alternada.

Uma página consiste em camadas de Client e Server Components

Como mensionado anteriormente no artigo, Server Components permitem a você renderizar componentes individuais puramente no servidor, enquando outros componentes na mesma página permanecem como Clients Componentes no lado do cliente (com Next.js eles são pré-renderizados uma vez no servidor e hidratados no cliente). A imagem acima mostra e exemplifica como isso pode ser. Os componentes em verde são renderizados em HTML no servidor, ao passo que os em azul são renderizados com JavaScript no cliente.

Isso significa que o Next.js permite decidir para cada componente se deve ser pré-renderizado no servidor ou se precisa ser renderizado no lado do cliente. Como vamos ver depois, na seção Renderização Estática vs Dinâmica, o Next.js também irá determinar automáticamente se esses Server Components precisam ser renderisados e tempo de execução ou se precisam ser renderizados antecipadamente em tempo de compilação.

Toc, Toc, quem está aí?

Qual solução de renderização devo usar?

Como vimos, existem muitas opções disponíveis para renderizar aplicações web modernas e, se você usar o Next.js 13, poderá escolher entre todas as opções discutidas anteriormente. Se você iniciar um novo projeto, recomendo usar o novo App Router. Ele está pronto para produção, apesar de outras funcionalidades relacionadas ainda estarem em alfa ou beta.

Para fazer a sua vida mais fácil, nós vamos ver quais soluções de renderização escolher para o Pages Router e para o novo App Router.

Next.js Pages Router

Com o Pages Router, você tem quatro opções de renderização para escolher:

  • Client Side Rendering (CSR)
  • Server Side Rendering (SSR)
  • Static Site Generation (SSG)
  • Incremental Static Regeneration (ISR)

Lembrando que todas essas opções são por página. O comportamento normal é que aplicações usem mais de uma dessas opções. Por exemplo, páginas de informações tal como uma página de "sobre nós" pode geralmente usariam SSG, enquanto outras páginas com dados mais dinâmicos usariam SSR.

Como nós veremos mais tarde no artigo, o desenvolvimento web moderno tende a favorecer renderização no servidor ao invés de no lado do cliente. Por isso CSR só é recomendado se realmente há necessidade disso. Algums casos onde é necessário ou recomendado renderizar a aplicação no lado do cliente são:

  • Quando você precisa usar APIs específicas do browser
  • Quando você precisa da localização em tempo real via API de geolocalização da Web ou IP
  • Quando seus dados dependem de dados armazenados no navegador
  • Quando apps estão se comunicando em uma rede ponto a ponto
  • Quando os dados mudam frequentemente podemos querer manter o carregamendo do lado do cliente para não sobrecarregar o servidor

Na maioria dos outros casos, usar alguma forma de pré-renderização no servidor é recomendado. O objetivo é armazenar em cache o conteúdo gerado o máximo possível. Se o site é completamente estático, SSG é geralmente preferido, se possível.

Se você tem muitas páginas para renderizar em tempo de compilação, ou se as páginas estáticas precisam ser atualizadas ocasionalmente, ISR deve ser um recurso exelente. Com ISR, as construções podem ser geradas em tempo de execução quando você precisa delas e então regeradas manualmente ou definindo um tempo de validação de cache.

Se uma página não é completamente estática e dos dados não mudam com o tempo, mas também dependem de informação autenticada do usuário ou dos cabeçalhos da requisição, SSR ou CSR é provavelmente o que você vai precisar usar em vez disso.

Next.js App Router

Com o App Router nós não temos tantas alternativas. As duas opções principais são Client ou Server Components.

O conceito de renderização estática e dinâmica ainda é relevante quando nós usamos o App Router, mas não é notável. Os detalhes sore isso são um pouco complicados, mas nós vamos discutir na seção Renderização Estática vs Dinâmica.

A parte fácil de entender é quando usamos Server Components. Assim como no Pages Router, SSR é preferido quando usamos o App Router. Isso significa que nós devemos usar Server Components enquanto não temos razões para usar Client Components. É também por isso que Server Components são o padrão no Next.js.

Isso pode soar estranho, mas nos casos em que usamos Client Components são um pouco diferentes de quando usamos CSR no Pages Router. A razão é porque toda a estrutura e design fundamentais é diferente com o App Router, então nós não podemos usar exatamente as mesmas regras.

Com o App Router, você pode seguir uma simples regra: se existe a necessidade de usar o navegador de qualquer forma ou armazenar qualquer estado que mudará o resultado das interações do usuário, então você deve usar um Client Component, caso contrário deve usar um Server Component.

Mais explícitamente, um Client Component vai ser necessário quando:

  • Você precisa de APIs específicas do navegador
  • Você precisa saber a localização real do usuário com alguma API de geolocalização via web ou IP
  • seus dados dependem de dados armazenados no navegador
  • o componente usa um hook de ciclo de vida ou de gerenciamento de estado como useState, useReducer, useEffect ou useContext
  • o componente usa um hook persinalizado que usa ciclo de vida ou gerenciamento de estado
  • os componentes precisam ser interativos, isto é, quando usam listeners onClick ou ouChange em elementos do DOM
  • se você ainda usa React Class Components por qualquer razão estranha

Isso pode parecer demais, mas lembre-se, uma grande parte das aplicações web é normalmente estática e nunca é alterada ou interage. Por exemplo, esse artigo inteiro é estático (no Tabnews não é tão estático assim XD), é apenas textos, imagens e links.

Server Components não são só gerados estáticamente em tempo de construção. Como nós vamos ver depois, você ainda pode buscar (fetch) dados de APIs neles, até com dados não armazenados em cache dinâmicamente. Você pode ler cookies e headers e eles permitem você ler dados sensíveis no servidor e evitar o envio de respostas enormes e dependências de JavaScript para o cliente.

Não se preocupe, o servidor incluiu instruções em assembly, estilo Ikea

Carregando publicação patrocinada...
1

Creio que esse post tenha vindo no tempo certo. Recentemente comecei a ver tecnologias que envolvem essas questões de Client e Server rendering, principalmente com NextJS.

Com certeza vou saber um pouquinho mais o que vou estar fazendo na decisão do método de renderização.

0

Renderização Estática vs Dinâmica

Como revelado anteriormente, Server Components podem ser renderizados tanto em tempo de construção (estático) quanto em tempo de execução quando uma requisição chega (dinâmico). Isso é apenas o que você deve saver, mas que, infelizmente, tem muitos "ses" e "poréns".

Next.js faz uma tentativa de gerenciar isso automáticamente para você. O que eles fazem é renderizar de forma estática por padrão e automáticamente ativar a renderização dinâmica quando necessário ou quando você configurar. A renderização dinâmica será usada quando:

Eu tenho certeza que você lerá esses links para entender isso, esse artigo já está longo o suficiente sem isso. Uma coisa que você deve anotar, é que o comportamento difere quando você usa as funções nativas do Next.js para busca (fetch) de dados, cookies, headers e parâmetros de busca, em comparação com quando usa soluções próprias ou bibliotecas externas.

O Next.js não irá saber quando seu componente precisa ser dinâmico se você não usar as suas próprias features. Nesses casos, vocẽ deve configurar manualmente o comportamento de cache.

Prós e Contras com renderização no servidor

Como prometido há um tempo ao longo do artigo, nós vamos agora ver os prós e contras de renderização no lado do servidor. SSR tem muitos benefícios e poucos malefícios. As vantages podem vairar ligeiramente dependendo do tipo de renderização no servidor escolhido. Note que as vantagens de SSG podem ser diferentes das de SSR. Esses prós e contras são, em termos gerais, para conteúdos renderizados no lado do servidor.

Vantagens de renderizar dados no lado do servidor

Desvantagens de Renderizar dados no lado do servidor

  • Renderizando conteúdos nos servidores leva a uma carga maior, que resulta em despesas maiores com servidores
  • Servidores geralmente tem pouco suporte para bibliotecas de terceiros
  • Você não pode acessar funcionalidades do navegador, a localização do usuário, dispositivo e etc em um servidor.
  • O tempo de carregamento para navegação pode ser lento se os dados não são reutilizados e cada navegação resulta em uma página completamente nova (Essa desvantagem era um problema maior com soluções tradicionais de renderização no lado do servidor onde o conteúdo renderizado era raramente reutilizado).

Server components vêm com benefícios adicionais

Quando se trata de React Server Components, todos os prós e contras acima listados para SSR são aplicados, mas Server Components também tem algumas vantagens adicionais.

Um detalhe interessante é que todo Server Components já é pré-renderizado quando o cliente recebe uma aplicação. Isso significa que Server Components renderizados condicionalmente podem ser renderizados instantâneamente, mesmo quando dependem de dados da rede. Não é necessário esperar uma resposta da rede e gerenciar o estado de carregamento, mesmo nos casos onde o componente é renderizado condicionalmente em resposta a uma ação do usuário.

Lendo isso você deve estar preocupado com o tamanho do bundle. Mas as suas preocupações são injustificadas, pois código HTML não tem um grande impacto no tempo de carregamento. HTML é armazenável em cache, mais rápido para analisar (parse) e rodar que JavaScript e só uma fração do tamanho de imagens.

E como cereja do bolo, Server Components adicionam tamanho zero de bundle para dependências de JavaScript! Mesmo se você usar uma biblioteca não otimizada para remoção de código não utilizado (tree-shacking) de 250 kB, o código HTML resultante ainda incluirá 0 kB de JavaScript.

Server Components não são perfeitos

Que Server Components são incríveis todos estão de acordo, certo? A resposta é não. Existem algumas potenciais desvantages incovenientes.

Server Components precisam de novos conhecimentos. A migração do velho Pages Router para o novo App Router vem com uma completa nova forma de pensar que a maioria dos desenvolvedores não estão acostumados.

Não apenas o conhecimento dos desenvolvedores torna-se obsoleto, o código também. Apesar das novas versões do Next.js estarem totalmente compatíveis com o antigo Pages Router, os código que o usam vão virar código legado, assim como os antigos Class Components do React.

Algumas outras desvantagens também existem em relação à qualidade de código. Compartilhar código torna-se mais difícil quando a renderização é dividida ainda mais em renderização no cliente e no servidor. Código marcado com use client e a importanção de recursos exclusivos de servidor tornam mais trabalhoso aplicar DRY ao código.

Eu devo admitir também, apesar de opinativo, que a prop drilling dos Server Components não é a melhor solução em termos de legibilidade. No Next.js, Server Components não podem ser importados em um Client Component, o que significa que Server Components renderizados em Client Components devem ser passados como children e renderizados dessa forma. Isso funciona e não é novo, mas pode ser um pouco complicado de se adaptar.

Conclusão

A web começou com HTML recebido de um servidor com muito pouco JavaScript. O tempo passou e depois de várias voltas e quatro diferentes soluções, como single page applications (SPAs), server side rendering (SSR) e static site generation (SSG), o React agora evoluiu com o uso dos Server Components.

O Next.js oferece o Pages Router como legado que usa as velhas opções de renderização juntas com uma estratégia de geração estática incremental (ISR). Com o advento dos Server Components, ele agora oferece o novo App Router que permite otimizar a renderização a nível de componente com os Server Components.

Entre todos os benefícios dos Server Components, nós temos o pequeno tamanho de bandle, rápido tempo de carregamento das páginas, ótima compatibilidade com SEO e suporte de navegadores, melhoras de UX e a possibilidade de usar dados sensíveis no servidor. Além disso, podemos obter renderização instantânea para componentes renderizados condicionalmente, sem a necessidade de exibir qualquer spinner ou skeleton para indicar carregamento.

1
0