O melhor dos dois mundos: SSR com JavaScript isomórfico

renderização do lado do servidor, ou SSR, é uma frase que você ouve frequentemente na comunidade de desenvolvimento frontend.

no nível mais básico, a renderização do lado do servidor é exatamente o que descreve: renderizar aplicativos no servidor. Você navega para um site, ele faz uma solicitação para o servidor, ele renderiza algum HTML e obtém o resultado totalmente renderizado de volta em seu navegador. Bastante simples. Você pode estar se perguntando Por que a comunidade ainda tem uma palavra da moda para isso.

antes do surgimento de aplicativos da web ricos e dinâmicos que dependiam fortemente de JavaScript e jQuery, essencialmente todos os aplicativos da web eram renderizados pelo servidor. PHP, WordPress e até mesmo sites HTML básicos são exemplos disso.

quando você visita uma página em um desses sites, você recebe de volta todos os dados HTML e tudo. Se você clicar em um link, o navegador fará outra solicitação ao servidor. Após a resposta, o navegador atualizará e renderizará a próxima página do zero. Esta abordagem funciona bem, e tem por anos; os navegadores são espetacularmente rápidos na renderização de HTML estático. O que mudou?

desde a virada do século, o uso de JavaScript passou de uma pequena pitada aqui e ali para a interatividade da página da web para a linguagem indiscutível de escolha na web. Estamos constantemente enviando mais lógica e JavaScript para o navegador.

estruturas de página única como React e Vue inauguraram esta nova era de aplicativos da web dinâmicos, complexos e orientados a dados renderizados por clientes. Esses SPAs diferem dos aplicativos renderizados pelo servidor porque não buscam conteúdo totalmente renderizado completo com dados do servidor antes de renderizar na tela.

aplicativos renderizados do lado do cliente renderizam seu conteúdo no navegador usando JavaScript. Em vez de buscar todo o conteúdo do servidor, eles simplesmente buscam uma página HTML barebones sem conteúdo corporal e renderizam todo o conteúdo dentro usando JavaScript.

o benefício disso é que você evita as atualizações de página inteira que acontecem com aplicativos totalmente renderizados pelo servidor, o que pode ser um pouco chocante para o usuário. Aplicativos renderizados por cliente de página única atualizarão o conteúdo em sua tela, buscarão dados de APIs e atualizarão bem na sua frente sem qualquer tipo de atualização de página. Essa característica é o que faz com que os aplicativos da web modernos se sintam rápidos e “nativos” à medida que você interage com eles.

trade-offs de renderização do lado do cliente

não é tudo Sol e arco-íris no mundo Spa renderizado do lado do cliente. Existem alguns trade-offs que vêm com a renderização de seu aplicativo no lado do cliente. Dois exemplos principais são SEO e desempenho de carga inicial.

SEO

Desde que o cliente prestados apps retornar um bare-bones página HTML com conteúdo muito pouco antes de JavaScript chutes e deixa o resto, pode ser difícil para os rastreadores de mecanismo de pesquisa para entender a estrutura HTML da sua página, o que é prejudicial para os rankings de busca do seu site. O Google tem feito um monte de bom trabalho em torno deste, mas ainda é recomendado para evitar renderização do lado do cliente se SEO é particularmente importante.

carga Inicial de desempenho

Com o cliente-renderizados apps, você geralmente vê o seguinte, as coisas acontecem quando você abrir a página:

  • O app carrega algum HTML básico, como um aplicativo de shell ou estático de barra de navegação
  • Você verá um indicador de carregamento de algum tipo
  • o Seu conteúdo é, então, processado

O problema com isso é que o aplicativo não mostra nada até que o JavaScript carrega totalmente a partir da rede e terminar a renderização de elementos na tela.

Em resumo, o problema do lado do cliente o desempenho em geral é que você não pode controlar o que o dispositivo de cliente que alguém usa sua aplicação — independentemente de seu estado-de-o-arte smartphone, o efeito poderoso computador da área de trabalho, ou de us $100 inferior-end de smartphones.

no entanto, controlamos o servidor. Quase sempre podemos dar ao nosso servidor mais CPU e memória e ajustá-lo para torná-lo melhor para nossos usuários.

o melhor dos dois mundos

podemos ter o melhor dos dois mundos ao usar renderização do lado do servidor com tecnologias de frontend modernas. A maneira como isso geralmente funciona é que o servidor renderiza e envia de volta o aplicativo totalmente renderizado na primeira carga. O próximo passo, conhecido como hidratação, é onde seu pacote JavaScript será baixado e executado. Isso anexa manipuladores de eventos e Fios coisas como seu roteador do lado do cliente.

