Skip to content

@W-19869537 Added Hybrid Proxy support for local and ODS hybrid development when no eCDN available#3409

Merged
yhsieh1 merged 22 commits intodevelopfrom
feature/hybridcdn
Oct 23, 2025
Merged

@W-19869537 Added Hybrid Proxy support for local and ODS hybrid development when no eCDN available#3409
yhsieh1 merged 22 commits intodevelopfrom
feature/hybridcdn

Conversation

@yhsieh1
Copy link
Contributor

@yhsieh1 yhsieh1 commented Oct 20, 2025

Description

Overview
This PR introduces Hybrid Proxy support for PWA Kit, enabling seamless integration between PWA Kit applications and Salesforce Commerce Cloud (SFCC) instances during local development and ODS hybrid scenarios when no eCDN is available.

🎯 Key Changes

  1. Added Hybrid Proxy in pwa-kit-runtime
  2. Added Hybrid Proxy Configuration in template-retail-react-app app/ssr.js
  3. Extra unit test is added to improve and pass test coverage requirement

A pwa-kit storefront with hybrid proxy enabled is deployed on MRT and connected to ODS for testing.

Screenshot 2025-10-20 at 10 32 13 AM

Types of Changes

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Documentation update
  • Breaking change (could cause existing functionality to not work as expected)
  • Other changes (non-breaking changes that does not fit any of the above)

Breaking changes include:

  • Removing a public function or component or prop
  • Adding a required argument to a function
  • Changing the data type of a function parameter or return value
  • Adding a new peer dependency to package.json

Changes

  • Added Hybrid Proxy support for local and ODS hybrid development when no eCDN available

How to Test-Drive This PR

Steps to test:

  1. Update ssr.js to enable Hybrid Proxy
  • localAllowCookies: true
  • hybridProxy.enabled: true
  • hybridProxy.sfccOrigin: [your SFCC store]
  1. Uncomment hybridAuthEnabled in _app-config.js

  2. Update routes.jsx to exclude routes on the PWA-Kit. Reference this code

  3. Update default.js

  • app.commerceAPI.parameters
  • app.enableHybrid: true to toggle routes exclusion on routes.jsx
  • NOTE: We need to change this to app.enableHybridProxy in the sample code and public doc
  • ssrParameters.proxyConfigs: add
    {
    host: [your SFCC store],
    path: 'dwrestatic'
    }
  1. Start up app
  • Add item to cart
  • Go to cart
  • It should show SFCC store cart page

Checklists

General

  • Changes are covered by test cases
  • CHANGELOG.md updated with a short description of changes (not required for documentation updates)

Accessibility Compliance

You must check off all items in one of the follow two lists:

  • There are no changes to UI

or...

Localization

  • Changes include a UI text update in the Retail React App (which requires translation)

yhsieh1 and others added 6 commits October 8, 2025 12:08
- Resolved merge conflicts in pwa-kit-mcp package
- Added new tools: hooks-recommendation and explore-scapi-shop-api
- Updated CHANGELOG.md and README.md with new features
- Merged changes from develop branch including new MCP tools and utilities
* Hybrid CDN 1st pass

---------

Signed-off-by: Aditya Tekur <126732792+aditek-sf@users.noreply.github.com>
@yhsieh1 yhsieh1 requested a review from a team as a code owner October 20, 2025 14:11
@cc-prodsec
Copy link
Collaborator

cc-prodsec commented Oct 20, 2025

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Licenses 0 0 0 0 0 issues
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Comment on lines +131 to +140
const isString = (element) => typeof element === 'string'
const isArray = (element) => Array.isArray(element)
const isObject = (element) => element && typeof element === 'object'
const isIterable = (element) => isArray(element) || isObject(element)

