chore: example BFF integration#21647
Conversation
…r runtime URL injection
Extends the existing CCv2 meta-tag mechanism with two new tags so that
OCC_BASE_URL and BFF_BASE_URL can be injected at deploy time without
rebuilding or mutating built files — fixing PWA Service Worker hash
breakage and CDN cache invalidation caused by the current approach.
- Add occBaseUrlFromMetaTagFactory reading <meta name="occ-base-url">
as a short-form alias for backend.occ.baseUrl (legacy occ-backend-base-url
tag still supported for backward compatibility)
- Add bffServerConfigFromMetaTagFactory reading <meta name="bff-base-url">
contributing backend.bff.baseUrl to the Spartacus config
- Extend BackendConfig with bff?: { baseUrl?: string } in OccConfig
- Add BFF_BASE_URL injection token and BffHttpService to the demo app
as reference implementation for calling BFF tRPC procedures
- Wire CX_BFF_BASE_URL through environment model; dev-server proxy
(proxy.conf.js) reads it to forward /bff/* to the real BFF, keeping
browser calls relative and CORS-free
- Add docs/backend-url-configuration.md for customer guidance
spartacus
|
||||||||||||||||||||||||||||
| Project |
spartacus
|
| Branch Review |
feat/CXSPA-13587
|
| Run status |
|
| Run duration | 04m 09s |
| Commit |
|
| Committer | Norbert Papp |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
3
|
|
|
0
|
|
|
0
|
|
|
103
|
| View all changes introduced in this branch ↗︎ | |
…e implementation The core library changes (new meta tag factories, BackendConfig.bff, schematics) are not ready for release in June. Reverting them to develop baseline. All BFF integration code remains in projects/storefrontapp as a reference implementation documented in docs/backend-url-configuration.md. The doc covers: index.html meta tag setup, BFF_BASE_URL token, BffHttpService, SSR configuration, local dev proxy, and manual substitution testing.
| export class BffHttpService { | ||
| protected readonly http = inject(HttpClient); | ||
| protected readonly bffBaseUrl = inject(BFF_BASE_URL); | ||
| protected readonly authStorage = inject(AuthStorageService); |
There was a problem hiding this comment.
[NITPICK]
For simple demo purposes, AuthStorageService should be fine.
I'm curious how the automatic token renewal works in this case. Whether it works at all.
Though for first PoC it might be not crucial.
AFAIK the AuthHttpInterceptor (with its AuthHttpHeaderService) attempts to renew tokens "on the fly" whenever detected a HTTP error response about invalid token.
| .query<{ | ||
| message: string; | ||
| }>( | ||
| 'sample.sayHello', |
There was a problem hiding this comment.
[QUESTION]
For demo purposes, didn't we want to actually call some auto-generated OCC procedure?
To setup a Vivaldi BFF app with OCC, you need to either scaffold a fresh BFF Nx repo with OCC support - to generate its procedures and plug into the trpc router.
Or alternatively you might want to reuse existing old generated occ procedures inside spa-bff repo. You'd just need to plug them into the trpc router there:
You'd need to add to the spa-bff apps/bff/ser/api/routers/root.ts::
export const rootRouter = router({
+ occ: {
+ v2: t.useProcedures(procedures.occ.v2),
+ },
/*...*/and in packages/procedures/bff/index.ts:
+ import occRouter from './occ';
export default {
+ occ: occRouter,then you could call e.g. a procedure from the occ.v2 namespace.
I guess e.g. this on (unless I made a typo; I didn't verify it):
'occ.v2.miscs.getLanguages'
(for more, see sources of spa-bff repo)
There was a problem hiding this comment.
I went with the sayHello procedure since it comes with the BFF out of the box. If we want to add an OCC call instead, I assume we'd need to document how to configure the BFF against an OCC environment. I'll look into it though.
There was a problem hiding this comment.
To my understanding, Bill wanted to showcase an example integration of spa-classic with CCV2 (OCC api) through BFF. But maybe I misunderstood.
Would you mind double-checking with Gil and Bill?
What we want to showcase:
a) partial Spartacus -> BFF integration
b) full Spartacus -> BFF -> OCC integration
There was a problem hiding this comment.
I added projects/storefrontapp/src/app/bff/examples/occ-base-sites.component.ts to have an example for calling getBaseSites from occ.
…on in spa-classic-bff-reference-implementation.md
Summary
This PR is a reference implementation and documentation only. No core library changes are included — all code lives in
projects/storefrontappas a working example that customers can follow.The implementation demonstrates how to integrate a Vivaldi BFF with Spartacus Classic using CCv2's existing meta tag substitution mechanism.
Demo app changes (
storefrontapp)src/index.html— adds<meta name="bff-base-url" content="BFF_BASE_URL_VALUE" />— CCv2 replaces the placeholder at deploy time via "Connect to BFF"bff/bff-base-url.token.ts—InjectionTokenthat readsbff-base-urlmeta tag at Angular bootstrap; falls back to/bff/apifor local devbff/bff-http.service.ts— generic HTTP client for BFF tRPC procedures (query + mutate), forwards OCC Bearer token viaAuthStorageServicebff/examples/say-hello.component.ts— demo route/bff-say-hellocalling a custom BFF procedure (sample.sayHello) withnameinput andx-app-customheaderbff/examples/occ-base-sites.component.ts— demo route/occ-base-sitescalling OCC's/basesitesendpoint via BFF (occ.getBaseSitesprocedure)bff/examples/bff-example.providers.ts— lazy route provider for both demo routes, spread intoapp.module.tsapp.module.server.ts— SSR override: providesBFF_BASE_URLfromprocess.env['BFF_BASE_URL'](Node has no document origin for relative URLs)proxy.conf.js— replaces staticproxy.conf.json; readsCX_BFF_BASE_URLat dev-server startup to set the proxy target dynamically, keeping browser calls relative (/bff/api) and CORS-freeproject.json— pointsservetarget atproxy.conf.jsCX_BFF_BASE_URLwired through.env-cmdrcand environment modelDocumentation
docs/backend-url-configuration.md— complete step-by-step guide covering every file, with full code examples, CCv2 deployment notes, and local testing instructionsKey findings from CCv2 testing
CCv2 platform URL injection
The platform's
substitute-caddy.shreplaces only two placeholders:OCC_BACKEND_BASE_URL_VALUE→$OCC_BASE_URL(user sets via VariableSet)BFF_BASE_URL_VALUE→$BFF_BASE_URL(platform auto-injects/bff/on "Connect to BFF")OCC_BASE_URL_VALUE/occ-base-urlare not supported —occ-backend-base-urlremains the only OCC placeholder.OCC URL must have a CA-signed certificate for BFF use
The BFF runs as Node.js on CCv2. Vivaldi builds the HTTPS agent as
new Agent({ rejectUnauthorized: !isDev })— locallyisDev=trueaccepts self-signed certs, on CCv2isDev=falserejects them. There is no per-destination TLS override in Vivaldi's API.Consequence:
OCC_BASE_URLin the BFF VariableSet must point to an OCC hostname with a CA-signed certificate (e.g.https://api.xxx.model-t.myhybris.cloud). Raw IP addresses with self-signed certs (e.g.https://40.x.x.x:9002) work in the browser (manual exception) but are rejected by the BFF container.provideConfig()overrides meta tagsSpartacus config priority:
provideConfig()> meta tag factories. Customers must remove any hardcodedbackend.occ.baseUrlfrom theirspartacus-configuration.module.tsto allow CCv2 runtime injection to work.Test plan
vivaldi dev bff) + storefront (npm run start), navigate to/bff-say-hello— response displayed without CORS errors/occ-base-sites, click "Load Base Sites" — OCC basesites response displayed via BFF proxynpm run build:ssr), manually substituteBFF_BASE_URL_VALUEindist/storefrontapp/browser/index.html, serve statically — meta tag read correctly at bootstrapBFF_BASE_URL=https://localhost:8482/bff/api— BFF calls succeed server-side/bff/— storefront reads meta tag and calls BFF correctly