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

[Spike] getComponentMap takes allRoutes #2337

Draft
wants to merge 2 commits into
base: implement-dynamic-update-routes
Choose a base branch
from

Conversation

hajinsuha1
Copy link
Collaborator

Description

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

  • (change1)

How to Test-Drive This PR

  • (step1)

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)

@hajinsuha1 hajinsuha1 changed the base branch from develop to implement-dynamic-update-routes March 26, 2025 20:06
Comment on lines +127 to +135
getComponentMap(allRoutes: RouteProps[]): ComponentMap {
const {resourceTypeToComponentMap} = this.getConfig()
return Object.values(resourceTypeToComponentMap).reduce((map: ComponentMap, componentName) => {
const component = allRoutes.find(route => route.component?.displayName.includes(componentName))?.component
if (component) {
map[componentName] = component
}
return map
}, {})
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the getComponentMap implementation searches the routes list for the component with a displayName that matches the component name in the resourceTypeToComponentMap

Comment on lines +160 to +167
public getComponentMap(allRoutes: RouteProps[]): ComponentMap | undefined {
if (typeof this.getRoutesAsync !== 'undefined') {
throw new Error(
`${this.getComponentMap.name} must be defined when getRoutesAsync() is defined in the ${this.getName()} extension`
)
}
return
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

default impl throws an error if getRoutesAsync() is implemented

Comment on lines 183 to 188
if (!isServerSide()) {
console.log('JINSUUUU !isServerSide')
serializedRoutes = window.__EXTENSIONS__[this.getName()].routes
} else {
serializedRoutes = this._cachedRoutes
}
Copy link
Collaborator Author

@hajinsuha1 hajinsuha1 Mar 26, 2025

Choose a reason for hiding this comment

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

one finding is that on the server side we actually do have to deserialize the routes or at least the route we are currently on.

See here.

Comment on lines 135 to 143
const _routes = await getAllRoutes(locals)

applicationExtensions.forEach((extension) => {
const componentMap = extension.getComponentMap(_routes)
console.log('JINSU componentMap', componentMap)
extension.deserialize(componentMap)
})

const routes = await getAllRoutes(locals)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

we need to call getAllRoutes twice. First time is to get the routes from the other extensions so we can pass it to getComponentMap and deserialize. The 2nd time is to reload the routes that have been deserialized from cache.

I also thought of loading only the synchrounous routes before deserializing and then loading the async routes after deserializing but i don't think that is viable since it will mess up the order of the routes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

prioritization and put it the routes at the end
for now we can hard code it to put SEO at the end
or assume it ats the end

getComponentMap only get routes from extension before it
manually process seo one last

deserialize first

routes = [] => deserialize empty ext and add routes into it

Comment on lines 163 to 169
applicationExtensions.forEach((extension) => {
const componentMap = extension.getComponentMap(_routes)
console.log('JINSU componentMap', componentMap)
extension.deserialize(componentMap)
})

let routes = await getAllRoutes(res.locals)
Copy link
Collaborator Author

@hajinsuha1 hajinsuha1 Mar 26, 2025

Choose a reason for hiding this comment

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

we need to deserialize also on the server because after we route match the component of the current route is passed to the initial App state on line 225

@@ -174,28 +172,20 @@ export class ApplicationExtension<
* @throws Error if getComponentMap() is not defined.
* @throws Error if the deserialized component cannot be found in the component map.
*/
private deserialize(): DeserializedExtension | null {
if (isServerSide() || typeof this.getRoutesAsync === 'undefined') {
public deserialize(componentMap: ComponentMap) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

we now pass componentMap to deserialize

Comment on lines +181 to 185
if (!isServerSide()) {
serializedRoutes = window.__EXTENSIONS__[this.getName()].routes
} else {
serializedRoutes = this._cachedRoutes
}
Copy link
Collaborator Author

@hajinsuha1 hajinsuha1 Mar 28, 2025

Choose a reason for hiding this comment

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

We also need to deserialize on the server side because we pass the component of the matched route to the initial app state in react-rendering.js.

const ret = await AppConfig.initAppState({
App: WrappedApp,
component,
match,
route,
req,
res,
location,
appJSX
})

Comment on lines +217 to 218
this._cachedRoutes = routes || null
return {routes}
Copy link
Collaborator Author

@hajinsuha1 hajinsuha1 Mar 28, 2025

Choose a reason for hiding this comment

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

we now return the routes after deserializing

if (extension.getRoutesAsync){
// Need to call getRoutesAsync so the routes can be cached before deserialize
await extension.getRoutesAsync({locals})
const componentMap = extension.getComponentMap(routes)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

we pass the accumulated routes from prev extension to getComponentMap

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.

1 participant