Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Server Components - Front End Day Fortaleza 14/10/2023

Server Components - Front End Day Fortaleza 14/10/2023

Lucas Correia

October 14, 2023
Tweet

More Decks by Lucas Correia

Other Decks in Programming

Transcript

  1. Quem sou eu • Frontend Senior na Chili Piper •

    6+ anos de experiência com Frontend e React • React Native • AngularJS & Ionic • Node • Typescript é vida Pro f issional CP Frontend Meetup 
 React Summit - AMS
  2. Quem sou eu • Entusiasta de astronomia e computação quântica

    • Moro com 1 cachorro e 5 gatos • Não gosto de café (desculpa) Pessoal
  3. Sobre a talk • Convencer de que RSC é diferente

    de PHP • Ajudar a diferenciar SSR de RSC • Repassar como streaming e hydration funcionam • Repassar o basico de RSC Objetivos
  4. Overview • Navegador (Client) faz uma requisição para o servidor

    (Server) • Server responde com o arquivo index.html • Client exibe o arquivo para o usuário HTTP & index.html
  5. Overview • Depois que o HTML é baixado, o Javascript

    é responsável por atualizar o conteúdo da página em tempo real • Quando usuário clicar em um botão, então atualize a lista Javascript
  6. Overview • Com o tempo, ferramentas que agrupam pedaços de

    código foram nascendo • React é uma delas • Componentes são pedaços de código que representam um item (ou conjunto de itens) na sua tela React
  7. SSR vs CSR • Server envia arquivo HTML vazio com

    referência para arquivo JS • Browser baixa o arquivo JS • Browser executa o arquivo • React transforma o HTML vazio na nossa página Client Side Rendering Fronte: https://medium.com/walmartglobaltech/the-bene f its-of- server-side-rendering-over-client-side-rendering-5d07 ff 2cefe8
  8. SSR vs CSR • Server pre-renderiza a nossa página e

    envia o HTML resultante para o browser • Browser exibe o HTML para o usuário • Browser baixa o arquivo JS • Browser executa o arquivo JS • Hydration acontece, página agora é interativa Server Side Rendering Fronte: https://medium.com/walmartglobaltech/the-bene f its-of- server-side-rendering-over-client-side-rendering-5d07 ff 2cefe8
  9. Subindo o nível FRONT END DAY FORTALEZA A partir daqui:

    Se você é iniciante e não acompanhar, tá tudo bem
  10. Hydration • Basicamente rerenderiza a aplicação no client, mas não

    substitui os nodes no DOM • Adiciona event listeners aos nodes já existentes no DOM • Finalmente, assume a renderização como se fosse uma aplicação client-side Overview Fronte: https://www.patterns.dev/posts/progressive-hydration
  11. Hydration • A função "hydrateRoot" do React mapeia os seus

    componentes para o HTML que foi renderizado no servidor • O HTML renderizado no servidor precisa ser o mesmo renderizado no client Mapeando components para HTML
  12. Streaming • E se o server pudesse atualizar o HTML

    enviado pro client em tempo real? • Caso uma request seja feita no servidor, um estado de loading será enviado para o client • Quando a request resolver, o conteúdo f inal será enviado Overview
  13. Streaming Leitura/escrita de dados em “chunks" (pedaços) NodeJS Streams const

    Stream = require("stream"); const readableStream = new Stream.Readable({ read() {}, }); readableStream.on("data", (chunk) => { console.log(chunk.toString()); }); setTimeout(() => readableStream.push("Oi"), 1000); setTimeout(() => readableStream.push(“Oi"), 2000); setTimeout(() => readableStream.push("Tchau"), 3000);
  14. Streaming Pode ser retornado em uma request HTTP NodeJS Streams

    const Stream = require("stream"); const readableStream = new Stream.Readable({ read() {}, }); readableStream.on("data", (chunk) => { console.log(chunk.toString()); }); setTimeout(() => readableStream.push("Oi"), 1000); setTimeout(() => readableStream.push(“Oi"), 2000); setTimeout(() => readableStream.push("Tchau"), 3000);
  15. Streaming Pode ser retornado em uma request HTTP NodeJS Streams

    const readableStream = new Stream.Readable({ read() {}, }); setTimeout(() => readableStream.push("Oi"), 1000); setTimeout(() => readableStream.push(“Oi"), 2000); setTimeout(() => readableStream.push("Tchau"), 3000);
  16. Streaming Pode ser retornado em uma request HTTP NodeJS Streams

    app.get("/", (_, res) => { res.writeHead(200, { "Content-Type": "text/html; charset=utf-8", }); const readableStream = new Stream.Readable({ read() {}, }); readableStream.pipe(res); readableStream.push("<!DOCTYPE html><html><body>”); setTimeout(() => readableStream.push("Oi"), 1000); setTimeout(() => readableStream.push("Oi2"), 2000); setTimeout(() => { readableStream.push("Tchau"); readableStream.push("</body></html>"); res.end(); }, 3000); });
  17. Streaming Mas ainda falta algo… NodeJS Streams app.get("/", (_, res)

    => { res.writeHead(200, { "Content-Type": "text/html; charset=utf-8", }); const readableStream = new Stream.Readable({ read() {}, }); readableStream.pipe(res); readableStream.push("<!DOCTYPE html><html><body>”); setTimeout(() => readableStream.push("Oi"), 1000); setTimeout(() => readableStream.push("Oi2"), 2000); setTimeout(() => { readableStream.push("Tchau"); readableStream.push("</body></html>"); res.end(); }, 3000); });
  18. Streaming Mas ainda falta algo… NodeJS Streams app.get("/", (_, res)

    => { res.writeHead(200, { "Content-Type": "text/html; charset=utf-8", }); const readableStream = new Stream.Readable({ read() {}, }); readableStream.pipe(res); readableStream.push("<!DOCTYPE html><html><body>"); setTimeout(() => readableStream.push("Oi"), 1000); setTimeout(() => { readableStream.push("<script>document.body.innerHTML = ‘';</script>"); readableStream.push("Oi2"); }, 2000); setTimeout(() => { readableStream.push("<script>document.body.innerHTML = ‘';</script>"); readableStream.push("Tchau"); readableStream.push("</body></html>"); res.end(); }, 3000); });
  19. Streaming React expõe a função renderToPipeableStream, que envia os rerenders

    que acontecem no servidor para o client em chunks renderToPipeableStream import { renderToPipeableStream } from "react-dom/server"; const { pipe } = renderToPipeableStream(<App />, { bootstrapScripts: ["/main.js"], onShellReady() { response.setHeader("content-type", "text/html"); pipe(response); }, });
  20. O client pode ser pre- renderizado no server FRONT END

    DAY FORTALEZA Então a camada de Client acaba rodando no server e no browser
  21. Comunicação através de endpoints FRONT END DAY FORTALEZA O server

    funciona como uma mistura de gateway e router
  22. Server Components • Por padrão, toda página é um Server

    Components • Server Components podem ser async • Somente o HTML renderizado é enviado para o browser Server import React from 'react' async function fetchName() { return 'Lucas' } export default async function Page() { const name = await fetchName() return <span>{name}</span> }
  23. import React from 'react' async function fetchName() { return 'Lucas'

    } export default async function Page() { const name = await fetchName() return <span>{name}</span> }
  24. import React from 'react' async function fetchName() { return 'Lucas'

    } export default async function Page() { const [name, setName] = React.useState(await fetchName()) function handleChange(e) { setName(e.target.value) } return ( <> <span>{name}</span> <input value={name} onChange={handleChange}/> </> ) }
  25. import React from 'react' async function fetchName() { return 'Lucas'

    } export default async function Page() { const [name, setName] = React.useState(await fetchName()) function handleChange(e) { setName(e.target.value) } return ( <> <span>{name}</span> <input value={name} onChange={handleChange}/> </> ) }
  26. Código vai pro client Código f ica no server import

    View from './View' async function fetchName() { return 'Lucas' } export default async function Page() { const name = await fetchName() return <View name={name} /> } import React from 'react' export default async function View({ name: serverName }) { const [name, setName] = React.useState(serverName) function handleChange(e) { setName(e.target.value) } return ( <> <span>{name}</span> <input value={name} onChange={handleChange} /> </> ) }
  27. Código vai pro client Código f ica no server import

    View from './View' async function fetchName() { return 'Lucas' } export default async function Page() { const name = await fetchName() return <View name={name} /> } 'use client' import React from 'react' export default async function View({ name: serverName }) { const [name, setName] = React.useState(serverName) function handleChange(e) { setName(e.target.value) } return ( <> <span>{name}</span> <input value={name} onChange={handleChange} /> </> ) }
  28. import View from './View' async function fetchName() { return 'Lucas'

    } export default async function Page() { const name = await fetchName() return <View name={name} /> } 'use client' import React from 'react' export default async function View({ name: serverName }) { const [name, setName] = React.useState(serverName) function handleChange(e) { setName(e.target.value) } return ( <> <span>{name}</span> <input value={name} onChange={handleChange} /> </> ) }
  29. import View from './View' async function fetchName() { return 'Lucas'

    } async function AnotherServerComponent() { const name = await fetchName() return <span>{name}</span> } export default async function Page() { const name = await fetchName() return ( <View name={name}> <AnotherServerComponent /> </View> ) } 'use client' import React from 'react' export default async function View({ name: serverName, children }) { const [name, setName] = React.useState(serverName) function handleChange(e) { setName(e.target.value) } return ( <> {children} <span>{name}</span> <input value={name} onChange={handleChange} /> </> ) }
  30. Não é sobre gerar o HTML no server FRONT END

    DAY FORTALEZA É sobre remover do client tudo que não for interativo
  31. import View from './View' async function fetchName() { return 'Lucas'

    } export default async function Page() { const name = await fetchName() return <View name={name} /> } 'use client' import React from 'react' export default async function View({ name: serverName }) { const [name, setName] = React.useState(serverName) function handleChange(e) { setName(e.target.value) } return ( <> <span>{name}</span> <input value={name} onChange={handleChange} /> </> ) }
  32. import View from './View' export default async function Page() {

    async function generateFullName(name) { 'use server' return `${name} Correia` } return ( <View generateFullName={generateFullName} /> ) } 'use client' import React from 'react' export default async function View({ name: serverName }) { const [name, setName] = React.useState(serverName) function handleChange(e) { setName(e.target.value) } return ( <> <span>{name}</span> <input value={name} onChange={handleChange} /> </> ) }
  33. import View from './View' export default async function Page() {

    async function generateFullName(name) { 'use server' return `${name} Correia` } return ( <View generateFullName={generateFullName} /> ) } 'use client' import React from 'react' export default async function View({ generateFullName }) { const [fullName, setFullName] = React.useState('') // debounce pls async function handleChange(e) { const newFullName = await generateFullName(e.target.value) setFullName(newFullName) } return ( <> <span>{fullName}</span> <input onChange={handleChange} /> </> ) }
  34. import View from './View' export default async function Page() {

    async function generateFullName(name) { 'use server' return `${name} Correia` } return <View generateFullName={generateFullName} /> }
  35. Server Actions • Funções não podem ser passadas como props

    para um Client Component • Server Actions é a exceção, sendo necessário o uso da diretiva "use server” Action import View from './View' export default async function Page() { async function generateFullName(name) { 'use server' return `${name} Correia` } return <View generateFullName={generateFullName} /> }
  36. Server Actions • Server Actions não precisam ser passadas como

    props. Podem ser exportadas/ importadas diretamente • Se passada para um form, será executada mesmo se o javascript do client estiver desabilitado Action 'use client' import React from 'react' export default async function View({ generateFullName }) { const [fullName, setFullName] = React.useState('') // debounce pls async function handleChange(e) { const newFullName = await generateFullName(e.target.value) setFullName(newFullName) } return ( <> <span>{fullName}</span> <input onChange={handleChange} /> </> ) }
  37. Server Actions • Server Actions não precisam ser passadas como

    props. Podem ser exportadas/ importadas diretamente • Se passada para um form, será executada mesmo se o javascript do client estiver desabilitado Action 'use client' import React from 'react' import { generateFullName } from './server-actions' export default async function View() { const [fullName, setFullName] = React.useState('') // debounce pls async function handleChange(e) { const newFullName = await generateFullName(e.target.value) setFullName(newFullName) } return ( <> <span>{fullName}</span> <input onChange={handleChange} /> </> ) }
  38. Server Actions • Camada de model isolada no servidor •

    Reduz dados enviados/ recebidos pela rede • Boa alternativa para um possível BFF/Gateway • Type-safe. São apenas funções! Utilidades 'use server' export async function getName() { const user = await userApi.getUser(...) return user.name } export function setName() { return userApi.setUser({ name }) }
  39. Server Actions • Camada de model isolada no servidor •

    Reduz dados enviados/ recebidos pela rede • Boa alternativa para um possível BFF/Gateway • Type-safe. São apenas funções! Utilidades 'use server' export async function getUserWithWorkspace() { const user = await userApi.getUser(...) const workspace = await workspaceApi.getWorkspace(...) return { user, workspace, } } export function setName() { return userApi.setUser({ name }) }
  40. Superpoderes • Composição de componentes • Composição de hooks •

    Injeção de dependência (Context API) 
 que utilizamos no dia-a-dia Fronte: https://alexsidorenko.com/blog/react-prop-drilling-composition/
  41. RSC extende seus poderes para a camada de networking e

    para o server FRONT END DAY FORTALEZA
  42. Overview • React já quebrou paradigmas no passado • Orientação

    a Objetos vs Funcional • Two-way data binding vs One- way data f low • JSX React vs AngularJS