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

Optimize Server-side performance #667

Merged
merged 53 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
1f9e61b
Use LocaleContext and SiteContext
adamraya Jul 5, 2022
7876f06
Merge branch 'develop' into server-side-performance
adamraya Jul 5, 2022
9c613c7
Merge branch 'develop' into server-side-performance
adamraya Jul 11, 2022
8be5553
Declare AppConfigProvider
adamraya Jul 11, 2022
3eeb5f6
Optimization use `AppConfig` context & `urlTemplateLiteral` without l…
adamraya Jul 14, 2022
b1e5863
Merge branch 'develop' into server-side-performance
adamraya Jul 14, 2022
588951d
Fix missing forward slash on `urlTemplateLiteral`
adamraya Jul 14, 2022
d1a3318
Clean up
adamraya Jul 14, 2022
0671b24
Remove `buildPathWithUrlConfig()` & Start fixing test
adamraya Jul 19, 2022
9309849
Merge branch 'develop' into server-side-performance
adamraya Jul 19, 2022
66af383
Fix some tests
adamraya Jul 20, 2022
89ca772
Merge branch 'develop' into server-side-performance
adamraya Jul 20, 2022
2cf132f
Clean up
adamraya Jul 20, 2022
39b3be0
Combine default cases
adamraya Jul 20, 2022
4d9d18e
Update url.js
adamraya Jul 21, 2022
176fe1a
Refactor switch
adamraya Jul 21, 2022
f86c753
Add docs
adamraya Jul 21, 2022
7d84e72
Merge branch 'develop' into server-side-performance
adamraya Jul 21, 2022
d938250
Merge branch 'server-side-performance' of https://github.com/Salesfor…
adamraya Jul 21, 2022
de76fff
Minor naming
adamraya Jul 21, 2022
6f2221f
Update packages/template-retail-react-app/app/utils/url.js
adamraya Jul 25, 2022
31561c5
PR Feedback rename c to config
adamraya Jul 25, 2022
273434b
Update packages/template-retail-react-app/app/components/link/index.jsx
adamraya Jul 25, 2022
be53a8f
PR Feedback naming
adamraya Jul 25, 2022
13f6523
Update `getPathWithLocale` signature & Clean up
adamraya Jul 25, 2022
db0379d
Fix tests
adamraya Jul 27, 2022
85142c7
Fix more tests
adamraya Jul 27, 2022
3d2e283
Merge branch 'develop' into server-side-performance
adamraya Jul 27, 2022
92c2026
Small refactor using site and locale references in `createUrlTemplate`
adamraya Jul 27, 2022
b756dab
LocaleProvider use locale id
adamraya Jul 27, 2022
5e4f418
Fix disallowParams test
adamraya Jul 28, 2022
8f4fa40
Footer Locale Select using the right params
adamraya Jul 28, 2022
3e32d62
Add `createUrlTemplate` tests
adamraya Jul 28, 2022
25d1de0
Small tweaks to `createUrlTemplate` tests
adamraya Jul 28, 2022
3868da7
Merge branch 'develop' into server-side-performance
adamraya Jul 28, 2022
7b3b2a4
Run all tests on link component
adamraya Jul 28, 2022
f6070c2
Fix link tests
adamraya Jul 29, 2022
356d0c6
Small naming
adamraya Jul 29, 2022
a14d2a4
Remove `homeUrlBuilder`
adamraya Jul 30, 2022
176a495
Run all url tests
adamraya Jul 30, 2022
5874be8
Extend `createUrlTemplate` to replace `homeUrlBuilder`
adamraya Aug 2, 2022
580eaec
Merge branch 'develop' into server-side-performance
adamraya Aug 2, 2022
f08bc68
URL templateConfig not needed
adamraya Aug 2, 2022
93e2ee4
Adjust `createUrlTemplate` home extension
adamraya Aug 2, 2022
1c12a18
PR Feedback
adamraya Aug 2, 2022
5405621
Merge branch 'develop' into server-side-performance
adamraya Aug 2, 2022
5644eea
Test `useUrlTemplate` Vincent M idea
adamraya Aug 2, 2022
958ef36
lint
adamraya Aug 2, 2022
bcc43f8
Move SiteProvider and LocaleProvider to AppConfig
adamraya Aug 3, 2022
ad0e289
Refactor Site, Locale and UrlTemplate Providers into `MultiSiteProvider`
adamraya Aug 3, 2022
6b00a3e
Rename `useUrlTemplate` hook to `useMultiSite` hook
adamraya Aug 3, 2022
788a69f
PR Feedback use `useCallback` in `useMultiSite` hook
adamraya Aug 3, 2022
56088a8
Rename `fillUrlTemplate` to `buildUrl`
adamraya Aug 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ import {
CustomerProductListsProvider,
CustomerProvider
} from '../../commerce-api/contexts'
import {AppConfigProvider} from '../../contexts'
import {resolveSiteFromUrl} from '../../utils/site-utils'
import {resolveLocaleFromUrl} from '../../utils/utils'
import {getConfig} from 'pwa-kit-runtime/utils/ssr-config'
import {getUrlTemplateLiteral} from '../../utils/url'

