Erweiterbarkeit von Vorlagen

Die Erweiterbarkeit von Vorlagen ist eine Funktionalität, die in PWA Kit v3 eingeführt wurde. Ziel dieser Funktionalität ist, Ihnen mithilfe von anpassbaren Vorlagen die Erstellung von PWA Kit-Projekten zu erleichtern. Sie können vorhandene Basisvorlagen wie die Retail React App anpassen oder Ihre eigene Vorlage erstellen. Wir regen die Mitglieder der PWA Kit Community an, ihre Basisvorlagen untereinander auszutauschen.

Die Erweiterbarkeit von Vorlagen hilft Ihnen, eine ausgewählte Vorlage zu ändern, ohne dass Sie alle darin enthaltenen Dateien duplizieren müssen.

Die Erweiterbarkeit von Vorlagen ist eine optionale Funktionalität. Allerdings werde nach dem 15. Juni 2023 erstellte Projekte automatisch für die Anwendung der Vorlagenerweiterbarkeit konfiguriert.

In einem Projekt in PWA Kit v3 kann es eine Basisvorlage und ein Overrides-Verzeichnis geben, die beide in der Datei package.json des Projekts konfiguriert werden. Um die Erweiterbarkeit von Vorlagen zu nutzen, müssen Sie mit ccExtensibility.extends in package.json eine Basisvorlage und mit ccExtensibility.overridesDir ein Overrides-Verzeichnis erklären. (Details zur Konfiguration finden Sie im nächsten Abschnitt.)

Eine Basisvorlage ist ein npm-Modul, das ein vollständig funktionsfähiges PWA Kit-Projekt enthält. Dieses Projekt wurde so vorkonfiguriert, dass ein anderes PWA Kit-Projekt einige seiner Dateien überschreiben kann. Manchmal wird eine Basisvorlage auch als "erweiterbare App" bezeichnet."

Das Overrides-Verzeichnis ist ein Verzeichnis innerhalb Ihres Projekts, in dem Sie Dateien speichern können, die entsprechende Dateien in der Basisvorlage überschreiben.

Angenommen, Sie haben bereits ein Overrides-Verzeichnis definiert und die Retail React App als Ihre Basisvorlage festgelegt. Nehmen wir weiter an, dass Sie die Startseitenkomponente der Retail React App überschreiben möchten. In der Retail React App finden Sie den Code für die Startseitenkomponente in der Datei app/pages/home/index.jsx im Paket @salesforce/retail-react-app. Um diese Datei zu überschreiben, müssen Sie im über ccExtensibility.overridesDir in package.json erklärten Verzeichnis die gleiche Datei erstellen. Dementsprechend lautet der Pfad für die neue Datei <ccExtensibility.overridesDir>/app/pages/home/index.jsx.

Jedes Mal, wenn jetzt index.jsx in eine andere Datei im @salesforce/retail-react-app-Paket importiert wird, wird statt der Datei im Paket die Datei im Overrides-Verzeichnis geladen. Für die Überschreibung reicht es aus, wenn nur der Basisname der Dateien identisch ist. Die Dateierweiterungen können voneinander abweichen.

Bei der Erstellung Ihrer App können Sie Dateien nach und nach aus der Basisvorlage zu Ihrem Overrides-Verzeichnis hinzufügen.

Je mehr Dateien Sie überschreiben, desto mehr Aufwand ist erforderlich, um an der Basisvorlage vorgenommene Änderungen abzugleichen.

Um die Erweiterbarkeit von Vorlagen in Aktion zu sehen, generieren Sie ein neues PWA Kit v3-Projekt, indem Sie npx @salesforce/pwa-kit-create-app@latest --outputDir <path/to/new/local/project> ausführen.

Das generierte Projekt verwendet die Basisvorlage Retail React App. Die Ergebnis ist eine App, die mehr oder weniger genauso aussieht wie die auf https://pwa-kit.mobify-storefront.com/ verfügbare App.

