Estensibilità del modello
L'estensibilità del modello è una funzionalità introdotta in PWA Kit v3. Il suo obiettivo è facilitare la creare di progetti PWA Kit mediante la personalizzazione di modelli. È possibile personalizzare i modelli di base esistenti, come Retail React App, o crearne di propri. I membri della community PWA Kit sono invitati a condividere i propri modelli di base con gli altri membri.
L'estensibilità del modello consente di modificare un modello selezionato senza dover duplicare ogni file al suo interno.
L'estensibilità del modello è una funzionalità facoltativa. Tuttavia, i nuovi progetti generati dopo il 15 giugno 2023 vengono configurati automaticamente per l'uso dell'estensibilità del modello.
In PWA Kit v3 un progetto può avere un modello di base e una directory degli override, entrambi configurabili nel file package.json
del progetto. Per utilizzare l'estensibilità del modello è necessario dichiarare un modello di base con ccExtensibility.extends
in package.json
e una directory degli override con ccExtensibility.overridesDir
. (I dettagli di configurazione sono trattati nella sezione successiva.)
Un modello di base è un modulo npm contenente un progetto PWA Kit completamente funzionante, preconfigurato in modo che un altro progetto PWA Kit possa eseguire l'override di alcuni dei suoi file. A volte un modello di base è definito anche "app estensibile" o "app estendibile."
La directory degli override è una directory interna al progetto in cui è possibile archiviare i file da utilizzare come override dei file corrispondenti nel modello di base.
Si supponga di avere già definito una directory degli override e di avere specificato Retail React App come modello di base. Si supponga di voler eseguire l'override del componente home page di Retail React App. In Retail React App il codice del componente home page è in app/pages/home/index.jsx
nel pacchetto @salesforce/retail-react-app
. Per eseguire l'override di tale file è necessario ricreare lo stesso file nella directory dichiarata tramite ccExtensibility.overridesDir
in package.json
. Pertanto, il percorso del nuovo file sarà <ccExtensibility.overridesDir>/app/pages/home/index.jsx
.
Ogni volta che index.jsx
viene importato in uno dei file del pacchetto @salesforce/retail-react-app
, viene caricato il file della directory degli override anziché il file del pacchetto. Affinché avvenga l'override, solo la base del nome file deve corrispondere. Le estensioni dei file possono essere diverse.
Mentre si crea l'app, è possibile aggiungere gradualmente file dal modello di base alla directory degli override.
Maggiore è il numero di file di cui si esegue l'override, più complicato sarà tenere il passo con le modifiche nel modello di base.
Per vedere l'estensibilità del modello in azione, generare un nuovo progetto PWA Kit v3 eseguendo npx @salesforce/pwa-kit-create-app@latest --outputDir <path/to/new/local/project>
.
Il progetto generato utilizza il modello di base Retail React App, che offre un'app molto simile a quella presente in https://pwa-kit.mobify-storefront.com/.
Nei tutorial sull'estensibilità dei modelli si apprenderà come aggiungere alcune personalizzazioni comuni al proprio sito:
- Personalizzazione di un componente: estensibilità a livello di componente
- Personalizzazione di una pagina: estensibilità a livello di pagina
Le istruzioni in questa sezione presuppongono che si desideri abilitare l'estensibilità del modello per un progetto esistente non generato con la funzionalità già abilitata.
Per eseguire l'aggiornamento alla versione più recente di Retail React App, eseguire questo comando:
npm install @salesforce/retail-react-app@latest
Dopo aver eseguito il comando, si consiglia di testare il sito per verificare che funzioni come previsto.
Per definire un modello di base, aggiungere @salesforce/retail-react-app
(o un modello diverso) come dipendenza npm nel file package.json
del progetto.
Quindi aggiungere una chiave ccExtensibility
a package.json
con le chiavi e i valori seguenti:
Se si utilizza un modello di base diverso da Retail React App, non dimenticare di sostituire @salesforce/retail-react-app
con l'identificatore di pacchetto dell'altro modello.
È possibile sostituire i valori di overridesDir
con un nome di directory personalizzato, ma si consiglia di utilizzare overrides
per coerenza tra i progetti (e il codice di esempio).
Non elencare le stesse dipendenze npm sia nel progetto principale che nel modello di base. Verificare che le dipendenze elencate nel progetto package.json
siano diverse da quelle del modello di base. Ciò assicura che @salesforce/pwa-kit-dev
possa distinguere tra le due nella risoluzione delle dipendenze. Definire un modello di base nel package.json
del progetto principale come descritto in Configurazione. Il progetto principale non può ereditare da se stesso.
Il progetto non deve presentare conflitti di versione con le dipendenze npm del modello di base elencate nel relativo file package.json
. Se il modello sottostante utilizza @chakra-ui
, anche il progetto deve utilizzarlo come dipendenza e la versione deve corrispondere. Oltre a garantire la continuità operativa, questa precauzione impedisce il rigonfiamento accidentale del bundle dovuto a versioni in conflitto dello stesso pacchetto. Fa eccezione a questa regola il caso in cui siano stati aggiunti override per tutti i file del modello di base che importa una dipendenza specifica. In tal caso, la versione della dipendenza del modello di base non viene mai importata nel progetto perché sono stati eliminati tutti i file che la importano tramite gli override.
L'aggiunta di ulteriori dipendenze npm che non vengono utilizzate nel modello sottostante è permessa. 👌
Ogni progetto PWA Kit distribuito in Managed Runtime deve essere composto dai seguenti file:
<overridesDir>/app/main.jsx
<overridesDir>/app/ssr.js
<overridesDir>/app/routes.jsx
<overridesDir>/app/request-processor.js
config/default.js
(fa eccezione il caso in cui si utilizzi la chiavemobify
inpackage.json
per archiviare i dati di configurazione del sito)
Per personalizzare i comportamenti nel progetto, è normale eseguire l'override di questi file in @salesforce/retail-react-app
:
app/pages/home/index.jsx
: la rimozione dei contenuti di marketing Salesforce predefiniti dalla home page è una delle prime operazioni per quasi tutti i progetti.app/static/*
: si tratta di file predefiniti che generano le icone utilizzate dai browser desktop e mobili per il branding del sito. Aggiornarli in base al brand.app/constants.js
app/assets/svg/brand-logo.svg
: di questo file viene eseguito l'override nel progetto generatore. Seguire questo esempio per eseguire l'override delle altre icone del proprio progetto.
Lo scopo di questa impostazione di tipo "filesystem come API" è quello di aiutare a individuare i file sottostanti, copiarli, quindi personalizzare il comportamento e la logica. La suddivisione del codice in file più piccoli che organizzano molti sottocomponenti facilita l'individuazione del singolo comportamento che di cui si vuole eseguire l'override.
Tuttavia, a volte occorre copiare un file nei propri override per modificare solo una parte del suo comportamento. Quando possibile, è preferibile importare le esportazioni del modello sottostante e riesportarle in modo che le modifiche della versione del modello non richiedano aggiornamenti manuali di codice nel progetto esteso.
Ad esempio, nel file routes.jsx
in un progetto generato, si noti che le route predefinite vengono importate tramite import {routes as _routes} from '@salesforce/retail-react-app/app/routes'
con _routes
come convenzione per indicare che tali route predefinite sono gestite da una dipendenza esterna. Come per il file @salesforce/retail-react-app/app/routes.jsx
, la nostra implementazione personalizzata di routes.jsx
esporta le route, e aggiunge una route (Home)/
. La nuova route ha la precedenza su quella predefinita perché React Router trova il primo elemento di un determinato nome di percorso nella matrice di route.
Le importazioni relative rappresentano l'approccio migliore per la maggior parte dei progetti che utilizzano l'estensibilità del modello. Il comportamento di importazione per i file nel modello di base (ad esempio @salesforce/retail-react-app
) ha una logica speciale che dà la precedenza al file nella directory degli override. La logica di importazione non si applica ai file nella directory degli override. Pertanto, per la maggior parte delle implementazioni si consiglia di utilizzare le importazioni relative.
Un possibile problema a cui occorre prestare attenzione utilizzando l'estensione del modello è l'importazione accidentale di due file differenti in conflitto tra loro. Un progetto PWA Kit viene creato tramite @salesforce/pwa-kit-dev
, che utilizza Webpack internamente. In @salesforce/pwa-kit-dev
è presente un plug-in che abilita la funzionalità "override" dell'estensibilità del modello. Il plug-in ispeziona tutte le richieste di file Webpack e pone due domande:
- Questa richiesta di file ha origine nel modello di base?
- Questo file esiste nella directory degli override?
Se la risposta a entrambe le domande è affermativa, la richiesta di file viene riscritta in fase di compilazione per puntare al file nella directory degli override.
Questa logica non entra in gioco per le richieste di file Webpack che hanno origine nella directory degli override. Pertanto, è possibile importare lo stesso file sia dalla directory degli override sia dal modello di base. Se si verifica la situazione in cui, ad esempio, @saleforce/retail-react-app/my-file
e <overrides directory>/my-file
vengono importati nello stesso bundle, Webpack restituisce un errore di confusione simile a can’t find <export name> from <filename>
. Webpack restituisce questo errore perché il bundle non sa quale importazione sia la destinazione prevista per la sua inclusione.
È importante evitare di importare file dal modello di base quando esiste un file equivalente negli override, con un'eccezione degna di nota. Come illustrato in precedenza con l'esempio di codice nella sezione File speciali e dimostrato con constants.js
, è preferibile importare il modello sottostante e riesportare tutte le relative esportazioni, con l'override o l'aggiunta del numero minimo di esportazioni necessarie.
Se occorre eseguire l'override del componente app/components/_app/index.jsx
, sono disponibili numerosi componenti globali, ad esempio Header
, Footer
e DrawerMenu
. Una volta effettuato l'override di _app/index.jsx
, qualsiasi tentativo da parte del modello di base di importare questo componente reindirizzerà la richiesta di file a <ccExtensibility.overridesDir>/app/components/_app/index.jsx
. Esiste tuttavia un problema. Poiché Header
e Footer
sono importati da app/components/_app/index.jsx
, l'importazione deve essere aggiornata anche in _app/index.jsx
. In caso contrario, _app/index.jsx
importa Header
e Footer
dal modello di base.
Le importazioni ECMAScript che hanno origine in ccExtensibility.extends
hanno un comportamento per così dire "magico", in quanto @salesforce/pwa-kit-dev
verifica in più ubicazioni se è presente un file con tale nome, dando la precedenza a ccExtensibility.overridesDir
.
Al contrario, le importazioni che hanno origine in <ccExtensibility.overridesDir>/*
non hanno un comportamento di questo tipo e, di conseguenza, è necessario scegliere come destinazione i file desiderati. <ccExtensibility.overridesDir>/app/components/header/index.jsx
deve quindi essere importato in modo esplicito in <ccExtensibility.overridesDir>/app/components/_app/index.jsx
, come descritto di seguito:
Non effettuare questo tipo di importazioni dal pacchetto perché in tal modo viene ignorata l'intestazione nella directory degli override:
Si noti che routes.jsx
è un file speciale. Nella terminologia Webpack costituisce l'"entryPoint" per l'intera applicazione. In caso di impostazioni errate in routes.jsx
, l'intera fase di compilazione dell'app non andrà a buon fine poiché la suddivisione in blocchi basata su route in pwa-kit-dev
non si risolve correttamente. Per questo motivo, viene incluso un esempio di come estendere correttamente le route unendo le importazioni da @salesforce/retail-react-app/app/routes.jsx
predefinito e un routes.jsx
locale in overridesDir
.
Poiché le importazioni in questo esempio sono "in cima alla struttura", se si esegue l'override di questi file e successivamente di footer.jsx
, è necessario tornare a _app/index.jsx
e modificare l'importazione in modo che punti alla relativa importazione del modello.
Una limitazione nota del sistema di estensibilità del modello è data dal fatto che, in virtù dell'inserimento "magico", ad esempio retail-react-app/constants
, ogni volta che il modello di base (@salesforce/retail-react-app
) importa questo file, si aspetta che vengano esportati gli stessi valori.
Un file negli override che non riesce ad esportare le stesse esportazioni ECMAScript del suo equivalente nel modello di base può causare errori imprevisti come quello indicato di seguito.
L'aggiunta di un file constants.js
alla directory degli override come illustrato di seguito provoca un errore:
Esempio di messaggio di errore:
Il motivo di questo errore è che CAT_MENU_DEFAULT_ROOT_CATEGORY
è un'esportazione prevista in @salesforce/retail-react-app/components/_app/index.jsx
e, durante l'override con la sola esportazione CUSTOM_MESSAGE
sopra indicata, l'override stesso interrompe il "contratto API" sottostante (la capacità dei file di dipendere da un determinato valore, in questo caso CAT_MENU_DEFAULT_ROOT_CATEGORY
) esportato da constants.js
.
Il seguente approccio è quello corretto ed evita l'omissione di CAT_MENU_DEFAULT_ROOT_CATEGORY
come esportazione obbligatoria e prevista. In questo modo viene mantenuta la coerenza dell'API esportata.
Questo approccio è applicabile solo in caso di modifiche additive. Nell'esempio seguente viene aggiunta un'esportazione CUSTOM_MESSAGE
non presente tra le esportazioni del file retail-react-app/constants.js
sottostante.
Questo approccio è valido per il seguente scenario, in cui DEFAULT_LOCALE
viene esportato da retail-react-app/constants
e tale valore viene modificato:
Gli hook di modello rappresentano un nuovo modo di interagire con il modello Retail React App, che storicamente era disponibile tramite il comando npx pwa-kit-create-app
(ora rinominato npx @salesforce/pwa-kit-create-app
).
Nell'ambito della funzionalità di estensibilità del modello, sono stati aggiunti a @salesforce/retail-react-app
nuovi "hook di modello" che supportano l'aggiunta globale di un piccolo sottoinsieme di componenti, riportati nell'elenco seguente. Per impostazione predefinita, ciascuno di questi componenti restituisce null
ed è intenzionalmente vuoto per evitare il rigonfiamento non necessario di un progetto di implementazione PWA Kit completato. @salesforce/retail-react-app
di base non aggiunge mai alcuna funzionalità a questi componenti. Gli hook di modello restituiscono sempre null
per consentire alle implementazioni del cliente di "agganciarsi" al modello in questi punti in modo da personalizzare il progetto senza dover eseguire l'override di più file del necessario.
A partire dalla versione @salesforce/retail-react-app@1.0.0
sono disponibili i seguenti hook di modello:
app/components/_app/partials/above-header.jsx
app/pages/product-list/partials/above-page-header.jsx
Al momento del rilascio di PWA Kit v3, un solo modello di base estensibile è disponibile pubblicamente: @salesforce/retail-react-app
(altri sono previsti in futuro).
Per essere utilizzato come modello di base, un progetto PWA Kit deve essere pubblicato su npm e tutte le relative importazioni ECMAScript devono essere precedute da un valore corrispondente al nome del pacchetto. Ad esempio, @salesforce/retail-react-app
viene pubblicato su npm e le relative importazioni sono precedute da @salesforce/retail-react-app
. Questo prefisso è un riferimento alla directory radice del pacchetto, necessaria per il suo corretto funzionamento come modello di base.
Per utilizzare un progetto PWA Kit come modello di base estensibile, è necessario utilizzare <npm package name>
per tutte le sue importazioni. Ad esempio, @salesforce/retail-react-app
aggiunge ccExtensibility
in package.json
, che garantisce la corretta risoluzione dei riferimenti IDE locali (ad esempio @salesforce/retail-react-app/app/components/_app
).
- Utilizzare l'estensibilità del modello anziché copiare il modello Retail React App e modificarlo.
- Man mano che si apportano modifiche, testare regolarmente il progetto per identificare e risolvere eventuali problemi che si presentano.
- Testare la funzionalità personalizzata in un ambiente non di produzione prima di distribuirla nell'ambiente Production.
- Eseguire l'iterazione degli override in base alle proprie esigenze per affinare il comportamento richiesto.
In questa sezione vengono suggerite soluzioni per gli errori comuni che possono verificarsi durante l'uso dell'estensibilità del modello.
Dopo aver modificato i file nel progetto, gli aggiornamenti non appaiono in fase di anteprima del sito.
Causa: Non è stato riavviato il server locale.
Soluzione suggerita: Eseguire npm start
ed eseguire di nuovo l'anteprima del sito.
Questo vale solo se si utilizza una versione di PWA Kit precedente alla 3.
Causa: Al file package.json
manca la configurazione ccExtensibility
richiesta.
Soluzione suggerita: Completare questa Configurazione in package.json
.
Causa: I file richiesti non sono presenti nella directory degli override (overridesDir
).
Soluzione suggerita: Assicurarsi che il progetto includa tutti i file richiesti nella directory overrides
. Vedere File di progetto richiesti.
Causa: Esistono versioni contrastanti delle dipendenze tra il modello di base e il proprio progetto
Soluzione suggerita: Assicurarsi che sia il modello di base che il progetto utilizzino la stessa versione delle dipendenze condivise. Vedere Conflitti di versione.