/**
* Use the AppConfig component to inject extra arguments into the getProps
Expand All @@ -36,15 +38,17 @@ const AppConfig = ({children, locals = {}}) => {
const [customer, setCustomer] = useState(null)

return (
<CommerceAPIProvider value={locals.api}>
<CustomerProvider value={{customer, setCustomer}}>
<BasketProvider value={{basket, setBasket}}>
<CustomerProductListsProvider>
<ChakraProvider theme={theme}>{children}</ChakraProvider>
</CustomerProductListsProvider>
</BasketProvider>
</CustomerProvider>
</CommerceAPIProvider>
<AppConfigProvider urlTemplateLiteral={locals.urlTemplateLiteral}>
<CommerceAPIProvider value={locals.api}>
<CustomerProvider value={{customer, setCustomer}}>
<BasketProvider value={{basket, setBasket}}>
<CustomerProductListsProvider>
<ChakraProvider theme={theme}>{children}</ChakraProvider>
</CustomerProductListsProvider>
</BasketProvider>
</CustomerProvider>
</CommerceAPIProvider>
</AppConfigProvider>
)
}

Expand All @@ -66,13 +70,15 @@ AppConfig.restore = (locals = {}) => {
apiConfig.parameters.siteId = site.id

locals.api = new CommerceAPI({...apiConfig, locale: locale.id, currency})
locals.urlTemplateLiteral = getUrlTemplateLiteral(appConfig, site, locale)
}

AppConfig.freeze = () => undefined

AppConfig.extraGetPropsArgs = (locals = {}) => {
return {
api: locals.api
api: locals.api,
urlTemplateLiteral: locals.urlTemplateLiteral
}
}

Expand Down
245 changes: 140 additions & 105 deletions packages/template-retail-react-app/app/components/_app/index.jsx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {Helmet} from 'react-helmet'
import App from './index.jsx'
import {renderWithProviders} from '../../utils/test-utils'
import {DEFAULT_LOCALE} from '../../utils/test-utils'
import useSite from '../../hooks/use-site'
import {useSite} from '../../hooks/use-site'
import messages from '../../translations/compiled/en-GB.json'
import mockConfig from '../../../config/mocks/default'
jest.mock('../../hooks/use-site', () => jest.fn())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import useCustomer from '../../commerce-api/hooks/useCustomer'
import LoadingSpinner from '../loading-spinner'

import useNavigation from '../../hooks/use-navigation'
import useSite from '../../hooks/use-site'
import {useSite} from '../../hooks/use-site'

// The FONT_SIZES and FONT_WEIGHTS constants are used to control the styling for
// the accordion buttons as their current depth. In the below definition we assign
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ import SocialIcons from '../social-icons'
import {HideOnDesktop, HideOnMobile} from '../responsive'
import {getPathWithLocale} from '../../utils/url'
import LocaleText from '../locale-text'
import useSite from '../../hooks/use-site'
import {useSite} from '../../hooks/use-site'

const Footer = ({...otherProps}) => {
const styles = useMultiStyleConfig('Footer')
const intl = useIntl()
const [locale, setLocale] = useState(intl.locale)
const site = useSite()
const {l10n} = site
const {l10n} = site?.site
const supportedLocaleIds = l10n?.supportedLocales.map((locale) => locale.id)
const showLocaleSelector = supportedLocaleIds?.length > 1

Expand Down
20 changes: 10 additions & 10 deletions packages/template-retail-react-app/app/components/link/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,26 @@ import React from 'react'
import PropTypes from 'prop-types'
import {Link as ChakraLink} from '@chakra-ui/react'
import {Link as SPALink, NavLink as NavSPALink} from 'react-router-dom'
import {buildPathWithUrlConfig} from '../../utils/url'
import useSite from '../../hooks/use-site'
import useLocale from '../../hooks/use-locale'
import {useSite} from '../../hooks/use-site'
import {useLocale} from '../../hooks/use-locale'
import {useAppConfig} from '../../hooks/use-app-config'

const Link = React.forwardRef(({href, to, useNavLink = false, ...props}, ref) => {
const _href = to || href
const site = useSite()
adamraya marked this conversation as resolved.
Show resolved Hide resolved
const locale = useLocale()

// if alias is not defined, use site id
const updatedHref = buildPathWithUrlConfig(_href, {
locale: locale.alias || locale.id,
site: site.alias || site.id
})
const appConfig = useAppConfig()
const pathWithUrlConfig = appConfig.urlTemplateLiteral(
_href,
site.site.alias || site.site.id,
locale.locale.id
)
return (
<ChakraLink
as={useNavLink ? NavSPALink : SPALink}
{...(useNavLink && {exact: true})}
{...props}
to={_href === '/' ? '/' : updatedHref}
to={_href === '/' ? '/' : pathWithUrlConfig}
ref={ref}
/>
)
Expand Down
45 changes: 45 additions & 0 deletions packages/template-retail-react-app/app/contexts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,51 @@ CategoriesProvider.propTypes = {
categories: PropTypes.object
}

export const LocaleContext = React.createContext()
export const LocaleProvider = ({locale: initialLocale = {}, children}) => {
const [locale, setLocale] = useState(initialLocale)

return <LocaleContext.Provider value={{locale, setLocale}}>{children}</LocaleContext.Provider>
}

LocaleProvider.propTypes = {
children: PropTypes.node.isRequired,
locale: PropTypes.object
}

export const SiteContext = React.createContext()
export const SiteProvider = ({site: initialSite = {}, children}) => {
const [site, setSite] = useState(initialSite)

return <SiteContext.Provider value={{site, setSite}}>{children}</SiteContext.Provider>
}

SiteProvider.propTypes = {
children: PropTypes.node.isRequired,
site: PropTypes.object
}

export const AppConfigContext = React.createContext()
export const AppConfigProvider = ({
appConfig: initialAppConfig = {},
urlTemplateLiteral,
children
}) => {
const [appConfig, setAppConfig] = useState(initialAppConfig)

return (
<AppConfigContext.Provider value={{appConfig, setAppConfig, urlTemplateLiteral}}>
{children}
</AppConfigContext.Provider>
)
}

AppConfigProvider.propTypes = {
children: PropTypes.node.isRequired,
appConfig: PropTypes.object,
urlTemplateLiteral: PropTypes.func
}

/**
* This is the global state for currency, we use this throughout the site. For example, on
* the product-list, product-detail and cart and basket pages..
Expand Down
15 changes: 15 additions & 0 deletions packages/template-retail-react-app/app/hooks/use-app-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright (c) 2021, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import {useContext} from 'react'
import {AppConfigContext} from '../contexts'

/**
* Custom React hook to get the current site
* @returns {site: Object, setSite: function}
*/
export const useAppConfig = () => useContext(AppConfigContext)
22 changes: 5 additions & 17 deletions packages/template-retail-react-app/app/hooks/use-locale.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,11 @@
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import useSite from './use-site'
import {useMemo} from 'react'
import {resolveLocaleFromUrl} from '../utils/utils'
import {useLocation} from 'react-router-dom'
import {useContext} from 'react'
import {LocaleContext} from '../contexts'