Die Anweisungen in diesem Abschnitt gehen davon aus, dass Sie die Erweiterbarkeit von Vorlagen für ein vorhandenes Projekt aktivieren wollen, in dem diese Funktionalität bei der Generierung nicht aktiviert wurde.

Fügen Sie zur Definition einer Basisvorlage in der Datei package.json Ihres Projekts @salesforce/retail-react-app (oder eine andere Vorlage) als npm-Abhängigkeit hinzu.

Fügen Sie dann in package.json einen ccExtensibility-Schlüssel mit den folgenden Schlüsseln und Werten hinzu:

Wenn Sie statt der Retail React App eine andere Basisvorlage verwenden, achten Sie darauf, @salesforce/retail-react-app durch die Paketkennung dieser anderen Vorlage zu ersetzen.

Sie können die Werte für overridesDir durch einen benutzerdefinierten Verzeichnisnamen ersetzen. Zur Gewährleistung der Konsistenz zwischen Projekten (und unserem Beispielcode) sollten Sie jedoch overrides verwenden.

Die gleiche Abhängigkeit kann nicht sowohl im Hauptprojekt als auch in der Basisvorlage enthalten sein. Die beiden PWA Kit-Apps müssen verschieden sein, damit @salesforce/pwa-kit-dev zwischen dem Hauptprojekt und der Basisvorlage unterscheiden kann. (Das Hauptprojekt muss eine Basisvorlage definieren und kann nicht von sich selbst erben.)

Die Version Ihres Projekts darf nicht zu Versionskonflikten mit den npm-Abhängigkeiten der Basisvorlage führen, die in deren package.json-Datei aufgeführt sind. Wenn die zugrunde liegende Vorlage @chakra-ui verwendet, muss diese Abhängigkeit auch in Ihrem Projekt enthalten sein. Diese Vorsichtsmaßnahme verhindert eine unbeabsichtigte Überfrachtung in Ihrem Bündel (ganz zu schweigen von Problemen mit Funktionen) aufgrund der Verwendung miteinander in Konflikt stehender Versionen im selben Paket. Von dieser Regel gibt es eine Ausnahme: Wenn Sie Überschreibungen für alle Dateien in der Basisvorlage hinzugefügt haben, die eine bestimmte Abhängigkeit importiert. In diesem Fall wird die in der Basisvorlage vorhandene Version der Abhängigkeit niemals in Ihr Projekt importiert, da Sie alle Dateien, die diese Abhängigkeit importieren, durch Überschreibung eliminiert haben.

Das Hinzufügen zusätzlicher npm-Abhängigkeiten, die nicht in der zugrunde liegenden Vorlage verwendet werden, verursacht keinerlei Probleme. 👌

Jedes in Managed Runtime bereitgestellte PWA Kit-Projekt muss die folgenden Dateien enthalten:

  • <overridesDir>/app/main.jsx
  • <overridesDir>/app/ssr.js
  • <overridesDir>/app/routes.jsx
  • <overridesDir>/app/request-processor.js
  • config/default.js (Ausnahme: Wenn Sie den Schlüssel mobify in package.json zur Speicherung der Config-Daten Ihrer Website verwenden.)