com esta abordagem, você obtém todos os benefícios do SSR na carga inicial, então cada interação desse ponto em diante será tratada pelo JavaScript do lado do cliente. Isso fornece uma carga inicial rápida e amigável ao SEO, seguida pela experiência dinâmica de aplicativo da web de página única que conhecemos e amamos.

aplicativos como este são conhecidos como aplicativos universais porque o mesmo JavaScript é executado no cliente e no servidor. Você também pode ouvir o termo mais sofisticado “isomórfico” sendo usado, o que significa exatamente a mesma coisa.

Tutorial: implementar SSR

SSR também não é isento de trade-offs. Ele adiciona sobrecarga ao seu desenvolvimento, introduzindo uma configuração mais complexa, além de ter que hospedar e gerenciar seu próprio servidor. Esses problemas são o motivo pelo qual estruturas incríveis como Next.js e Razzle são muito populares: eles abstraem a parte de configuração SSR e permitem que você se concentre em escrever o código da interface do Usuário.

neste tutorial, não vamos usar nenhuma estrutura SSR. A melhor maneira de aprender como algo funciona é construindo-o, então vamos aprender como criar a configuração SSR mais simples que pudermos que fornecerá:

  • Global CDN
  • Totalmente funcional API de back-end
  • Não há servidores ou de infra-estrutura para gerenciar
  • Único comando de implantação

Vamos implantar um servidor universal-renderizados Reagir aplicativo criado com o criar-reagir-app na Amazon Web Services (AWS). Você não precisa ter experiência com a AWS para acompanhar.

nossas ferramentas

para construir nosso aplicativo, usaremos alguns serviços diferentes da AWS.

  • AWS Amplify: Um alto nível framework para o gerenciamento de serviços da AWS, principalmente para celular e desenvolvimento web
  • AWS Lambda: Executar o código na nuvem, sem o gerenciamento de servidores
  • AWS Cloudfront (CDN): UMA rede de entrega de conteúdo responsável pela entrega e colocação em cache de conteúdo em todo o mundo
  • AWS Simple Storage Service (S3): Onde vamos guardar nosso estático ativos (JS, CSS, etc.)

Diagrama de arquitetura

nossa função Lambda é responsável pela renderização do servidor de nosso aplicativo React. Usaremos o S3 para armazenar nosso conteúdo estático e CDN do Cloudfront para atendê-lo. Você não precisa ter nenhum conhecimento prévio desses serviços, pois o AWS Amplify tornará super simples criá-los.

Nosso Diagrama de Arquitetura

Nosso Diagrama de Arquitetura

Construir nossa aplicação

Primeiro de tudo, você precisa para instalar o AWS Ampliar o clip e criar uma conta da AWS se você não tiver já. Você pode fazer isso seguindo este breve guia.

configuração do projeto

agora que o Amplify está configurado, podemos começar a configurar nosso projeto React. Vamos usar o fantástico create-react-app para nos ajudar. Supondo que você tenha nó.JS e npm instalados, podemos executar:

npx create-react-app amplify-ssrcd amplify-ssr yarn add aws-amplify amplify init

Selecione as opções padrão no Assistente do AWS Amplify.

nosso projeto React agora está inicializado com Amplify e pronto para adicionarmos nosso “servidor” para SSR. Fazemos isso executando amplify add api e respondendo a algumas perguntas:

$ amplify add api? Please select from one of the below mentioned services: REST? Provide a friendly name for your resource to be used as a label for this category in the project: amplifyssr? Provide a path (e.g., /items): /ssr? Choose a Lambda source: Create a new Lambda function? Provide a friendly name for your resource to be used as a label for this category in the project: amplifyssr? Provide the AWS Lambda function name: ssr? Choose the function runtime that you want to use: NodeJS? Choose the function template that you want to use: Serverless expressJS function? Do you want to access other resources created in this project from your Lambda function? N? Do you want to edit the local lambda function now? N? Restrict API access: N? Do you want to add another path? N

isso criará os modelos, diretórios e códigos relevantes necessários para nossa infraestrutura e back-end da AWS: uma função do AWS Lambda que executará um pequeno servidor Express responsável por renderizar nosso aplicativo React.