/**
* This hook returns the locale object based on current location
* @return {object} locale
* Custom React hook to get the locale
* @returns {locale: Object, setLocale: function}
*/
const useLocale = () => {
const {pathname, search} = useLocation()
const site = useSite()
const locale = useMemo(() => {
return resolveLocaleFromUrl(`${pathname}${search}`)
}, [pathname, search, site])

return locale
}

export default useLocale
export const useLocale = () => useContext(LocaleContext)
15 changes: 8 additions & 7 deletions packages/template-retail-react-app/app/hooks/use-navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import {useCallback} from 'react'
import {useHistory} from 'react-router'
import {useIntl} from 'react-intl'
import {buildPathWithUrlConfig} from '../utils/url'
import useSite from './use-site'
import {useSite} from './use-site'
import {getLocaleByReference} from '../utils/utils'
import {useAppConfig} from './use-app-config'

/**
* A convenience hook for programmatic navigation uses history's `push` or `replace`. The proper locale
Expand All @@ -21,6 +21,7 @@ const useNavigation = () => {

const {locale: localeShortCode} = useIntl()
const site = useSite()
const appConfig = useAppConfig()
return useCallback(
/**
*
Expand All @@ -30,11 +31,11 @@ const useNavigation = () => {
*/
(path, action = 'push', ...args) => {
const locale = getLocaleByReference(site, localeShortCode)

const updatedHref = buildPathWithUrlConfig(path, {
locale: locale.alias || locale.id,
site: site.alias || site.id
})
const updatedHref = appConfig.urlTemplateLiteral(
path,
site.site.alias || site.site.id,
locale
)
history[action](path === '/' ? '/' : updatedHref, ...args)
},
[localeShortCode, site]
Expand Down
20 changes: 5 additions & 15 deletions packages/template-retail-react-app/app/hooks/use-site.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,11 @@
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import {useLocation} from 'react-router-dom'
import {resolveSiteFromUrl} from '../utils/site-utils'
import {useMemo} from 'react'
import {useContext} from 'react'
import {SiteContext} from '../contexts'

