Actualización a v3

A partir de la versión 3, se pueden obtener actualizaciones de @salesforce/retail-react-app agregándola como una dependencia de package.json y habilitando la extensibilidad de la plantilla en su proyecto.

Esta guía cubre cómo actualizar un proyecto de PWA Kit de v2.7.x a v3.0.0.

Novedades 

Hemos agregado muchas características nuevas a PWA Kit v3, que incluyen:

⚛️ Se requiere:

  • getProps Cambio rotundo
  • Actualizaciones importantes de la biblioteca, incluida la compatibilidad con React 18, Node 18, Chakra 2 y más

🔨 Opcional: Extensibilidad de la plantilla — Reduzca en gran medida la huella de código de su proyecto y reduzca el trabajo de desarrollo, el costo de propiedad y los dolores de cabeza por mejoras futuras. Para obtener más información, consulte la guía Extensibilidad de la plantilla.

🔨 Opcional: @salesforce/commerce-sdk-react “hooks” integration — Disocia las llamadas de API de la implementación de un proyecto, permite que las llamadas de API se mejoren como dependencia de biblioteca npm y suma muchas de las grandes características (incluida gestión de estado, entre otras) a través de la consulta de TanStack. Consulte la documentación SDK de React de Commerce para comenzar.

Cambios requeridos 

Nuevos paquetes de SDK 

Los SDK de PWA Kit se han movido a la organización NPM @salesforce . Para actualizar a la versión 3, instale los nuevos paquetes y reemplace todas las instrucciones de importación para los siguientes paquetes:

  • pwa-kit-react-sdk > @salesforce/pwa-kit-react-sdk@^3
  • pwa-kit-runtime > @salesforce/pwa-kit-runtime@^3
  • pwa-kit-dev > @salesforce/pwa-kit-dev@^3
  • pwa-kit-create-app > @salesforce/pwa-kit-create-app@^3
  • retail-react-app > @salesforce/retail-react-app@^3

Cambio importante para getProps 

A partir de la versión 3.0.0, PWA Kit presenta una nueva estrategia withReactQueryde obtención de datos. Esta estrategia utiliza la biblioteca react-query y le permite escribir ganchos de React para obtener datos de forma isomórfica. getProps A diferencia de , ya no es necesario duplicar la lógica de obtención de datos para el lado del cliente y el lado del servidor. En esta versión, de forma predeterminada, @salesforce/retail-react-app utiliza @salesforce/commerce-sdk-react que funciona con react-query.

1// app/components/_app-config/index.jsx
2
3import { withLegacyGetProps } from "@salesforce/pwa-kit-react-sdk/ssr/universal/components/with-legacy-get-props";
4
5const AppConfig = ({ children }) => {
6  return <div>My AppConfig</div>;
7};
8
9export default withLegacyGetProps(AppConfig);
  • Puede usar withReactQuery y withLegacyGetProps al mismo tiempo.
  • getProps y shouldGetProps se eliminaron de la plantilla predeterminada de las páginas de Retail React App, pero no están en desuso. Se mantiene el apoyo a largo plazo para estos métodos.

Note

Actualizaciones de dependencias de paquetes 

Cambie las dependencias en package.json como se muestra a continuación. Retire @chakra-ui/system de peerDependencies e inclúyalo en dependencies o devDependencies.

1"@chakra-ui/icons": "^2.0.19",
2"@chakra-ui/react": "^2.6.0",
3"@chakra-ui/skip-nav": "^2.0.15",
4"@chakra-ui/system": "^2.5.6",
5"framer-motion": "^10.12.9",
6"react": "^18.2.0",
7"react-dom": "^18.2.0",
8"react-hook-form": "^7.43.9"

Actualice los motores en package.json para admitir Node 18 y npm 9.

