Extensibilidad de la plantilla
La extensibilidad de la plantilla es una característica introducida en PWA Kit v3. El objetivo de esta característica es permitirle crear proyectos de PWA Kit con mayor facilidad mediante la personalización de plantillas. Puede personalizar las plantillas base existentes, como la Retail React App, o puede crear las suyas. Alentamos a los miembros de la comunidad de PWA Kit a compartir sus plantillas base entre sí.
La extensibilidad de la plantilla le ayuda a modificar una plantilla elegida sin tener que duplicar todos los archivos que contiene.
La extensibilidad de la plantilla es una característica opcional. Sin embargo, los proyectos nuevos que se generen después del 15 de junio de 2023 se configurarán de manera automática para utilizar la extensibilidad de la plantilla.
En PWA Kit v3, un proyecto puede tener una plantilla base y un directorio de reemplazos, los cuales se pueden configurar en el archivo package.json
del proyecto. Para utilizar la extensibilidad de la plantilla, debe indicar una plantilla base con ccExtensibility.extends
en package.json
y debe indicar un directorio de reemplazos con ccExtensibility.overridesDir
. (Los detalles de configuración se tratan en la siguiente sección).
Una plantilla base es un módulo npm que contiene un proyecto de PWA Kit completamente funcional que ha sido preconfigurado para que otro proyecto de PWA Kit pueda reemplazar algunos de sus archivos. A veces, la plantilla base también se denomina “aplicación extensible” o “aplicación expandible”."
El directorio de reemplazos es un directorio dentro de su proyecto en el que puede almacenar archivos que reemplazarán a los archivos correspondientes en la plantilla base.
Supongamos que ya definió un directorio de reemplazos y definió la Retail React App como su plantilla base. Digamos que quiere reemplazar el componente de la página de inicio de la Retail React App. En la Retail React App, el código para el componente de la página de inicio se encuentra en app/pages/home/index.jsx
dentro del paquete @salesforce/retail-react-app
. Para reemplazar ese archivo, debe volver a crear ese mismo archivo en el directorio indicado mediante ccExtensibility.overridesDir
en package.json
. Entonces, la ruta del nuevo archivo es <ccExtensibility.overridesDir>/app/pages/home/index.jsx
.
Ahora, cada vez que se importa index.jsx
a cualquiera de los archivos dentro del paquete @salesforce/retail-react-app
, se carga el archivo del directorio de reemplazos en lugar del archivo del paquete. Para que se ejecute el reemplazo, solo es necesario que la base del nombre del archivo sea la misma. Las extensiones del archivo pueden ser diferentes.
A medida que crea su aplicación, puede agregar archivos de forma gradual desde la plantilla base a su directorio de reemplazos.
Cuantos más archivos reemplace, se necesitará un mayor esfuerzo para mantenerse al día con los cambios en la plantilla base.
Para ver la extensibilidad de la plantilla en acción, genere un nuevo proyecto de PWA Kit v3 ejecutando npx @salesforce/pwa-kit-create-app@latest --outputDir <path/to/new/local/project>
.
El proyecto generado utiliza la plantilla base de la Retail React App, que le brinda una aplicación que se ve prácticamente igual a la que se encuentra en https://pwa-kit.mobify-storefront.com/.
En los tutoriales de extensibilidad de plantillas, aprenderá a agregar algunas personalizaciones comunes a su sitio:
- Personalizar un componente : extensibilidad a nivel de componente
- Personalizar una página : extensibilidad a nivel de página
Las instrucciones de esta sección asumen que quiere habilitar la extensibilidad de la plantilla para un proyecto existente que no se generó con la característica ya habilitada.
Para actualizar a la última versión de Retail React App, ejecute este comando:
npm install @salesforce/retail-react-app@latest
Después de ejecutar ese comando, le recomendamos que pruebe su sitio para confirmar que funciona según lo esperado.
Para definir una plantilla base, agregue @salesforce/retail-react-app
(o una plantilla diferente) como dependencia npm en el archivo package.json
de su proyecto.
Luego agregue una clave ccExtensibility
a package.json
con las siguientes claves y valores:
Si está utilizando una plantilla base que no es la Retail React App, no se olvide de reemplazar @salesforce/retail-react-app
con el identificador de paquete de la otra plantilla.
Puede reemplazar los valores de overridesDir
con un nombre de directorio personalizado, pero recomendamos usar overrides
para mantener la coherencia entre los proyectos (y nuestro código de ejemplo).
No enumere las mismas dependencias de npm tanto en el proyecto principal como en la plantilla base. Confirme que las dependencias enumeradas en el package.json
proyecto son diferentes de las de la plantilla base. Esto garantiza que @salesforce/pwa-kit-dev
se pueda diferenciar entre los dos en la resolución de dependencias. Defina una plantilla base en el proyecto package.json
principal como se describe en Configuración. El proyecto principal no puede heredar de sí mismo.
Su proyecto no debe tener conflictos con las versiones de las dependencias npm de la plantilla base que se enumeran en el archivo package.json
. Si la plantilla subyacente utiliza @chakra-ui
, su proyecto también debe tenerla como dependencia y debe ser la misma versión. Esta medida evita que su paquete se llene por accidente (sin mencionar el mal funcionamiento) debido a versiones en conflicto del mismo paquete. Hay una excepción a esta regla: Cuando haya agregado reemplazos para todos los archivos en la plantilla base que importa una dependencia determinada. En ese caso, la versión de la dependencia de la plantilla base nunca se importa al proyecto porque ha eliminado todos los archivos que la importan mediante reemplazos.
Agregar dependencias npm adicionales que no se usan en la plantilla subyacente está bien. 👌
Cada proyecto de PWA Kit implementado en Managed Runtime debe tener los siguientes archivos:
<overridesDir>/app/main.jsx
<overridesDir>/app/ssr.js
<overridesDir>/app/routes.jsx
<overridesDir>/app/request-processor.js
config/default.js
(excepción: si está utilizando la clavemobify
enpackage.json
para almacenar los datos de configuración de su sitio)
Para personalizar comportamientos en el proyecto, es habitual reemplazar estos archivos en @salesforce/retail-react-app
:
app/pages/home/index.jsx
: Eliminar el contenido de marketing predeterminado de Salesforce de la página de inicio es el primer paso en casi todos los proyectos.app/static/*
: Estos archivos son predeterminados que contienen íconos utilizados por los navegadores de escritorio y móviles para la marca de su sitio. Actualícelos para que coincidan con su marca.app/constants.js
app/assets/svg/brand-logo.svg
: Este archivo se reemplaza en el proyecto del generador. Siga el siguiente ejemplo para reemplazar otros íconos en su proyecto.
La intención de esta configuración de “sistema de archivos como API” es ayudarle a encontrar los archivos subyacentes, copiarlos y luego personalizar el comportamiento y la lógica. Dividir el código en archivos más pequeños que organizan muchos subcomponentes hace que sea más fácil centrarse únicamente en el comportamiento que desea reemplazar.
Dicho esto, a veces es necesario copiar un archivo en los reemplazos para cambiar solo una parte del comportamiento de ese archivo. Siempre que sea posible, es mejor importar las exportaciones de la plantilla subyacente y volver a exportarlas para que los cambios en la versión de la plantilla no requieran actualizaciones manuales del código en su proyecto extendido.
Por ejemplo, en el archivo routes.jsx
en un proyecto generado, se observa que las rutas predeterminadas se importan a través de import {routes as _routes} from '@salesforce/retail-react-app/app/routes'
con la intención de que _routes
sea un convenio para indicar que estas rutas predeterminadas son administradas por una dependencia externa. Al igual que el archivo @salesforce/retail-react-app/app/routes.jsx
, nuestra implementación personalizada de routes.jsx
exporta rutas; agrega una ruta /
(Inicio). La nueva ruta tiene prioridad sobre la ruta predeterminada porque el enrutador React encuentra el primer artículo de un nombre de ruta determinado en la matriz de rutas.
Las importaciones relativas son el mejor enfoque para la mayoría de los proyectos que utilizan la extensibilidad de la plantilla. El comportamiento de importación de los archivos en su plantilla base (por ejemplo, @salesforce/retail-react-app
) tiene una lógica especial que le da prioridad al archivo en su directorio de reemplazos. Esta lógica de importación no se aplica a los archivos en su directorio de reemplazos. Por lo tanto, recomendamos utilizar importaciones relativas para la mayoría de las implementaciones.
Un problema a tener en cuenta con la extensibilidad de la plantilla es la importación accidental de dos archivos diferentes en conflicto. Un proyecto de PWA Kit se crea a través de @salesforce/pwa-kit-dev
, que utiliza webpack de manera interna. Hay un complemento en @salesforce/pwa-kit-dev
que habilita la funcionalidad de “reemplazo” de la extensibilidad de la plantilla. Este complemento inspecciona todas las solicitudes de archivos del webpack y formula dos preguntas:
- ¿Esta solicitud de archivo se origina en la plantilla base?
- ¿Este archivo existe en el directorio de reemplazos?
Si la respuesta a ambas preguntas es “sí”, la solicitud de archivo se reescribe en el momento de la compilación para que se dirija al archivo en el directorio de reemplazos.
Esta lógica no entra en juego para las solicitudes de archivos de webpack que se originan en el directorio de reemplazos. De este modo, es posible importar el mismo archivo tanto desde el directorio de reemplazos como desde la plantilla base. Si esta situación ocurre, por ejemplo, cuando @saleforce/retail-react-app/my-file
y <overrides directory>/my-file
se importan en el mismo paquete, el webpack arroja un error confuso similar a can’t find <export name> from <filename>
. El webpack arroja este error porque el paquete no sabe qué importación es el destino previsto para la inclusión del paquete.
Es importante evitar la importación de archivos desde la plantilla base cuando existe un archivo equivalente en los reemplazos, con una excepción notable. Como se explicó anteriormente con el ejemplo de código en la sección Archivos especiales y se demostró con constants.js
, es mejor importar la plantilla subyacente y volver a exportar todas sus exportaciones, reemplazando o adjuntando tantas exportaciones como sean necesarias.
Cuando es necesario reemplazar el componente app/components/_app/index.jsx
, hay muchos componentes globales, como Header
, Footer
y DrawerMenu
. Una vez implementado el reemplazo de _app/index.jsx
, cualquier intento de la plantilla base de importar este componente redirigirá la solicitud de archivo a <ccExtensibility.overridesDir>/app/components/_app/index.jsx
. ¡Pero hay un problema! Debido a que Header
y Footer
son importados por app/components/_app/index.jsx
, ¡la importación también debe actualizarse en _app/index.jsx
! De lo contrario, _app/index.jsx
importa a Header
y Footer
desde la plantilla base.
Las importaciones de ECMAScript que se originan en ccExtensibility.extends
son “mágicas” porque @salesforce/pwa-kit-dev
busca en varios lugares un archivo con ese nombre, pero dándole prioridad a ccExtensibility.overridesDir
.
Por otro lado, las importaciones que se originan en <ccExtensibility.overridesDir>/*
no tienen un comportamiento mágico, por ende, debe indicar los archivos que desea y, por lo tanto, <ccExtensibility.overridesDir>/app/components/header/index.jsx
debe importarse explícitamente en <ccExtensibility.overridesDir>/app/components/_app/index.jsx
de la siguiente manera:
No importe desde el paquete de esta manera porque omite el encabezado (Header) en su directorio de reemplazos:
Tenga en cuenta que routes.jsx
es un archivo especial. Forma el “punto de entrada”, según la terminología del webpack, para toda la aplicación. Si hay algo configurado de manera incorrecta en routes.jsx
, toda la aplicación fallará en la fase de compilación ya que la fragmentación basada en rutas en pwa-kit-dev
no se resuelve correctamente. Debido a esto, incluimos un ejemplo de cómo extender rutas correctamente al mezclar importaciones de @salesforce/retail-react-app/app/routes.jsx
por defecto y routes.jsx
local en overridesDir
.
Dado que las importaciones aquí están en la “cima”, si reemplaza estos archivos y luego reemplaza footer.jsx
, debe volver a _app/index.jsx
y modificar esa importación para que se dirija a su importación de la plantilla relativa.
Una limitación conocida del sistema de extensibilidad de la plantilla es que, en virtud de incorporar mágicamente, por ejemplo retail-react-app/constants
, cada vez que la plantilla base (@salesforce/retail-react-app
) importa este archivo, espera que se exporten los mismos valores.
Un archivo del directorio de reemplazos que no logra realizar las mismas exportaciones de ECMAScript que su equivalente en la plantilla base puede causar errores inesperados como el que se muestra a continuación.
Agregar un archivo constants.js
a su directorio de reemplazos de esta manera provoca un error:
Ejemplo de un mensaje de error:
El motivo de este error es que CAT_MENU_DEFAULT_ROOT_CATEGORY
es una exportación esperada en @salesforce/retail-react-app/components/_app/index.jsx
y en el proceso de reemplazarla con la única exportación CUSTOM_MESSAGE
que se menciona arriba, el reemplazo rompe el “contrato API” subyacente (la capacidad de los archivos de depender de un valor determinado, en este caso CAT_MENU_DEFAULT_ROOT_CATEGORY
) al ser exportado por constants.js
.
El enfoque correcto sería el siguiente. Este enfoque evita la omisión de CAT_MENU_DEFAULT_ROOT_CATEGORY
como exportación requerida y esperada. De esta forma mantenemos la coherencia de la API exportada.
Este enfoque solo funciona para cambios adicionales. En el siguiente ejemplo, agregamos una exportación CUSTOM_MESSAGE
que no está en las exportaciones del archivo retail-react-app/constants.js
subyacente.
Este enfoque funciona para el siguiente escenario, donde DEFAULT_LOCALE
es exportado por retail-react-app/constants
y estamos transformando ese valor:
Los enlaces de plantilla son una nueva forma de interactuar con la plantilla de la Retail React App que históricamente ha estado disponible mediante el comando npx pwa-kit-create-app
(ahora con el nombre de npx @salesforce/pwa-kit-create-app
).
Como parte de la característica de extensibilidad de la plantilla, se han agregado nuevos “enlaces de plantilla” a @salesforce/retail-react-app
que admiten la adición global de un pequeño subconjunto de componentes, que se enumeran en la siguiente lista. Por defecto, cada uno de estos componentes devuelve null
y está vacío de manera intencional para evitar que un proyecto de implementación de PWA Kit completado se llene innecesariamente. La base @salesforce/retail-react-app
nunca agrega funcionalidades a estos componentes. Los enlaces de plantilla siempre devuelven null
para garantizar que las implementaciones del cliente puedan “enlazarse” a la plantilla en estos lugares y así personalizar el proyecto sin tener que reemplazar más archivos de los necesarios.
A partir de @salesforce/retail-react-app@1.0.0
, se encuentran disponibles los siguientes enlaces de plantilla:
app/components/_app/partials/above-header.jsx
app/pages/product-list/partials/above-page-header.jsx
Al momento del lanzamiento de PWA Kit v3, solo hay una plantilla base extensible disponible para el público: @salesforce/retail-react-app
(se esperan más en el futuro).
Para usarlo como plantilla base, el proyecto de PWA Kit debe publicarse en npm y todas sus importaciones de ECMAScript deben tener un prefijo cuyo valor coincida con el nombre del paquete. Por ejemplo, @salesforce/retail-react-app
se publica en npm y sus importaciones tienen el prefijo @salesforce/retail-react-app
. Este prefijo es una referencia al directorio raíz del paquete, que es necesario para que funcione correctamente como plantilla base.
Para usar un proyecto de PWA Kit como plantilla base extensible, debe usar <npm package name>
para todas las importaciones. Por ejemplo, @salesforce/retail-react-app
agrega ccExtensibility
en package.json
, lo que garantiza que las referencias del entorno de desarrollo integrado (IDE) local (por ejemplo, @salesforce/retail-react-app/app/components/_app
) se resuelvan correctamente.
- Use la extensibilidad de la plantilla en lugar de copiar la plantilla de Retail React App y editarla.
- A medida que realice cambios, pruebe su proyecto con regularidad para identificar y solucionar cualquier problema que surja.
- Pruebe la funcionalidad personalizada en un entorno que no sea de producción antes de implementarla en producción.
- Itere en las invalidaciones según sea necesario para refinar el comportamiento.
En esta sección se proporcionan soluciones sugeridas para errores comunes que pueden surgir al usar la extensibilidad de plantillas.
Después de cambiar los archivos del proyecto, las actualizaciones no aparecen al obtener una vista previa del sitio.
Causa: No ha reiniciado el servidor local.
Solución sugerida: Ejecute npm start
y vuelva a obtener una vista previa del sitio.
Esto solo se aplica si usas una versión de PWA Kit anterior a la versión 3.
Causa: A su package.json
archivo le falta la configuración requerida ccExtensibility
.
Solución sugerida: Complete esta configuración en package.json
.
Causa: Faltan los archivos necesarios en el directorio de anulaciones (overridesDir
).
Solución sugerida: Asegúrese de que su proyecto incluya todos los archivos necesarios en el overrides
directorio. Consulte Archivos de proyecto requeridos.
Causa: Hay versiones conflictivas de dependencias entre la plantilla base y el proyecto
Solución sugerida: Asegúrese de que tanto la plantilla base como el proyecto usen la misma versión de las dependencias compartidas. Consulte Conflictos de versiones.