From 2fdfe45cfbac3d6de5478822179b987ae25c19d3 Mon Sep 17 00:00:00 2001
From: "Ana Carolina D. C" <76822093+devartes@users.noreply.github.com>
Date: Wed, 13 Dec 2023 12:29:11 -0300
Subject: [PATCH] feat: add docs 'sending only necessary data to client' (#213)
---
.../en.md | 160 ++++++++++++++++++
.../pt.md | 159 +++++++++++++++++
docs/toc.ts | 19 ++-
3 files changed, 332 insertions(+), 6 deletions(-)
create mode 100644 docs/performance/sending-only-necessary-data-to-client/en.md
create mode 100644 docs/performance/sending-only-necessary-data-to-client/pt.md
diff --git a/docs/performance/sending-only-necessary-data-to-client/en.md b/docs/performance/sending-only-necessary-data-to-client/en.md
new file mode 100644
index 00000000..157dde2b
--- /dev/null
+++ b/docs/performance/sending-only-necessary-data-to-client/en.md
@@ -0,0 +1,160 @@
+---
+description: Sending only necessary data to client
+since: 1.0.0
+---
+
+When loading data from external APIs using [Loaders](/docs/en/concepts/loader) and sending them to the [Section](/docs/en/concepts/section), it's possible that the size of the payload may negatively impact the site's performance. The impact occurs both in the initial loading time and in the [hydration](https://blog.saeloun.com/2021/12/16/hydration/), where the page is "initialized" in the browser to make it interactive (using `useEffect`, `useSignal`, etc.). It's possible to visualize the size of the final JSON through the **Performance** tab in the CMS deco.
+
+![288067513-db3a14e1-c0ac-47f8-83b9-afc8db60de71](https://github.com/deco-sites/starting/assets/76822093/ec005f5d-4169-4e89-acd0-8c06baf3c80d)
+
+When the JSON size exceeds ~500kb, it's likely that the UI doesn't need the complete data but rather some part of it (or a computation based on other values). To reduce this size and improve page performance, it's possible to **filter the data** still on the loader to ensure that only the necessary data is passed to the UI.
+
+
+## Example Code - 1
+
+In this first example, we will show how to avoid sending too much data to an Island.
+
+Let's say there's a component called ProductCard, which receives the entire JSON of a product.
+
+```tsx
+ import Image from "apps/website/components/Image.tsx"
+
+ export default function ProductCard({product} : Props){
+ return(
+
+
+
+ )
+ }
+```
+
+In it, you want to include an [Island](https://fresh.deno.dev/docs/concepts/islands) to create the buy button.
+
+```tsx
+ import BuyButton from "$store/components/ui"
+ import Image from "apps/website/components/Image.tsx"
+
+ export default function ProductCard({product} : Props){
+
+ return(
+
+
+
+
+ )
+ }
+```
+
+It's possible that this BuyButton may need some product information to be able to add it to the cart.
+
+Here is where we should be careful about the amount of data sent to the Island.
+
+For example, it's quite possible that the buy button doesn't need to receive image data.
+
+The ideal approach is to send only the necessary data.
+
+❌ Wrong Approach:
+
+```tsx
+ import BuyButton from "$store/components/ui"
+ import Image from "apps/website/components/Image.tsx"
+
+ export default function ProductCard({product} : Props){
+
+ return(
+
+
+
+
+ )
+ }
+```
+
+✅ Correct Approach:
+
+```tsx
+ import BuyButton from "$store/components/ui"
+ import Image from "apps/website/components/Image.tsx"
+
+ export default function ProductCard({product} : Props){
+
+ return(
+
+
+
+
+ )
+ }
+```
+
+The correct approach sends only the ID and Seller data, which in this example are the only ones needed in the Island.
+
+Thus, during hydration, the JSON that the Island will load won't be as large.
+
+## Example Code - 2
+
+In this example, we will show how to avoid sending a very large piece of data to a section.
+
+Let's say we have an inline loader to fetch product colors and return them in a section.
+
+```tsx
+export default function Colors({colors}){
+
+ return colors.map(color => {color})
+}
+
+export const loader = async () => {
+ const colors = await fetch("/product/colors").then(r => r.json())
+
+ return colors;
+}
+```
+
+This component seems correct, right?
+
+However, after an investigation, we found that the returned data also included product images.
+
+Example of the API response:
+
+```tsx
+colors = [
+ {
+ "color": "red"
+ "images": [...]
+ },
+ {
+ "color": "green"
+ "images": [...]
+ },
+ {
+ "color": "orange"
+ "images": [...]
+ },
+}]
+```
+
+The image data in this response will not be used in the section, so we don't need to send it.
+
+We can filter it like this:
+
+
+```tsx
+export default function Colors({colors}){
+
+ return colors.map(color => {color})
+}
+
+export const loader = async () => {
+ const result = await fetch("/product/colors").then(r => r.json())
+ const colors = result.map(item => item.color)
+ return colors;
+}
+```
+
+This way, only the data that is used will be sent, avoiding unnecessary overload.
+
+## Benefits
+- Significant reduction in the size of transmitted JSON.
+- Noticeable improvement in page performance, especially in terms of loading.
+
+By implementing this data preprocessing process, it is possible to optimize page performance, ensuring that only crucial information is sent and processed, providing a more streamlined performance for the user.
diff --git a/docs/performance/sending-only-necessary-data-to-client/pt.md b/docs/performance/sending-only-necessary-data-to-client/pt.md
new file mode 100644
index 00000000..761f5ffd
--- /dev/null
+++ b/docs/performance/sending-only-necessary-data-to-client/pt.md
@@ -0,0 +1,159 @@
+---
+descrição: Enviando apenas dados necessários ao cliente
+since: 1.0.0
+---
+
+Ao carregar dados de APIs externas usando [Loaders](/docs/pt/concepts/loader) e enviá-los para a [Section](/docs/pt/concepts/section), é possível que o tamanho do _payload_ impacte negativamente a performance do site. O impacto ocorre tanto no tempo inicial de carregamento como também na [hidratação](https://blog.saeloun.com/2021/12/16/hydration/), onde a página é "inicializada" no browser para que possa ser interativa (usar `useEffect`, `useSignal`, etc...). É possível visualizar no tamanho do JSON final através da aba **Performance** no CMS deco.
+
+![288067513-db3a14e1-c0ac-47f8-83b9-afc8db60de71](https://github.com/deco-sites/starting/assets/76822093/ec005f5d-4169-4e89-acd0-8c06baf3c80d)
+
+Quando o tamanho do JSON passa de ~500kb, é provável que a UI não precise do dado completo, mas sim alguma parte dele (ou então uma computação sobre outros valores). Para diminuir esse tamanho e melhorar a performance da página, é possível **filtrar os dados** ainda no Loader para que apenas o necessário seja passado para a UI.
+
+
+## Código de exemplo - 1
+
+Nesse primeiro exemplo, mostraremos como evitar enviar muitos dados para uma Island.
+
+Digamos que existe um componente chamado ProductCard, que recebe todo o JSON de um produto.
+
+```tsx
+ import Image from "apps/website/components/Image.tsx"
+
+ export default function ProductCard({product} : Props){
+ return(
+
+
+
+ )
+ }
+```
+
+Nele, você deseja incluir uma [Island](https://fresh.deno.dev/docs/concepts/islands) para criar o botão de comprar.
+
+```tsx
+ import BuyButton from "$store/components/ui"
+ import Image from "apps/website/components/Image.tsx"
+
+ export default function ProductCard({product} : Props){
+
+ return(
+
+
+
+
+ )
+ }
+```
+
+É possível que esse BuyButton, precise de algumas informações do produto para poder adicionar ao carrinho.
+
+Aqui que devemos tomar cuidado a quantidade de dados enviados para a Island.
+
+Por exemplo, é bem possível que o botão de comprar não precise receber dados de imagem.
+
+O ideal é enviar apenas os dados necessários
+
+❌ Abordagem errada:
+
+```tsx
+ import BuyButton from "$store/components/ui"
+ import Image from "apps/website/components/Image.tsx"
+
+ export default function ProductCard({product} : Props){
+
+ return(
+
+
+
+
+ )
+ }
+```
+
+✅ Abordagem correta:
+
+```tsx
+ import BuyButton from "$store/components/ui"
+ import Image from "apps/website/components/Image.tsx"
+
+ export default function ProductCard({product} : Props){
+
+ return(
+
+
+
+
+ )
+ }
+```
+
+A abordagem correta envia apenas os dados de ID e Seller, que no exemplo, são os únicos necessários na Island.
+
+Assim, no momento de hidratação, o JSON que a Island irá carregar não será tão grande.
+
+## Código de exemplo - 2
+
+Neste exemplo, vamos mostrar como evitar enviar um dado muito grande para uma section.
+
+Digamos que temos um loader inline para buscar as cores do produto e retornar em uma section.
+
+```tsx
+export default function Colors({colors}){
+
+ return colors.map(color => {color})
+}
+
+export const loader = async () => {
+ const colors = await fetch("/product/colors").then(r => r.json())
+
+ return colors;
+}
+```
+
+Esse componente parece correto, certo?
+
+Porém, após uma investigação, verificamos que o dado retornado trazia também as imagens do produto.
+
+Exemplo do retorno da API:
+
+```tsx
+colors = [
+ {
+ "color": "red"
+ "images": [...]
+ },
+ {
+ "color": "green"
+ "images": [...]
+ },
+ {
+ "color": "orange"
+ "images": [...]
+ },
+}]
+```
+
+Os dados de imagem nesse retorno, não serão utilizados na section, então não precisamos enviá-los.
+
+Podemos filtrar dessa forma:
+
+```tsx
+export default function Colors({colors}){
+
+ return colors.map(color => {color})
+}
+
+export const loader = async () => {
+ const result = await fetch("/product/colors").then(r => r.json())
+ const colors = result.map(item => item.color)
+ return colors;
+}
+```
+
+Dessa forma, apenas os dados utilizados serão enviados, evitando uma sobrecarga desnecessária.
+
+## Benefícios
+- Redução significativa no tamanho do JSON transmitido.
+- Melhoria perceptível no desempenho da página, especialmente em termos de carregamento.
+
+Ao implementar esse processo de pré-processamento de dados, é possível otimizar a performance da página, garantindo que apenas as informações cruciais sejam enviadas e processadas, proporcionando um desempenho mais otimizado para o usuário.
diff --git a/docs/toc.ts b/docs/toc.ts
index 2cb70820..16f65d48 100644
--- a/docs/toc.ts
+++ b/docs/toc.ts
@@ -280,17 +280,24 @@ const tableOfContents: TableOfContents = [
},
{
title: {
- pt: "Como usar a deco para atingir alta performance",
- en: "How can you use deco for achieve high performance",
+ pt: "Dicas para atingir uma alta performance",
+ en: "Performance tips",
},
- slug: "performance/how-deco-performance",
+ slug: "performance/tips",
},
{
title: {
- pt: "Dicas para atingir uma alta performance",
- en: "Performance tips",
+ pt: "Enviar apenas os dados necessários para o cliente",
+ en: "Sending only necessary data to client",
},
- slug: "performance/tips",
+ slug: "performance/sending-only-necessary-data-to-client",
+ },
+ {
+ title: {
+ pt: "Como usar a deco para atingir alta performance",
+ en: "How can you use deco for achieve high performance",
+ },
+ slug: "performance/how-deco-performance",
},
],
},