1"engines": {`
2    "node": "^18.0.0",`
3    "npm": "^8.0.0 || ^9.0.0"`
4}

Reinstale las dependencias de su proyecto con npm i.

Opcional. Uso de la extensibilidad de la plantilla 

Al migrar de v2.7.x a v3.x, puede elegir si desea usar la extensibilidad de plantillas. Para beneficiarse de él, debe importar al menos un archivo de @salesforce/retail-react-app (u otra plantilla ampliable en el futuro).

A partir de ahí, considere cuántos archivos ha modificado del proyecto original que generó a través de npx pwa-kit-create-app@2.x. Algunos clientes tienen un gran número (quizás cientos) de archivos, pero incluso así, un número significativo puede no modificarse. Esos archivos no modificados son buenos candidatos para importar desde @salesforce/retail-react-app, pero recomendamos realizar este proceso con cuidado y de forma gradual. Muchos archivos en @salesforce/retail-react-app son similares pero se han modificado desde su estado anterior en v2.x de la Retail React App de PWA Kit. En particular, la integración de @salesforce/commerce-sdk-react (los detalles de la migración se tratan con más detalle más adelante) ha provocado que un gran número de archivos cambien en términos de sus importaciones y su estructura de archivos. El directorio completo commerce-api se eliminó de Retail React App.

Al migrar un proyecto para usar la extensibilidad de la plantilla, tenga en cuenta que la versión 2.x de los SDK del PWA Kit y los proyectos generados a través de npx pwa-kit-create-app@2.x no dependen de @salesforce/commerce-sdk-react, mientras que el código más nuevo @salesforce/retail-react-app@^1.x hace un uso intensivo de esta biblioteca, que toca y cambia muchos archivos. Para tener una idea de la magnitud de los cambios, se puede comparar release-2.7.xrelease-3.0.x en esta diferencia de Github https://github.com/SalesforceCommerceCloud/pwa-kit/compare/release-2.7.x…release-3.0.x?diff=unified#files_bucket y buscar @salesforce/commerce-sdk-react y tomar nota de todas las adiciones que agregan esta importación.

Note

Si su aplicación intenta compartir código con la versión 2.x (que incluye el directorio app/commerce-api), corre el riesgo de agregar código innecesario a su paquete donde ese código existe (en dos formas muy diferentes) tanto en la carpeta commerce-api como en el módulo npm @salesforce/commerce-sdk-react.

Warning

Opcional. Consumir la biblioteca de enlaces commerce-sdk-react 

A partir de v3.0.0, el PWA Kit utiliza una estrategia de recuperación diferente withReactQuery. Esta estrategia aprovecha la biblioteca react-query y permite consultas en el paso de renderizado SSR. La @salesforce/retail-react-app utiliza @salesforce/commerce-sdk-react que funciona con react-query.

Para que los enlaces funcionen en el lado del servidor, debe envolver su componente AppConfig con el nuevo componente withReactQuery de orden superior.

Como estrategia de recuperación predeterminada, se requiere un cambio en @salesforce/retail-react-app@^1 para garantizar que las llamadas getProps() heredadas sigan funcionando.

Warning

1// app/components/_app-config/index.jsx
2
3import { CommerceApiProvider } from "@salesforce/commerce-sdk-react";
4import { withReactQuery } from "@salesforce/pwa-kit-react-sdk/ssr/universal/components/with-react-query";
5
6const AppConfig = ({ children }) => {
7  return (
8    <CommerceApiProvider
9      clientId="12345678-1234-1234-1234-123412341234"
10      organizationId="f_ecom_aaaa_001"
11      proxy="localhost:3000/mobify/proxy/api"
12      redirectURI="localhost:3000/callback"
13      siteId="RefArch"
14      shortCode="12345678"
15      locale="en-US"
16      currency="USD"
17    >
18      {children}
19    </CommerceApiProvider>
20  );
21};
22
23export default withReactQuery(AppConfig);

Solución de problemas y optimización 

Al completar las actualizaciones de dependencias descritas anteriormente, es posible que encuentre problemas en el proyecto relacionados con las bibliotecas siguientes. En las siguientes secciones proponemos soluciones para resolver estos problemas. Los detalles de su proyecto variarán y las soluciones propuestas deben tratarse como pautas y no como reglas absolutas.

Actualizar react-hook-form 

Para la migración de react-hook-form, lea el documento oficial de react-hook-form aquí. En el proyecto PWA, hay dos lugares que requieren cambios:

  1. Mueva el objeto de formulario errors a una capa más de destrucción para los ganchos a app/components/forms/ medida que el errors objeto se ha movido al formState objeto.
1// app/components/forms/useAddressFields.jsx
2
3    //before
4    export default function useAddressFields({form: {watch, control, errors}, prefix = ''}) {
5
6    //after
7    export default function useAddressFields({
8        form: {
9            watch,
10            control,
11            formState: {errors}
12        },
13        prefix = ''
14    })
  1. Mueva las props de renderización en Controller a la prop field. La firma de devolución de Render devuelve un objeto que contiene field y fieldState.
1// app/components/field/index.jsx
2
3    // before
4    <Controller
5        name={name}
6        control={control}
7        rules={rules}
8        defaultValue={defaultValue}
9        render={({onChange, value, ref}) => {
10          // other code
11        }}
12    />
13
14    // after
15    <Controller
16        name={name}
17        control={control}
18        rules={rules}
19        defaultValue={defaultValue}
20        render={({field: {onChange, value, ref}}) => {
21          // other code
22        }}
23    />

Error de hidratación de React 18 

A partir de React 18, las advertencias de hidratación aparecen como errores en lugar de advertencias como aparecían en React 17. Se requirieron algunas actualizaciones de código para suprimir estos errores potenciales que impiden que la aplicación se cree cuando hay errores de hidratación. Es esencial corregir estos errores para garantizar que la aplicación pueda renderizarse de forma isomórfica. Este error se produce porque no hay coincidencia entre el servidor o el cliente. Si un componente o una página se renderiza de forma condicional, debe asegurarse de que finalice la hidratación antes de renderizar cualquier código específico del cliente.

En su proyecto, cree una función de utilidad para determinar si la hidratación ha terminado. Puede utilizar una variable incorporada proporcionada por window.__HYDRATING__ en pwa-kit-react-sdk.

1/**
2 * This utility function determines if the app has finished hydration
3 * @return {boolean}
4 */
5export const isHydrated = () =>
6  typeof window !== "undefined" && !window.HYDRATING;

Chakra 2 

Si su proyecto utiliza componentes y API de la biblioteca @chakra-ui/react que son diferentes a la plantilla de la Retail React App, revise los documentos oficiales de migración de Chakra 2.

Important

Para admitir Chakra 2, hay algunos archivos que requieren actualizaciones para proyectos basados en la plantilla de la Retail React App:

Elimine allowToggle en el componente Accordion porque allowMultiple y allowToggle no se pueden usar al mismo tiempo en Chakra 2.

En el componente Footer, importar StylesProvider directamente desde @chakra-ui/react está obsoleto. Debes crearlo a través de createStylesContext('Footer') en su lugar.

1import { createStylesContext } from "@chakra-ui/react";
2
3const [StylesProvider, useStyles] = createStylesContext("Footer");

@testing-library/react 

Configure userEvent antes de llamar a cualquier acción y espere la acción en las pruebas unitarias que usan userEvent porque en la biblioteca de pruebas de React v14.0.0, todas las acciones del usuario son asíncronas y es necesario llamar a setup antes de realizar las acciones del usuario.

Por ejemplo:

1const user = userEvent.setup()`
2// Import `render`and`screen` from the framework library of your choice.
3// See https://testing-library.com/docs/dom-testing-library/install#wrappers
4render(<MyComponent />)
5
6await user.click(screen.getByRole('button', {name: /click me!/i}))

Para obtener más información, consulte los documentos oficiales de userEvent de la testing-library.

Alternativamente, para evitar llamar repetidamente a setup()in many unit tests, you can set up youruserEvent ‘in app/utils/test-util.js justo antes de renderizar el componente de prueba y devolverlo junto con los resultados de renderizado para que la prueba pueda realizar las acciones del usuario sin tener que llamar setup().

1export const renderWithProvider = (children, options) => {
2   // some code here
3   const user = userEvent.setup()
4   const res = render(children, {
5        wrapper: () => (
6            <TestProvidersWithDataAPI {...options?.wrapperProps} locals={locals}>
7                {children}
8            </TestProvidersWithDataAPI>
9        ),
10        ...options
11    })
12    return {user, ...res}
13}
14
15//usage
16test('some test', async () => {
17   const {user} = renderWithProviders(<MyComponent />
18   const button = screen.getByText(/button/)
19   await user.click(button)
20}

Jest-setup 

En jest-setup, hay una dependencia simulada que puede generar un error acerca de que TextDecoder no está definido en jest-setup.js. Agregue lo siguiente a jest-setup.js:

1global.TextDecoder = require("util").TextDecoder;

Otras mejoras 

Al migrar desde la versión 2.x de los SDK del PWA Kit o proyectos generados a través de npx pwa-kit-create-app@2.x, el código @salesforce/commerce-sdk-react se ha refactorizado significativamente para eliminar el directorio app/commerce-api/. En lugar de que esos archivos manejen la solicitud de API y actúen como un SDK, @salesforce/commerce-sdk-react reemplaza esa funcionalidad. La versión v3 de los SDK se correlaciona con la primera versión de @salesforce/retail-react-app@^1.x porque los SDKS usan mucho esta biblioteca.

La implementación de @salesforce/commerce-sdk-react cambia muchos archivos en la Retail React App. Para tener una idea del tamaño de los cambios, compáralos release-2.7.x con release-3.0.x en esta diferencia de GitHub y busca @salesforce/commerce-sdk-react. En el diff, toma nota de todas las adiciones que incluyen esta importación.