Um Verhalten im Projekt anzupassen, ist es üblich, diese Dateien in @salesforce/retail-react-app zu überschreiben:

  • app/pages/home/index.jsx: Das Entfernen der von Salesforce bereitgestellten Standard-Marketinginhalte aus der Startseite ist in fast allen Projekten der erste Schritt.
  • app/static/*: Diese Dateien sind Standarddateien mit Branding-Symbolen für Ihre Website in Desktop- und mobilen Browsern. Ersetzen Sie diese Symbole durch die Ihrer eigenen Marke.
  • app/constants.js
  • app/assets/svg/brand-logo.svg: Diese Datei wird im Generator-Projekt überschrieben. Folgen Sie den Schritten in diesem Beispiel, um andere Symbole in Ihrem Projekt zu überschreiben.

Dieses "Dateisystem als eine API" soll Ihnen helfen, die zugrunde liegenden Dateien zu finden, sie zu kopieren und dann das Verhalten und die Logik anzupassen. Indem der Code in kleinere Dateien aufgespalten wird, die viele Unterkomponenten orchestrieren, können Sie leichter gezielt das Verhalten herausgreifen, das Sie überschreiben wollen.

Allerdings müssen Sie manchmal eine Datei in Ihre Überschreibungen kopieren, um nur einen Teil des Verhaltens in dieser Datei zu ändern. Wann immer möglich, sollten Sie die zugrunde liegenden Vorlagenexporte importierten und anschließend erneut exportieren, damit Änderungen an der Vorlagenversion in Ihrem erweiterten Projekt nicht manuell aktualisiert werden müssen.

In der Datei routes.jsx in einem generierten Projekt können Sie beispielsweise sehen, dass die Standardrouten über import {routes as _routes} from '@salesforce/retail-react-app/app/routes' importiert werden, wobei _routes als Konvention angibt, dass diese Standardrouten von einer externen Abhängigkeit verwaltet werden. Genau wie die Datei @salesforce/retail-react-app/app/routes.jsx exportiert auch unsere benutzerdefinierte Implementierung von routes.jsx Routen; sie fügt eine /-(Startseiten)-Route hinzu. Die neue Route erhält Vorrang vor der Standardroute, da React Router das erste Element eines bestimmten Pfadnamens im Routen-Array findet.

Relative Importe sind der beste Ansatz für die meisten Projekte, die die Erweiterbarkeit von Vorlagen nutzen. Das Importverhalten für die Dateien in Ihrer Basisvorlage (zum Beispiel @salesforce/retail-react-app) wendet eine besondere Logik an, die der Datei in Ihrem Overrides-Verzeichnis den Vorrang gibt. Diese Importlogik gilt nicht für die Dateien in Ihrem Overrides-Verzeichnis. Deshalb sollten Sie bei den meisten Implementierungen relative Importe verwenden.

Ein Problem, das bei der Erweiterbarkeit von Vorlagen auftreten kann, ist, dass versehentlich zwei verschiedene, miteinander in Konflikt stehende Dateien importiert werden. Ein PWA Kit-Projekt wird über @salesforce/pwa-kit-dev erstellt, das Webpack intern anwendet. In @salesforce/pwa-kit-dev gibt es ein Plug-in, das die "Override"-Funktionalität der Erweiterbarkeit von Vorlagen aktiviert. Dieses Plug-in inspiziert alle Webpack-Dateianfragen und stellt zwei Fragen:

  1. Stammt diese Dateianfrage ursprünglich aus der Basisvorlage?
  2. Ist diese Datei im Overrides-Verzeichnis vorhanden?

Wenn beide Fragen mit Ja beantwortet werden, wird die Dateianfrage zum Zeitpunkt des Builds umgeschrieben, sodass sie jetzt auf die Datei im Overrides-Verzeichnis zeigt.

Diese Logik wird nicht auf Webpack-Dateianfragen angewendet, die aus dem Overrides-Verzeichnis stammen. Daher ist es möglich, die gleiche Datei sowohl aus dem Overrides-Verzeichnis als auch aus der Basisvorlage zu importieren. Wenn in einer derartigen Situation beispielsweise @saleforce/retail-react-app/my-file und <overrides directory>/my-file in dasselbe Bündel importiert werden, gibt Webpack eine verwirrende Fehlermeldung wie etwa can’t find <export name> from <filename> aus. Webpack gibt diese Fehlermeldung aus, da das Bündel nicht weiß, welcher Import das beabsichtigte Ziel für den Einschluss in das Bündel ist.

Es ist wichtig, Dateien nicht aus der Basisvorlage zu importieren, wenn eine entsprechende Datei bereits im Overrides-Verzeichnis vorhanden ist - mit einer wichtigen Ausnahme. Wie zuvor im Codebeispiel im Abschnitt Besondere Dateien behandelt und mit constants.js gezeigt, ist es besser, die zugrunde liegende Vorlage zu importieren und alle ihre Exporte erneut zu exportieren und dabei so wenige Exporte wie nötig zu überschreiben bzw. anzuhängen.

Wenn Sie die Komponente app/components/_app/index.jsx überschreiben müssen, gilt es viele allgemeine Komponenten wie Header, Footer und DrawerMenu zu berücksichtigen. Nach erfolgter Überschreibung von _app/index.jsx wird bei jedem Versuch der Basisvorlage, diese Komponente zu importieren, die Dateianfrage an <ccExtensibility.overridesDir>/app/components/_app/index.jsx umgeleitet. Doch die Sache hat einen Haken! Da Header und Footer von app/components/_app/index.jsx importiert werden, muss der Import ebenfalls in _app/index.jsx aktualisiert werden. Ansonsten importiert _app/index.jsx Header und Footer aus der Basisvorlage.

ECMAScript-Importe mit Ursprung in ccExtensibility.extends sind "magisch", da @salesforce/pwa-kit-dev an mehreren Orten nach einer Datei dieses namens sucht, wobei ccExtensibility.overridesDir zuerst übergeprüft wird.

Importen mit Ursprung in <ccExtensibility.overridesDir>/* dagegen fehlt dieses magische Verhalten. Deshalb müssen Sie gezielt auf die gewünschten Dateien verweisen, und <ccExtensibility.overridesDir>/app/components/header/index.jsx muss wie folgt ausdrücklich in <ccExtensibility.overridesDir>/app/components/_app/index.jsx importiert werden:

Importieren Sie nicht auf diese Weise aus dem Paket, da dadurch der Header in Ihrem Overrides-Verzeichnis umgangen wird:

Beachten Sie, dass routes.jsx eine besondere Datei ist. Sie bildet den "entryPoint", wie es in der Webpack-Terminologie heißt, für die gesamte Anwendung. Wenn Sie in routes.jsx etwas nicht ordnungsgemäß eingerichtet haben, schlägt Ihre gesamte App in der Kompilierungsphase fehl, da das routenbasierte Chunking in pwa-kit-dev nicht richtig aufgelöst wird. Aus diesem Grund schließen wir ein Beispiel dazu ein, wie Sie Routen ordnungsgemäß erweitern, indem Sie Importe aus der Standarddatei @salesforce/retail-react-app/app/routes.jsx und einer lokalen Datei routes.jsx im overridesDir mischen.

Da sich die Importe oben im Verzeichnis befinden, müssen Sie zu _app/index.jsx zurückkehren und diesen Import so modifizieren, dass er auf den relative Vorlagenimport verweist, wenn Sie diese Dateien überschreiben und dann footer.jsx überschreiben.

Eine bekannte Einschränkung des Systems der erweiterbaren Vorlagen ist, dass die Basisvorlage (@salesforce/retail-react-app) jedes Mal, wenn sie beispielsweise retail-react-app/constants auf magische Weise importiert, erwartet, dass dieselben Werte auch exportiert werden.

Eine Datei im Overrides-Verzeichnis, die nicht dieselben ECMAScript-Exporte wie ihr Äquivalent in der Basisvorlage exportiert, kann unerwartete Fehler wie den im Folgenden aufgeführten verursachen.

Wenn Sie in Ihrem Overrides-Verzeichnis eine constants.js-Datei hinzufügen, wird ein Fehler ausgelöst:

Beispiel der Fehlermeldung:

Die Ursache dieses Fehlers ist, dass CAT_MENU_DEFAULT_ROOT_CATEGORY ein erwarteter Export in @salesforce/retail-react-app/components/_app/index.jsx ist und dass Ihre Überschreibung während des Überschreibungsprozesses dieser Datei mit dem obigen einzigen Export CUSTOM_MESSAGE den zugrunde liegenden, von constants.js exportierten "API-Vertrag" (die Fähigkeit von Dateien, von einem vorgegebenen Wert abhängig zu sein, in diesem Fall von CAT_MENU_DEFAULT_ROOT_CATEGORY) bricht.

Im Folgenden wird der richtige Ansatz beschrieben. Dieser Ansatz vermeidet die Auslassung von CAT_MENU_DEFAULT_ROOT_CATEGORY als ein erforderlicher und erwarteter Export. Auf diese Weise bewahren wir die Konsistenz der exportierten API.

Dieser Ansatz funktioniert nur für additive Änderungen. Im folgenden Beispiel fügen wir einen CUSTOM_MESSAGE-Export hinzu, der sich nicht in den Exporten der zugrunde liegenden Datei retail-react-app/constants.js befindet.

Dieser Ansatz funktioniert im folgenden Szenario, indem DEFAULT_LOCALE von retail-react-app/constants exportiert wird und wir diesen Wert mutieren:

Vorlagen-Hooks sind eine neue Methode für die Interaktion mit der Retail React App-Vorlage, die zuvor über den Befehl npx pwa-kit-create-app (jetzt in npx @salesforce/pwa-kit-create-app umbenannt) verfügbar war.

Im Rahmen der Funktionalität der erweiterbaren Vorlagen wurden in @salesforce/retail-react-app neue "Vorlagen-Hooks" hinzugefügt, die das allgemeine Hinzufügen einer kleinen Teilmenge von in der folgenden Liste aufgeführten Komponenten unterstützen. Standardmäßig gibt jede dieser Komponenten, die zur Vermeidung einer unnötigen Überfrachtung eines abgeschlossenen PWA Kit-Implementierungsprojekts absichtlich leer gelassen werden, null zurück. Die Basis-@salesforce/retail-react-app fügt diesen Komponenten niemals Funktionalitäten hinzu. Vorlagen-Hooks geben immer null zurück, um sicherzustellen, dass sich Kundenimplementierungen an diesen Stellen in die Vorlage "einhaken" können, um das Projekt anzupassen, ohne mehr Dateien als unbedingt notwendig überschreiben zu müssen.

Für @salesforce/retail-react-app@1.0.0 sind die folgenden Vorlagen-Hooks verfügbar:

  • app/components/_app/partials/above-header.jsx
  • app/pages/product-list/partials/above-page-header.jsx

Zum Zeitpunkt der Release von PWA Kit v3 gibt es nur eine erweiterbare Basisvorlage, die öffentlich verfügbar ist: @salesforce/retail-react-app (weitere sind geplant).

Um als Basisvorlage verwendet zu werden, muss ein PWA Kit-Projekt in npm veröffentlicht werden und alle seiner ECMAScript-Importe müssen ein Präfix mit einem Wert erhalten, der dem Namen des Pakets entspricht. Beispiel: @salesforce/retail-react-app ist in npm veröffentlich und die zugehörigen Importe erhalten das Präfix @salesforce/retail-react-app. Dieses Präfix ist ein Verweis auf das Stammverzeichnis des Pakets; dies ist erforderlich, damit es ordnungsgemäß als Basisvorlage fungieren kann.

Um ein PWA Kit-Projekt als eine erweiterbare Basisvorlage zu nutzen, muss <npm package name> für alle zugehörigen Importe verwendet werden. Beispiel: @salesforce/retail-react-app fügt ccExtensibility in package.json hinzu, was gewährleistet, dass lokale IDE-Referenzen (z. B. @salesforce/retail-react-app/app/components/_app) ordnungsgemäß aufgelöst werden.