From afa05dfd7b88b3a02cdf92ab30741824780fd213 Mon Sep 17 00:00:00 2001 From: devartes Date: Tue, 5 Dec 2023 18:18:36 -0300 Subject: [PATCH] docs: applying improvement suggestions --- .../en.md | 136 ++++------------- .../pt.md | 141 ++++-------------- 2 files changed, 64 insertions(+), 213 deletions(-) diff --git a/docs/performance/sending-only-necessary-data-to-client/en.md b/docs/performance/sending-only-necessary-data-to-client/en.md index 3a46a570..a4dc9949 100644 --- a/docs/performance/sending-only-necessary-data-to-client/en.md +++ b/docs/performance/sending-only-necessary-data-to-client/en.md @@ -1,131 +1,57 @@ --- -description: TODO +description: Sending only necessary data to client since: 1.0.0 --- -In some situations, when using [loaders](http://localhost:8000/docs/en/concepts/loader) to fetch data, an excessive amount of information may be received, negatively impacting page performance. This is evidenced by the significant size of the JSON transmitted to the client. +When loading data from external APIs using [Loaders](/docs/pt/concepts/loader) and sending them to the [Section](/docs/pt/concepts/section), it is 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.). You can visualize the size of the final JSON in the **Performance** tab in the CMS deco. -![287814343-44b8fc59-2c25-4a55-bbe3-16810d5501a6](https://github.com/deco-sites/starting/assets/76822093/ab2d2212-1e3e-487d-ad6a-3eb225f9b15b) +![288067513-db3a14e1-c0ac-47f8-83b9-afc8db60de71](https://github.com/deco-sites/starting/assets/76822093/ec005f5d-4169-4e89-acd0-8c06baf3c80d) -To mitigate this issue, we propose implementing a client-side data preprocessing process, ensuring that only necessary information is transmitted and used in the markup/UI. +When the JSON size exceeds ~500kb, it's likely that the UI doesn't need the complete data but rather some portion of it, or a computation based on other values. To reduce this size and improve page performance, it's possible to **filter the data** directly in the Loader, passing only what is necessary to the UI. ## Data Flow -1. Data Request: Initiate the normal data flow by requesting the necessary information through props. +- Initiate the request for necessary information using props. -2. Data Loader: Use a loader to fetch the desired data. In some scenarios, the loader may return a substantial amount of data, for instance, when fetching related products from [VTEX](https://www.deco.cx/docs/en/composable-apis/vtex). However, it's essential to note that there are instances where the loader might return more data than necessary for the specific operation. +- Employ a loader to fetch the desired data. In certain situations, it may return a substantial amount of data, for instance, when requesting products from [VTEX](https://www.deco.cx/docs/en/composable-apis/vtex). Be aware that it might return more data than necessary. -3. Inline Preprocessing: Introduce an inline data preprocessing mechanism. This component will receive the same props as the loader and process the data to transmit only essential information, optimizing performance. - -4. Delivery to Component: Transmit only the processed data to the JSX component, thus reducing unnecessary load on the client. +- Transmit only the processed data to the JSX component, thereby reducing unnecessary load on the client. ## Example Code -This is the implementation of the `storefront/loaders/Layouts/ProductCard.tsx`: +Implementation example of a [Loader](docs/en/developing/fetching-data): ```tsx -import ProductCard, { Layout } from "$store/components/product/ProductCard.tsx"; -import { usePlatform } from "$store/sdk/usePlatform.tsx"; +import type { SectionProps } from "deco/mod.ts"; -interface Props { - /** @title Product Card layout props */ - layout: Layout; +// Props type that will be configured in deco.cx's Admin +export interface Props { + title: string; + numberOfFacts?: number; } -/** @title Product Card Layout */ -const loader = ({ layout }: Props): Layout => layout; - -export const Preview = (props: Props) => { - const { layout } = props; +export async function loader( + { numberOfFacts, title }: Props, + _req: Request, +) { + const { facts: dogFacts } = (await fetch( + `https://dogapi.dog/api/facts?number=${numberOfFacts ?? 1}`, + ).then((r) => r.json())) as { facts: string[] }; + return { dogFacts, title }; +} +export default function DogFacts( + { title, dogFacts }: SectionProps, +) { return ( -
-
- Camisetas Gola Lisa", - "productID": "165", - "url": "", - "name": "Product Test", - "description": "Product Description", - "brand": { - "@type": "Brand", - "@id": "2000000", - "name": "deco.cx", - }, - "inProductGroupWithID": "33", - "sku": "165", - "gtin": "789456123003305", - "additionalProperty": [ - { - "@type": "PropertyValue", - "name": "TAMANHO", - "value": "GG", - "valueReference": "SPECIFICATION", - }, - ], - "isVariantOf": { - "@type": "ProductGroup", - "productGroupID": "33", - "hasVariant": [], - "name": "Camiseta Masculina Gola Lisa Olive", - "additionalProperty": [], - }, - "image": [ - { - "@type": "ImageObject", - "alternateName": "test", - "url": - "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2291/b9e0a819-6a75-47af-84fe-90b44fecda5f", - }, - { - "@type": "ImageObject", - "alternateName": "test", - "url": - "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2291/b9e0a819-6a75-47af-84fe-90b44fecda5f", - }, - ], - "offers": { - "@type": "AggregateOffer", - "priceCurrency": "BRL", - "highPrice": 69.3, - "lowPrice": 69.3, - "offerCount": 1, - "offers": [ - { - "@type": "Offer", - "price": 69.3, - "seller": "1", - "priceValidUntil": "2024-09-04T13:03:31Z", - "inventoryLevel": { "value": 10000 }, - "teasers": [], - "priceSpecification": [ - { - "@type": "UnitPriceSpecification", - "priceType": "https://schema.org/ListPrice", - "price": 179, - }, - { - "@type": "UnitPriceSpecification", - "priceType": "https://schema.org/SalePrice", - "price": 69.3, - }, - ], - "availability": "https://schema.org/InStock", - }, - ], - }, - }} - /> -
+
+

{title}

+
    + {dogFacts.map((fact) =>
  • {fact}
  • )} +
); -}; - -export default loader; +} ``` ## Benefits diff --git a/docs/performance/sending-only-necessary-data-to-client/pt.md b/docs/performance/sending-only-necessary-data-to-client/pt.md index 59482245..7d75c7f0 100644 --- a/docs/performance/sending-only-necessary-data-to-client/pt.md +++ b/docs/performance/sending-only-necessary-data-to-client/pt.md @@ -1,132 +1,57 @@ --- -description: TODO +descrição: Enviando apenas dados necessários ao cliente since: 1.0.0 --- -Em algumas situações, ao utilizar [loaders](http://localhost:8000/docs/pt/concepts/loader) para obter dados, pode-se receber uma quantidade excessiva de informações, impactando negativamente o desempenho da página. Isso é evidenciado pelo tamanho significativo do JSON transmitido para o cliente. +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 no [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. -![287813945-9ccd40a6-f41f-486f-a2b6-3f1efca0bfd1](https://github.com/deco-sites/starting/assets/76822093/bff19a56-bc1d-475b-b25d-f45fd1af713a) +![288067513-db3a14e1-c0ac-47f8-83b9-afc8db60de71](https://github.com/deco-sites/starting/assets/76822093/ec005f5d-4169-4e89-acd0-8c06baf3c80d) - -Para mitigar esse problema, propomos a implementação de um processo de pré-processamento dos dados no lado do cliente, garantindo que apenas as informações necessárias sejam transmitidas e utilizadas no markup/UI. +Quando o tamanho do JSON passa de ~500kb, é provável que a UI não precisa do dado completo, mas sim alguma parte dele (ou então uma computação sobre outros valores). Para diminuir esse tamanho e 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. ## Fluxo de Dados -1. Solicitação de Dados: Inicie o fluxo normal de dados, solicitando as informações necessárias por meio de props. - -2. Loader de Dados: Utilize um loader para obter os dados desejados. Em algumas situações, o loader pode retornar uma quantidade substancial de dados, por exemplo, ao solicitar produtos relacionados da [VTEX](https://www.deco.cx/docs/pt/composable-apis/vtex). No entanto, é importante observar que há momentos em que o loader pode retornar uma quantidade de dados maior do que o necessário para a operação em questão. - -3. Pré-Processamento Inline: Introduza um mecanismo de pré-processamento de dados inline. Este componente receberá as mesmas props do loader e processará os dados de forma a transmitir apenas as informações essenciais, otimizando assim o desempenho. - -4. Entrega ao Componente: Transmita apenas os dados processados para o componente JSX, reduzindo assim a carga desnecessária no cliente. +- Inicie solicitando as informações necessárias usando props. + +- Utilize um loader para obter os dados desejados. Em algumas situações, pode retornar muitos dados, como ao solicitar produtos da [VTEX](https://www.deco.cx/docs/pt/composable-apis/vtex). Esteja ciente de que pode retornar mais dados do que o necessário. + +- Transmita apenas os dados processados para o componente JSX, reduzindo assim a carga desnecessária no cliente. ## Código de exemplo -Esta é a implementação do Loader `storefront/loaders/Layouts/ProductCard.tsx`: +Exemplo de implementação de um [Loader](docs/pt/developing/fetching-data): ```tsx -import ProductCard, { Layout } from "$store/components/product/ProductCard.tsx"; -import { usePlatform } from "$store/sdk/usePlatform.tsx"; +import type { SectionProps } from "deco/mod.ts"; -interface Props { - /** @title Product Card layout props */ - layout: Layout; +// Props type that will be configured in deco.cx's Admin +export interface Props { + title: string; + numberOfFacts?: number; } -/** @title Product Card Layout */ -const loader = ({ layout }: Props): Layout => layout; - -export const Preview = (props: Props) => { - const { layout } = props; +export async function loader( + { numberOfFacts, title }: Props, + _req: Request, +) { + const { facts: dogFacts } = (await fetch( + `https://dogapi.dog/api/facts?number=${numberOfFacts ?? 1}`, + ).then((r) => r.json())) as { facts: string[] }; + return { dogFacts, title }; +} +export default function DogFacts( + { title, dogFacts }: SectionProps, +) { return ( -
-
- Camisetas Gola Lisa", - "productID": "165", - "url": "", - "name": "Product Test", - "description": "Product Description", - "brand": { - "@type": "Brand", - "@id": "2000000", - "name": "deco.cx", - }, - "inProductGroupWithID": "33", - "sku": "165", - "gtin": "789456123003305", - "additionalProperty": [ - { - "@type": "PropertyValue", - "name": "TAMANHO", - "value": "GG", - "valueReference": "SPECIFICATION", - }, - ], - "isVariantOf": { - "@type": "ProductGroup", - "productGroupID": "33", - "hasVariant": [], - "name": "Camiseta Masculina Gola Lisa Olive", - "additionalProperty": [], - }, - "image": [ - { - "@type": "ImageObject", - "alternateName": "test", - "url": - "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2291/b9e0a819-6a75-47af-84fe-90b44fecda5f", - }, - { - "@type": "ImageObject", - "alternateName": "test", - "url": - "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2291/b9e0a819-6a75-47af-84fe-90b44fecda5f", - }, - ], - "offers": { - "@type": "AggregateOffer", - "priceCurrency": "BRL", - "highPrice": 69.3, - "lowPrice": 69.3, - "offerCount": 1, - "offers": [ - { - "@type": "Offer", - "price": 69.3, - "seller": "1", - "priceValidUntil": "2024-09-04T13:03:31Z", - "inventoryLevel": { "value": 10000 }, - "teasers": [], - "priceSpecification": [ - { - "@type": "UnitPriceSpecification", - "priceType": "https://schema.org/ListPrice", - "price": 179, - }, - { - "@type": "UnitPriceSpecification", - "priceType": "https://schema.org/SalePrice", - "price": 69.3, - }, - ], - "availability": "https://schema.org/InStock", - }, - ], - }, - }} - /> -
+
+

{title}

+
    + {dogFacts.map((fact) =>
  • {fact}
  • )} +
); -}; - -export default loader; +} ``` ## Benefícios