/**
* This hook returns the current site based on current location
*
* @returns {Object} - current site
* Custom React hook to get the current site
* @returns {site: Object, setSite: function}
*/
const useSite = () => {
const {pathname, search} = useLocation()
const site = useMemo(() => {
return resolveSiteFromUrl(`${pathname}${search}`)
}, [pathname, search])
return site
}

export default useSite
export const useSite = () => useContext(SiteContext)
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {createMemoryHistory} from 'history'
import {render, screen} from '@testing-library/react'
import {Router} from 'react-router'
import React from 'react'
import useSite from './use-site'
import {useSite} from './use-site'

afterEach(() => {
jest.clearAllMocks()
Expand Down
17 changes: 10 additions & 7 deletions packages/template-retail-react-app/app/pages/account/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ import {useLocation} from 'react-router-dom'
import {messages, navLinks} from './constant'
import useNavigation from '../../hooks/use-navigation'
import LoadingSpinner from '../../components/loading-spinner'
import {buildPathWithUrlConfig} from '../../utils/url'
import useLocale from '../../hooks/use-locale'
import useSite from '../../hooks/use-site'
import {useLocale} from '../../hooks/use-locale'
import {useSite} from '../../hooks/use-site'
import {useAppConfig} from '../../hooks/use-app-config'

const Account = () => {
const {path} = useRouteMatch()
Expand All @@ -53,6 +53,8 @@ const Account = () => {
const [mobileNavIndex, setMobileNavIndex] = useState(-1)
const [showLoading, setShowLoading] = useState(false)

const appConfig = useAppConfig()

const onSignoutClick = async () => {
setShowLoading(true)
await customer.logout()
Expand Down Expand Up @@ -91,10 +93,11 @@ const Account = () => {
// Using Redirect allows us to store the directed page to location
// so we can direct users back after they are successfully log in
if (customer.authType != null && !customer.isRegistered) {
const path = buildPathWithUrlConfig('/login', {
locale: locale.alias || locale.id,
site: site.alias || site.id
})
const path = appConfig.urlTemplateLiteral(
'/login',
site.site.alias || site.site.id,
locale.locale.id
)
return <Redirect to={{pathname: path, state: {directedFrom: location.pathname}}} />
}

Expand Down
Loading