Antes de implantarmos nossa infraestrutura, há algumas mudanças que precisamos fazer dentro de nosso aplicativo React para prepará-lo para a renderização do lado do servidor. Abra src/App.js(o componente principal do aplicativo para seu aplicativo React) e cole o seguinte:

import React from 'react';function App() { return ( <div className="App"> <header className="App-header"> Server Rendered React App </header> </div> );}export default App;

em seguida, precisamos criar um script que renderizará nosso aplicativo React no lado do servidor. Isso é feito com a função renderToString no Pacote react-dom/server. Esta função é responsável por pegar nosso componente <App /> e renderizá-lo no lado do servidor como uma string, pronto para ser retornado como HTML totalmente renderizado para o cliente.

crie um arquivo em src/render.js com o seguinte código:

import React from "react";import { renderToString } from "react-dom/server";import App from "./App";export default () => renderToString(<App />);

ótimo-nosso aplicativo React do lado do cliente tem todo o código que precisa ser renderizado no lado do servidor. Isso significa que agora devemos codificar o endpoint do lado do servidor que renderizará nosso aplicativo React.

temos um problema — no entanto-precisamos da função src/render e do nosso código de componente <App /> para ser executado no lado do servidor. O servidor não sabe nada sobre os módulos React ou mesmo ES por padrão. Por esse motivo, vamos transpilar o código do aplicativo React usando o Babel para o lado do servidor.

para fazer isso, vamos instalar algumas dependências Babel em nosso projeto.

yarn add --dev @babel/core @babel/cli @babel/preset-react @babel/preset-env

em seguida, crie um .babelrc na raiz do seu projeto. Este arquivo é usado para configurar o Babel e dizer quais plugins/predefinições usar.

{ "presets":}

finalmente, vamos atualizar nosso package.json para transpilar nosso código como parte da etapa de compilação. Isso transpilará os arquivos para o diretório amplify/backend/function/amplifyssr/src/client, que é onde armazenaremos todo o JavaScript universal que precisa ser executado no lado do cliente, bem como o servidor para SSR.

 "scripts": { "start": "react-scripts start", "transpile": "babel src --out-dir amplify/backend/function/amplifyssr/src/client --copy-files", "build": "npm run transpile && react-scripts build && npm run copy", "copy": "cp build/index.html amplify/backend/function/amplifyssr/src/client", "test": "react-scripts test", "eject": "react-scripts eject" },

renderizar o aplicativo no Lambda

a configuração de compilação está concluída! Vamos pular para amplify/backend/function/amplifyssr/src e instalar react e react-dom, pois ambos serão necessários para que o Lambda execute SSR.

yarn add react react-dom

agora para configurar nosso servidor expresso, que será executado no Lambda. A função Lambda foi gerada automaticamente para nós quando completamos a etapa amplify add api anteriormente e escolhemos uma API REST e ExpressJS.

Amplify já configurou o servidor Express para que possamos executar no Lambda, então tudo o que precisamos fazer agora é adicionar um endpoint ao servidor-renderizar nosso aplicativo React quando alguém acessar o URL da API no navegador. Atualize seu arquivo amplify/backend/function/amplifyssr/src/app.js para conter o seguinte código:

/* Amplify Params - DO NOT EDIT ENV REGIONAmplify Params - DO NOT EDIT */const express = require('express')const bodyParser = require('body-parser')const awsServerlessExpressMiddleware = require('aws-serverless-express/middleware')const fs = require('fs');const render = require('./client/render').default;// declare a new express appconst app = express()app.use(bodyParser.json())app.use(awsServerlessExpressMiddleware.eventContext())// Enable CORS for all methodsapp.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*") res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept") next()});app.get('*', function(req, res) { // Read the index.html file from the create-react-app build const html = fs.readFileSync("./client/index.html", "utf-8"); // Server side render the react application const markup = render(); // Replace the empty body of index.html with the fully server rendered react application and send it back to the client res.send(html.replace(`<div></div>`, `<div>${markup}</div>`))});module.exports = app

nosso servidor expresso agora está pronto para SSR e podemos implantar nosso aplicativo React.

hospedagem e retoques finais

assim que recebermos o HTML renderizado pelo servidor da renderização inicial do nosso aplicativo, buscaremos o pacote JavaScript do lado do cliente para assumir a partir daí e nos dar um SPA totalmente interativo.

precisamos de algum lugar para hospedar nosso JavaScript do lado do cliente e arquivos estáticos. Na AWS, o serviço geralmente usado para isso é o S3 (Simple Storage Service), um armazenamento de objetos em nuvem massivamente escalável.