const forEachIn = (iterable, functionRef) => {
Object.keys(iterable).forEach((key) => {
functionRef(key, iterable[key])
})
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These appear to be generic util functions. Do they need to be a part of hybridProxy.js ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will move them to utils.js. Thanks!

enabled: false,

// The origin of the SFCC instance (i.e. the instance that is being proxied to which hosts the storefront).
sfccOrigin: 'https://zzrf-001.dx.commercecloud.salesforce.com',
Copy link
Contributor

@shethj shethj Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we consider reading this from config/env instead of hard-coding the hostname ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be read from env var but the ask from one pager is to leave the decision to use env var to the customer that's why the string is used here.

// * https://developer.salesforce.com/docs/commerce/commerce-api/references/cdn-api-process-apis?meta=MrtRules
// * https://developer.salesforce.com/docs/commerce/commerce-api/guide/ecdn-rules-for-phased-headless-rollout.html
routingRules: [
'http.request.uri.path eq "/" or http.request.uri.path matches "^/callback" or http.request.uri.path matches "^/mobify" or http.request.uri.path matches "^/worker.js" or http.request.uri.path matches "^/(\\\\w+)/([-\\\\w]+)/$" or http.request.uri.path matches "^/(\\\\w+)/([-\\\\w]+)/login" or http.request.uri.path matches "^/(\\\\w+)/([-\\\\w]+)/reset-password" or http.request.uri.path matches "^/(\\\\w+)/([-\\\\w]+)/registration" or http.request.uri.path matches "^/(\\\\w+)/([-\\\\w]+)/account" or http.request.uri.path matches "^/(\\\\w+)/([-\\\\w]+)/account/orders" or http.request.uri.path matches "^/(\\\\w+)/([-\\\\w]+)/account/orders/(\\\\w+)" or http.request.uri.path matches "^/(\\\\w+)/([-\\\\w]+)/account/wishlist" or http.request.uri.path matches "^/(\\\\w+)/([-\\\\w]+)/product/(\\\\w+)" or http.request.uri.path matches "^/(\\\\w+)/([-\\\\w]+)/search" or http.request.uri.path matches "^/(\\\\w+)/([-\\\\w]+)/category/(\\\\w+)" or http.request.uri.path matches "^/(\\\\w+)/([-\\\\w]+)/order-status" or http.request.uri.path matches "^/(\\\\w+)/([-\\\\w]+)/page/(\\\\w+)" or http.request.uri.path matches "^/(\\\\w+)/([-\\\\w]+)/page-viewer/(\\\\w+)"'
Copy link
Contributor

@shethj shethj Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. Can we avoid hard-coding the routing rules and make them configurable via env var ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be read from env var but according to one pager we would like to leave the decision to customer and not introduce dotenv dependency in the project.

Customers can always implement using in env-vars on their own; our documenting using plain config will be simpler without introducing that extra dependency (and no need for the 3PP). Furthermore the rule set is unlikely to change within a customers implementation and they will likely only use env-vars for the ECOM upstream. We will leave this up to them.

// HYBRID PROXY REQUIREMENT:
// - Hybrid Proxy requires this to be 'true' for SFCC session management to work properly
// - Only enable Hybrid Proxy in development environments, never in production
localAllowCookies: false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see these options in the generated app. You might need to update the handlebar files. Please make sure you test the code with generated apps as well (with and without extensibility.)

Image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for catching this. I will update it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ssr.js.hbs is updated for both extensible and non-extensible and tested in generated project for:

  • my own instance
    -- non extensible
    -- extensible
  • demo instance

@shethj
Copy link
Contributor

shethj commented Oct 21, 2025

I see the steps to test require updates to config/default.js:

app.commerceAPI.parameters
app.enableHybrid: true to toggle routes exclusion on routes.jsx
ssrParameters.proxyConfigs: add
{
host: [your SFCC store],
path: 'dwrestatic'
}

I don't see corresponding code changes to config/default.js in the PR.
Is this expected ?

Also for the config consider naming: app.enableHybridProxy: true because app.enableHybrid: true comes across as something I should enable for hybrid in general.

@yhsieh1
Copy link
Contributor Author

yhsieh1 commented Oct 21, 2025

enableHybrid
@shethj the default.js changes is required for customer to config proxy of dwrestatic and exclude the route from PWA storefront client side navigation(step 3 code) so that the request will be proxied from the server side.

@shethj
Copy link
Contributor

shethj commented Oct 21, 2025

enableHybrid
@shethj the default.js changes is required for customer to config proxy of dwrestatic and exclude the route from PWA storefront client side navigation(step 3 code) so that the request will be proxied from the server side.

Yeah I understood the changes. I was wondering if the config.js changes should be shipped with defaults OOTB.

@yhsieh1
Copy link
Contributor Author

yhsieh1 commented Oct 21, 2025

enableHybrid
@shethj the default.js changes is required for customer to config proxy of dwrestatic and exclude the route from PWA storefront client side navigation(step 3 code) so that the request will be proxied from the server side.

Yeah I understood the changes. I was wondering if the config.js changes should be shipped with defaults OOTB.

@shethj You are right but the main problem is client might configure app.url site, locale, showDefaults differently and this will affect the routes.jsx changes needed accordingly to construct the newURL.pathname. We might need to provide routes.jsx examples to cover some use cases including default generated app in the doc. cc. @aditek-sf

enabled: false,

// The origin of the SFCC instance (i.e. the instance that is being proxied to which hosts the storefront).
sfccOrigin: 'https://{{answers.project.commerce.instanceUrl}}',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use {{answers.project.commerce.instanceUrl}} so that user does not need to update this manually in ssr.js

enabled: false,

// The origin of the SFCC instance (i.e. the instance that is being proxied to which hosts the storefront).
sfccOrigin: 'https://{{answers.project.commerce.instanceUrl}}',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use {{answers.project.commerce.instanceUrl}} so that user does not need to update this manually in ssr.js

@yhsieh1 yhsieh1 requested a review from shethj October 21, 2025 19:50
@@ -0,0 +1,150 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yhsieh1 Can we please rename this file to hybrid-proxy.js to make sure we follow the naming convention to match other files in the package. Also for the test file.
Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for catching this. I did not notice the file name is not right.

@yhsieh1 yhsieh1 requested a review from shethj October 21, 2025 20:59
@shethj
Copy link
Contributor

shethj commented Oct 22, 2025

LGTM 👍

shethj
shethj previously approved these changes Oct 22, 2025
@@ -3,6 +3,7 @@
- Prompt text for Site ID should match actual validation: Site ID may contain uppercase or lowercase letters, numbers, hyphens, or underscores. - Updated Site ID validator regex to allow both uppercase and lowercase letters for improved compatibility, clarity. [#3410] (https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3410)

## v3.14.0-dev (Sep 26, 2025)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe not this PR directly, but why are there two v3.14.0-dev sections?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @patricksullivansf. It must be the auto merge. I fixed it.

@yhsieh1 yhsieh1 dismissed stale reviews from shethj and patricksullivansf via c0e0e18 October 23, 2025 02:21
@yhsieh1 yhsieh1 requested a review from shethj October 23, 2025 14:48
Signed-off-by: yhsieh1 <yhsieh@salesforce.com>
@yhsieh1 yhsieh1 merged commit 9765651 into develop Oct 23, 2025
42 checks passed
@yhsieh1 yhsieh1 deleted the feature/hybridcdn branch October 23, 2025 16:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants