Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@W-16442332@ Add support for environment level base path (the base path for /mobify routes) #1970

Merged
merged 42 commits into from
Aug 29, 2024

Conversation

vcua-mobify
Copy link
Contributor

@vcua-mobify vcua-mobify commented Aug 9, 2024

In #1824, we started to lay the groundwork for adding a namespace to our /mobify routes (which will be called the environment base path, or envBasePath from here on out).

This PR follows up that work by allowing projects to define this envBasePath via the environment specific configuration files. A separate PR will be created following this PR to set the base path of app pages such as our PLP or PDP.

Configuring the envBasePath
For example, suppose I have the an MRT environment named amer

In the config file named amer.js, I can set the envBasePath like so:

const defaultConfig = require('./default.js')

module.exports = {
    ...defaultConfig,
    envBasePath: '/amer'

Change summary:

  • pwa-kit-runtime updates to read an envBasePath from config file and append this envBasePath to /mobify routes
  • pwa-kit-runtime exposes functions for getting /mobify routes
  • pwa-kit-dev update to set a webpack public path for HMR to work with envBasePath
  • updates to _app-config for consuming runtime changes and setting envBasePath to proxies

Testing these changes:

Locally:
Create a local.js config file and set envBasePath: '/local' (see above)
Start the app
See that all /mobify requests now have the /local basePath
Navigate between different pages and make changes. See that HMR is working

Remote:
Create a ca.js and us.js config file and set envBasePath to /ca and /us respectively
Deploy the changes to our ca and us environments on MRT
See that all /mobify requests on ca now have the /ca basePath
See that all /mobify requests on us now have the /us basePath

TODO
Apply PR feedback

@vcua-mobify vcua-mobify requested review from bendvc and kevinxh August 9, 2024 21:11
}

export const ssrNamespace = _getNamespace()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we intend to also keep ssrNamespace as part of the deprecated variables?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Urk, good catch. It was exported so we should keep it as a deprecated variable like the others

// TODO - Allow projects to define this function?
export const getEnvBasePath = () => {
const config = getConfig()
return config?.envBasePath ? config.envBasePath : ''
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we expect to find a default fallback envBasePath in the config?
If we do, shouldn't we print an error in console so users know that the expected configuration was not found?

Something like:

export const getEnvBasePath = () => {
    const config = getConfig()
    if (!config || typeof config.envBasePath !== 'string') {
        log.error('Invalid environment base path configuration')
        return ''
    }
    return config.envBasePath || ''
}

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 tried adding a logger.error but then the client side attempt to invoke logger as well and the logger does not exist client side.

For now, I have set a console.log to print an error of envBasePath isn't a string.

Copy link
Collaborator

Choose a reason for hiding this comment

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

The logger does exist on the client-side as well. It's just a wrapper around Node's console object.

Comment on lines 33 to 36
export const getBundlePath = () => `${getEnvBasePath()}${BUNDLE_PATH_BASE}`
export const getCachingPath = () => `${getEnvBasePath()}${CACHING_PATH_BASE}`
export const getHealthCheckPath = () => `${getEnvBasePath()}${HEALTHCHECK_PATH}`
export const getSlasPrivateProxyPath = () => `${getEnvBasePath()}${SLAS_PRIVATE_CLIENT_PROXY_PATH}`
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we add this work to a feature branch until all the parts are feature complete and tested, to avoid introducing new breaking changes?

*/
return ''
// TODO - Allow projects to define this function?
export const getEnvBasePath = () => {
Copy link
Collaborator

@adamraya adamraya Aug 12, 2024

Choose a reason for hiding this comment

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

The function getEnvBasePath() is called multiple times in different files. This could potentially create a performance bottleneck if loops or complex logic is implemented.
Keeping a simple logic and cache the result of getEnvBasePath could help to reduce the performance impact.

Note that if we give customers access, it might lead to more complex implementations and thus performance issues.

We can also introduce an ssr metric to monitor the execution time of this function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

getConfig is memoized on the server side so there should not be much of a performance impact there.
I think we are also ok client side since there we are just reading from window.__config__ once it's hydrated.

I removed the note about allowing projects to define this. I think for now we will keep this function definition internal.

@@ -11,7 +11,7 @@ module.exports = {
...base,
coverageThreshold: {
global: {
branches: 67,
branches: 65,
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 had to lower this threshold since the new conditional in build-dev-server.js for setting the HMR publicPath dropped coverage below 67%. There is no easy way to test the new conditional since the changes are inside _addSDKInternalHandlers and our tests override _addSDKInternalHandlers with a no-op.

Copy link
Collaborator

Choose a reason for hiding this comment

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

fixed, bumped up to 68

@vcua-mobify vcua-mobify requested a review from adamraya August 13, 2024 17:09
@vcua-mobify vcua-mobify marked this pull request as ready for review August 13, 2024 17:09
@vcua-mobify vcua-mobify requested a review from a team as a code owner August 13, 2024 17:09
@@ -46,6 +46,9 @@ const AppConfig = ({children, locals = {}}) => {

const appOrigin = getAppOrigin()

const redirectURI = `${appOrigin}/callback`
const proxy = `${appOrigin}${getEnvBasePath()}${commerceApiConfig.proxyPath}`
Copy link
Collaborator

Choose a reason for hiding this comment

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

If I was a partner dev and I saw this line of code I would probably be quite confused. Since we are giving people this file, this code is theirs and they should probably be able to understand it.

Have you thought about either creating a new util called getAppOriginWithBasePatth or maybe modifying so we can optionally include the base path? like getAppOrigin({includeBasePath: true})

Just a thought.

Copy link
Collaborator

Choose a reason for hiding this comment

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

It's a good thought, but I think we may need to put more effort into this. I'd really love to get this merged soon and move on to the second part of this work...

Comment on lines 19 to 31
if (!window.__CONFIG__ && typeof document !== 'undefined') {
try {
const data = JSON.parse(document.getElementById('mobify-data').innerHTML)

// Set all globals sent from the server on the window object.
Object.entries(data).forEach(([key, value]) => {
window[key] = value
})
} catch (error) {
console.error('Unable to parse server-side rendered config.')
console.error(error)
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

As you mentioned this is leaking internal details into the runtime specifically those from the react-sdk. This isn't ideal, but not horrible. But if, like you said, it might not be required in this implementation, then I would take it out.

Copy link
Collaborator

Choose a reason for hiding this comment

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

reverted

Comment on lines -72 to +77
OCAPISessionsURL={`${appOrigin}${proxyBasePath}/ocapi/s/${locals.site?.id}/dw/shop/v22_8/sessions`}
OCAPISessionsURL={`${appOrigin}${getProxyPath()}/ocapi/s/${
locals.site?.id
}/dw/shop/v22_8/sessions`}
Copy link
Collaborator

@adamraya adamraya Aug 28, 2024

Choose a reason for hiding this comment

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

nit: I'm curious, why we are not following the same pattern of creating a const OCAPISessionsURL like we do for redirectURI and proxy?

@kevinxh kevinxh merged commit d7a412a into develop Aug 29, 2024
29 checks passed
@kevinxh kevinxh deleted the basePaths-impl branch August 29, 2024 00:49
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.

4 participants