também vamos colocar um CDN na frente dele para cache global e desempenho. Com o Amplify, podemos criar esses dois recursos para o nosso projeto executando alguns comandos do diretório raiz do nosso projeto:

$ amplify add hostingSelect the plugin module to execute Amazon CloudFront and S3? Select the environment setup: PROD (S3 with CloudFront using HTTPS)? hosting bucket name (name your bucket or use the default)

agora você pode implantar toda a infraestrutura, incluindo a função Lambda do servidor expresso, o bucket S3 e o CDN, executando o comando amplify publish.

a saída do console mostrará todos os recursos relevantes de seus modelos criados para você pelo Amplify. Observe que a criação de um CDN do Cloudfront pode demorar um pouco, portanto, seja paciente. Depois que seus recursos forem criados, o URL do Cloudfront CDN será exibido no terminal.

Publish started for S3AndCloudFront✔ Uploaded files successfully.Your app is published successfully.https://d3gdcgc9a6lz30.cloudfront.net

a última coisa que precisamos fazer é dizer ao React de onde buscar nosso pacote do lado do cliente depois que o aplicativo é renderizado pelo servidor. Isso é feito em create-react-app usando a variável de ambiente PUBLIC_URL. Vamos atualizar nosso aplicativo React package.json scripts novamente para se parecer com o seguinte:

 "scripts": { "start": "react-scripts start", "transpile": "babel src --out-dir amplify/backend/function/amplifyssr/src/client --copy-files", "build": "npm run transpile && PUBLIC_URL=<your-cloudfront-url> react-scripts build && npm run copy", "copy": "cp build/index.html amplify/backend/function/amplifyssr/src/client", "test": "react-scripts test", "eject": "react-scripts eject" },

reconstrua e implante seu aplicativo na AWS com essa configuração atualizada.

amplify publish

agora devemos ter um aplicativo React totalmente renderizado do lado do servidor em execução na AWS!

executando nosso aplicativo

seu URL da API SSR pode ser encontrado em amplify/backend/amplify-meta.json. Procure o RootUrl em seu arquivo JSON e você deve ver o URL no qual você pode visitar seu novo aplicativo renderizado pelo servidor. Deve ser algo como o seguinte:

"output": { "ApiName": "amplifyssr", "RootUrl": "https://g6nfj3bvsg.execute-api.eu-west-1.amazonaws.com/dev", "ApiId": "g6nfj3bvsg"}, 

visite o URL do API Gateway em seu navegador em <your-api-url>/ssr e você verá seu novo aplicativo React renderizado pelo servidor! Se você mergulhar na guia Rede em seu navegador de escolha e visualizar as solicitações, notará que a solicitação para /ssr tem uma resposta HTML totalmente renderizada com nosso aplicativo React renderizado dentro do <body> do documento.

<div> <div class="App" data-reactroot=""> <header class="App-header">Server Rendered React App</header> </div></div>

você também notará as solicitações feitas no URL do Cloudfront do navegador para carregar o JavaScript do lado do cliente que assumirá a renderização a partir daqui, dando-nos o melhor dos mundos de renderização do lado do cliente e do lado do servidor.

para onde ir a partir daqui

este tutorial destina-se a colocá-lo em funcionamento com renderização do lado do servidor o mais rápido possível, sem se preocupar em Gerenciar infraestrutura, CDNs e muito mais. Tendo usado a abordagem serverless, existem algumas melhorias agradáveis que podemos fazer para a nossa configuração.

simultaneidade provisionada

uma maneira pela qual o AWS Lambda é capaz de permanecer extremamente de baixo custo é que as funções Lambda que não foram atingidas em um tempo ficarão “ociosas.”Isso significa essencialmente que, quando os executarmos novamente, haverá o que é conhecido como “arranque a frio” — um atraso de inicialização que deve acontecer antes que o Lambda responda.

depois disso, o lambda é então” quente ” novamente por um período de tempo e responderá às solicitações subsequentes rapidamente até o próximo longo período ocioso. Isso pode causar tempos de resposta ligeiramente não confiáveis.

apesar de ser “sem servidor”, o Lambda usa contêineres leves para processar quaisquer solicitações. Cada contêiner pode processar apenas uma solicitação a qualquer momento. Além do problema de inicialização a frio após um período ocioso, o mesmo também é verdadeiro quando muitas solicitações simultâneas atingem a mesma função Lambda, fazendo com que mais contêineres ou trabalhadores simultâneos sejam iniciados a frio antes de responder.No passado, muitos engenheiros resolveram esse problema escrevendo scripts para fazer ping no Lambda periodicamente para mantê-lo aquecido. Agora existe uma maneira nativa da AWS muito melhor de resolver isso e é conhecida como simultaneidade provisionada.

