Skip to content

Commit f178dec

Browse files
committed
implement route serialization/deserialization
1 parent 144f097 commit f178dec

File tree

4 files changed

+70
-22
lines changed

4 files changed

+70
-22
lines changed

packages/pwa-kit-react-sdk/src/ssr/browser/main.jsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,40 @@ export const start = async () => {
132132
locals
133133
})
134134

135+
// Await the async getRoutes function
136+
let routes = await getRoutes(locals)
137+
138+
// Deserialize routes
139+
let serializedRoutes = window.__CONFIG__.app.routes
140+
serializedRoutes = serializedRoutes.map(
141+
({path, componentName, componentProps}) => {
142+
let component = routes.find((route) =>
143+
route.component?.displayName?.includes(componentName)
144+
)?.component
145+
if (!component) {
146+
// TODO: Error handling if given component couldn't be found
147+
console.error('Component', componentName, 'could not be deserialized for path', path)
148+
return
149+
}
150+
151+
if (componentProps) {
152+
const Component = component
153+
component = () => <Component {...componentProps} />
154+
}
155+
return {
156+
path,
157+
exact: true,
158+
component
159+
}
160+
}
161+
)
162+
serializedRoutes = serializedRoutes.filter((route) => !!route)
163+
routes = serializedRoutes
164+
135165
const props = {
136166
error: window.__ERROR__,
137167
locals: locals,
138-
routes: getRoutes(locals),
168+
routes: routes,
139169
extensions: applicationExtensions,
140170
WrappedApp
141171
}

packages/pwa-kit-react-sdk/src/ssr/server/react-rendering.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ export const render = async (req, res, next) => {
139139
locals: res.locals
140140
})
141141

142-
let routes = getRoutes(res.locals)
142+
let routes = await getRoutes(res.locals, req)
143143

144144
const [pathname] = req.originalUrl.split('?')
145145

@@ -150,6 +150,14 @@ export const render = async (req, res, next) => {
150150
})
151151
}
152152

153+
// Serialize the routes and add them to the config. We'll use this on the client-side later.
154+
// TODO: Don't serialize all the routes (only the one route or only the non-localized routes before configurRoutes is run)
155+
config.app.routes = routes.map((route) => ({
156+
path: route.path,
157+
componentName: route.component.displayName.match(/\((\w+)\)/)[1],
158+
componentProps: route.props
159+
}))
160+
153161
// Step 1 - Find the match.
154162

155163
// Call `beforeRouteMatch` application extension hook.

packages/pwa-kit-react-sdk/src/ssr/universal/components/route-component/index.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -402,17 +402,17 @@ export const routeComponent = (Wrapped, isPage, locals) => {
402402
*
403403
* @private
404404
*/
405-
export const getRoutes = (locals = {}) => {
405+
export const getRoutes = async (locals = {}, req = {}) => {
406406
let _routes = routes
407407
const {applicationExtensions = []} = locals
408408
if (typeof routes === 'function') {
409-
_routes = routes()
409+
_routes = await routes(locals)
410410
}
411411

412412
// Call the `extendRoutes` function for all the Application Extensions.
413-
applicationExtensions.forEach((applicationExtension) => {
414-
_routes = applicationExtension.extendRoutes(_routes)
415-
})
413+
for (const applicationExtension of applicationExtensions) {
414+
_routes = await applicationExtension.extendRoutes(_routes, req)
415+
}
416416

417417
const allRoutes = [
418418
// NOTE: this route needs to be above _routes, in case _routes has a fallback route of `path: '*'`

packages/pwa-kit-react-sdk/src/ssr/universal/components/switch/index.jsx

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
* SPDX-License-Identifier: BSD-3-Clause
55
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
66
*/
7-
import React from 'react'
7+
import React, {useContext, useState} from 'react'
88
import PropTypes from 'prop-types'
99
import {Switch as RouterSwitch, Route} from 'react-router-dom'
1010
import AppErrorBoundary from '../app-error-boundary'
1111
import {UIDReset, UIDFork} from 'react-uid'
1212

13+
// TODO: can the context be moved to a HOC so routes don't always have to be serialized
14+
const RoutesContext = React.createContext({})
15+
export const useRoutesContext = () => useContext(RoutesContext)
16+
1317
/**
1418
* The Switch component packages up the bits of rendering that are shared between
1519
* server and client-side. It's *mostly* a react-router Switch component, hence the
@@ -21,24 +25,30 @@ import {UIDReset, UIDFork} from 'react-uid'
2125
*/
2226
const Switch = (props) => {
2327
const {error, appState, routes, App} = props
28+
const [_routes, setRoutes] = useState(routes)
2429
return (
2530
<UIDReset>
2631
<AppErrorBoundary error={error}>
2732
{!error && (
28-
<App preloadedProps={appState.appProps}>
29-
<RouterSwitch>
30-
{routes.map((route, i) => {
31-
const {component: Component, ...routeProps} = route
32-
return (
33-
<Route key={i} {...routeProps}>
34-
<UIDFork>
35-
<Component preloadedProps={appState.pageProps} />
36-
</UIDFork>
37-
</Route>
38-
)
39-
})}
40-
</RouterSwitch>
41-
</App>
33+
<RoutesContext.Provider value={{
34+
routes: _routes,
35+
setRoutes
36+
}}>
37+
<App preloadedProps={appState.appProps}>
38+
<RouterSwitch>
39+
{_routes.map((route, i) => {
40+
const {component: Component, ...routeProps} = route
41+
return (
42+
<Route key={i} {...routeProps}>
43+
<UIDFork>
44+
<Component preloadedProps={appState.pageProps} />
45+
</UIDFork>
46+
</Route>
47+
)
48+
})}
49+
</RouterSwitch>
50+
</App>
51+
</RoutesContext.Provider>
4252
)}
4353
</AppErrorBoundary>
4454
</UIDReset>

0 commit comments

Comments
 (0)