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 49 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 {LocaleProvider, SiteProvider, UrlTemplateProvider} from '../../contexts'
import {resolveSiteFromUrl} from '../../utils/site-utils'
import {resolveLocaleFromUrl} from '../../utils/utils'
import {getConfig} from 'pwa-kit-runtime/utils/ssr-config'
import {createUrlTemplate} from '../../utils/url'

/**
* Use the AppConfig component to inject extra arguments into the getProps
Expand All @@ -36,15 +38,21 @@ 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>
<SiteProvider site={locals.site}>
<LocaleProvider locale={locals.locale}>
<UrlTemplateProvider fillUrlTemplate={locals.fillUrlTemplate}>
<CommerceAPIProvider value={locals.api}>
<CustomerProvider value={{customer, setCustomer}}>
<BasketProvider value={{basket, setBasket}}>
<CustomerProductListsProvider>
<ChakraProvider theme={theme}>{children}</ChakraProvider>
</CustomerProductListsProvider>
</BasketProvider>
</CustomerProvider>
</CommerceAPIProvider>
</UrlTemplateProvider>
</LocaleProvider>
</SiteProvider>
)
}

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

locals.api = new CommerceAPI({...apiConfig, locale: locale.id, currency})
locals.fillUrlTemplate = createUrlTemplate(
appConfig,
site.alias || site.id,
locale.id || locale
)
locals.site = site
locals.locale = locale.id
adamraya marked this conversation as resolved.
Show resolved Hide resolved
}

AppConfig.freeze = () => undefined

AppConfig.extraGetPropsArgs = (locals = {}) => {
return {
api: locals.api
api: locals.api,
fillUrlTemplate: locals.fillUrlTemplate,
site: locals.site,
locale: locals.locale
}
}

Expand Down
45 changes: 23 additions & 22 deletions packages/template-retail-react-app/app/components/_app/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import React, {useState, useEffect} from 'react'
import React, {useState, useEffect, useMemo} from 'react'
import PropTypes from 'prop-types'
import {useHistory, useLocation} from 'react-router-dom'
import {getAssetUrl} from 'pwa-kit-react-sdk/ssr/universal/utils'
Expand Down Expand Up @@ -35,21 +35,20 @@ import useShopper from '../../commerce-api/hooks/useShopper'
import useCustomer from '../../commerce-api/hooks/useCustomer'
import {AuthModal, useAuthModal} from '../../hooks/use-auth-modal'
import {AddToCartModalProvider} from '../../hooks/use-add-to-cart-modal'
import useSite from '../../hooks/use-site'
import useLocale from '../../hooks/use-locale'
import useWishlist from '../../hooks/use-wishlist'

// Localization
import {IntlProvider} from 'react-intl'

// Others
import {watchOnlineStatus, flatten} from '../../utils/utils'
import {homeUrlBuilder, getPathWithLocale, buildPathWithUrlConfig} from '../../utils/url'
import {getTargetLocale, fetchTranslations} from '../../utils/locale'
import {DEFAULT_SITE_TITLE, HOME_HREF, THEME_COLOR} from '../../constants'
import {resolveLocaleFromUrl} from '../../utils/utils'

import Seo from '../seo'
import {resolveSiteFromUrl} from '../../utils/site-utils'
import useUrlTemplate from '../../hooks/use-url-template'

const DEFAULT_NAV_DEPTH = 3
const DEFAULT_ROOT_CATEGORY = 'root'
Expand All @@ -63,18 +62,19 @@ const App = (props) => {
const location = useLocation()
const authModal = useAuthModal()
const customer = useCustomer()
const {fillUrlTemplate} = useUrlTemplate()

const site = useSite()
const locale = useLocale()
const {pathname, search} = useLocation()
const site = useMemo(() => {
return resolveSiteFromUrl(`${pathname}${search}`)
}, [pathname, search])
adamraya marked this conversation as resolved.
Show resolved Hide resolved
const locale = useMemo(() => {
adamraya marked this conversation as resolved.
Show resolved Hide resolved
return resolveLocaleFromUrl(`${pathname}${search}`)
}, [pathname, search, site])

const [isOnline, setIsOnline] = useState(true)
const styles = useStyleConfig('App')

const configValues = {
locale: locale.alias || locale.id,
site: site.alias || site.id
}

const {isOpen, onOpen, onClose} = useDisclosure()

// Used to conditionally render header/footer for checkout page
Expand Down Expand Up @@ -115,15 +115,16 @@ const App = (props) => {

const onLogoClick = () => {
// Goto the home page.
const path = homeUrlBuilder(HOME_HREF, {locale, site})
const path = fillUrlTemplate(HOME_HREF)
adamraya marked this conversation as resolved.
Show resolved Hide resolved

history.push(path)

// Close the drawer.
onClose()
}

const onCartClick = () => {
const path = buildPathWithUrlConfig('/cart', configValues)
const path = fillUrlTemplate('/cart')
history.push(path)

// Close the drawer.
Expand All @@ -133,7 +134,7 @@ const App = (props) => {
const onAccountClick = () => {
// Link to account page for registered customer, open auth modal otherwise
if (customer.isRegistered) {
const path = buildPathWithUrlConfig('/account', configValues)
const path = fillUrlTemplate('/account')
history.push(path)
} else {
// if they already are at the login page, do not show login modal
Expand All @@ -143,7 +144,7 @@ const App = (props) => {
}

const onWishlistClick = () => {
const path = buildPathWithUrlConfig('/account/wishlist', configValues)
const path = fillUrlTemplate('/account/wishlist')
history.push(path)
}

Expand Down Expand Up @@ -184,19 +185,15 @@ const App = (props) => {
<link
rel="alternate"
hrefLang={locale.id.toLowerCase()}
href={`${appOrigin}${getPathWithLocale(locale.id, {
location
})}`}
href={`${appOrigin}${fillUrlTemplate(location.pathname)}`}
key={locale.id}
/>
))}
{/* A general locale as fallback. For example: "en" if default locale is "en-GB" */}
<link
rel="alternate"
hrefLang={site.l10n.defaultLocale.slice(0, 2)}
href={`${appOrigin}${getPathWithLocale(site.l10n.defaultLocale, {
location
})}`}
href={`${appOrigin}${fillUrlTemplate(location.pathname)}`}
/>
{/* A wider fallback for user locales that the app does not support */}
<link rel="alternate" hrefLang="x-default" href={`${appOrigin}/`} />
Expand All @@ -222,11 +219,15 @@ const App = (props) => {
onClose={onClose}
onLogoClick={onLogoClick}
root={allCategories[DEFAULT_ROOT_CATEGORY]}
locale={locale}
/>
</HideOnDesktop>

<HideOnMobile>
<ListMenu root={allCategories[DEFAULT_ROOT_CATEGORY]} />
<ListMenu
root={allCategories[DEFAULT_ROOT_CATEGORY]}
locale={locale}
/>
</HideOnMobile>
</Header>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ afterEach(() => {

describe('App', () => {
const site = {
...mockConfig.app.sites[0],
alias: 'uk'
site: {
...mockConfig.app.sites[0],
alias: 'uk'
}
}
test('App component is rendered appropriately', () => {
useSite.mockImplementation(() => site)
Expand Down Expand Up @@ -77,7 +79,7 @@ describe('App', () => {
const hasGeneralLocale = ({hrefLang}) => hrefLang === DEFAULT_LOCALE.slice(0, 2)

// `length + 2` because one for a general locale and the other with x-default value
expect(hreflangLinks.length).toBe(site.l10n.supportedLocales.length + 2)
expect(hreflangLinks.length).toBe(site.site.l10n.supportedLocales.length + 2)

expect(hreflangLinks.some((link) => hasGeneralLocale(link))).toBe(true)
expect(hreflangLinks.some((link) => link.hrefLang === 'x-default')).toBe(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import LoadingSpinner from '../loading-spinner'

import useNavigation from '../../hooks/use-navigation'
import useSite from '../../hooks/use-site'
import useUrlTemplate from '../../hooks/use-url-template'

// 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 Expand Up @@ -84,8 +85,9 @@ const DrawerMenu = ({isOpen, onClose = noop, onLogoClick = noop, root}) => {
const styles = useMultiStyleConfig('DrawerMenu')
const drawerSize = useBreakpointValue({sm: PHONE_DRAWER_SIZE, md: TABLET_DRAWER_SIZE})
const socialIconVariant = useBreakpointValue({base: 'flex', md: 'flex-start'})
const site = useSite()
const {site} = useSite()
const {l10n} = site
const {fillUrlTemplate} = useUrlTemplate()
const [showLoading, setShowLoading] = useState(false)
const onSignoutClick = async () => {
setShowLoading(true)
Expand Down Expand Up @@ -272,9 +274,13 @@ const DrawerMenu = ({isOpen, onClose = noop, onLogoClick = noop, root}) => {
locales={supportedLocaleIds}
onSelect={(newLocale) => {
// Update the `locale` in the URL.
const newUrl = getPathWithLocale(newLocale, {
disallowParams: ['refine']
})
const newUrl = getPathWithLocale(
newLocale,
fillUrlTemplate,
{
disallowParams: ['refine']
}
)
window.location = newUrl
}}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ import {HideOnDesktop, HideOnMobile} from '../responsive'
import {getPathWithLocale} from '../../utils/url'
import LocaleText from '../locale-text'
import useSite from '../../hooks/use-site'
import useUrlTemplate from '../../hooks/use-url-template'

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

Expand Down Expand Up @@ -136,9 +138,13 @@ const Footer = ({...otherProps}) => {
setLocale(target.value)

// Update the `locale` in the URL.
const newUrl = getPathWithLocale(target.value, {
disallowParams: ['refine']
})
const newUrl = getPathWithLocale(
target.value,
fillUrlTemplate,
{
disallowParams: ['refine']
}
)

window.location = newUrl
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,12 @@ 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 useUrlTemplate from '../../hooks/use-url-template'

const Link = React.forwardRef(({href, to, useNavLink = false, ...props}, ref) => {
const _href = to || href
const site = useSite()
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 {fillUrlTemplate} = useUrlTemplate()
const updatedHref = fillUrlTemplate(_href)
return (
<ChakraLink
as={useNavLink ? NavSPALink : SPALink}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ test('renders a link with locale prepended', () => {
delete window.location
window.location = new URL('/us/en-US', 'https://www.example.com')
const {getByText} = renderWithProviders(<Link href="/mypage">My Page</Link>, {
wrapperProps: {locale: 'en-US'}
wrapperProps: {locale: 'en-US', siteAlias: 'us', appConfig: mockConfig.app}
})
expect(getByText(/My Page/i)).toHaveAttribute('href', '/us/en-US/mypage')
})
Expand All @@ -49,7 +49,7 @@ test('renders a link with locale and site as query param', () => {
delete window.location
window.location = new URL('https://www.example.com/women/dresses?site=us&locale=en-US')
const {getByText} = renderWithProviders(<Link href="/mypage">My Page</Link>, {
wrapperProps: {locale: 'en-US'}
wrapperProps: {locale: 'en-US', siteAlias: 'us', appConfig: newConfig.app}
})

expect(getByText(/My Page/i)).toHaveAttribute('href', `/mypage?site=us&locale=en-US`)
Expand All @@ -60,7 +60,7 @@ test('accepts `to` prop as well', () => {
delete window.location
window.location = new URL('us/en-US', 'https://www.example.com')
const {getByText} = renderWithProviders(<Link to="/mypage">My Page</Link>, {
wrapperProps: {locale: 'en-US'}
wrapperProps: {locale: 'en-US', siteAlias: 'us', appConfig: mockConfig.app}
})
expect(getByText(/My Page/i)).toHaveAttribute('href', '/us/en-US/mypage')
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import SearchInput from './index'
import Suggestions from './partials/suggestions'
import {noop} from '../../utils/utils'
import mockSearchResults from '../../commerce-api/mocks/searchResults'
import mockConfig from '../../../config/mocks/default'

jest.mock('../../commerce-api/utils', () => {
const originalModule = jest.requireActual('../../commerce-api/utils')
Expand Down Expand Up @@ -53,7 +54,9 @@ test('renders Popover if recent searches populated', async () => {
})

test('changes url when enter is pressed', async () => {
renderWithProviders(<SearchInput />)
renderWithProviders(<SearchInput />, {
wrapperProps: {siteAlias: 'uk', appConfig: mockConfig.app}
})
const searchInput = document.querySelector('input[type="search"]')
await user.type(searchInput, 'Dresses{enter}')
await waitFor(() => expect(window.location.pathname).toEqual(createPathWithDefaults('/search')))
Expand Down
Loading