com simultaneidade provisionada, você pode solicitar facilmente um determinado número de contêineres dedicados para ficar aquecido para uma função Lambda específica. Isso lhe dará um tempo de resposta SSR muito mais consistente em tempos de carga alta e esporádica.

versões Lambda

você pode criar várias versões Lambda para suas funções e dividir o tráfego entre elas. Isso é muito poderoso em nosso aplicativo SSR, pois nos permite fazer atualizações no lado Lambda e a/B testá-las com uma parcela menor de usuários.

você pode publicar várias versões do seu Lambda e dividir o tráfego entre elas em pesos que você especificar. Por exemplo, você pode querer renderizar um banner CTA para alguns usuários para medir o engajamento, mas não renderizá-lo para outros. Você pode fazer isso com versões Lambda.

Full-stack web application

conforme explicado anteriormente, o AWS Amplify já cria uma API REST e um servidor expresso para nós, no qual criamos um endpoint para renderizar nosso aplicativo React. Sempre podemos adicionar mais código e endpoints a este servidor expresso em amplify/backend/function/amplifyssr/src/app.js, permitindo-nos transformar nosso aplicativo em um aplicativo da web de pilha completa, completo com banco de dados, autenticação e muito mais.

você pode usar o fantástico conjunto de ferramentas do AWS Amplify para criar esses recursos ou conectar — se à sua própria infraestrutura-mesmo que não esteja hospedado na AWS. Você pode tratar seu back-end do AWS Lambda como qualquer outro servidor expresso e construir sobre ele.

você já tem todo o seu pipeline de implantação configurado executando amplify publish para que você possa se concentrar em escrever código. O ponto de partida neste tutorial dá-lhe total flexibilidade para fazer o que quiser a partir daqui.

conclusão

a renderização do lado do servidor não precisa ser difícil. Podemos usar ferramentas totalmente gerenciadas como Next ou Razzle, que são incríveis por direito próprio, mas para muitas equipes isso pode ser uma mudança de paradigma muito grande, dado seu código ou requisitos existentes. Usar uma abordagem simples e de baixa manutenção pode facilitar a vida, especialmente se você já estiver usando a AWS ou o Amplify para seu projeto.

SSR pode adicionar uma tonelada de valor para suas aplicações web e fornecer um desempenho muito necessário ou impulso SEO. Temos a sorte na comunidade de desenvolvimento web de ter ferramentas que podem criar CDNs, back-ends sem servidor e aplicativos da web totalmente hospedados com alguns comandos ou cliques.

mesmo que você não ache que precisa de SSR, é um tópico muito prevalente e comum no ecossistema JavaScript. Ter uma compreensão de seus benefícios e trade-offs será útil para quase qualquer pessoa envolvida na esfera do desenvolvimento web.

espero que você tenha aprendido algo hoje-obrigado por ler! Sinta-se à vontade para entrar em contato comigo ou me seguir no Twitter, onde eu tweet E blog sobre JavaScript, Python, AWS, automação e desenvolvimento sem código.

visibilidade total dos aplicativos react de produção

depurar aplicativos React pode ser difícil, especialmente quando os usuários enfrentam problemas difíceis de reproduzir. Se você estiver interessado em monitorar e rastrear o estado Redux, detectar automaticamente erros de JavaScript e rastrear solicitações de rede lentas e tempo de carregamento de componentes, tente LogRocket. LogRocket Dashboard Free Trial Banner

LogRocket é como um DVR para aplicativos da web, gravando literalmente tudo o que acontece em seu aplicativo React. Em vez de adivinhar por que os problemas acontecem, você pode agregar e relatar em que estado seu aplicativo estava quando ocorreu um problema. O LogRocket também monitora o desempenho do seu aplicativo, relatórios com métricas como carga da CPU do cliente, uso da memória do cliente e muito mais.

o pacote de middleware LogRocket Redux adiciona uma camada extra de visibilidade em suas sessões de usuário. LogRocket registra todas as ações e estado de suas lojas Redux. Modernize como você depura seus aplicativos React-comece a monitorar gratuitamente.

Deixe uma resposta

O seu endereço de email não será publicado.