Performance testing NextJS / React (#19540)
* Remove json.parse(json.stringify( usage to improve performance * Fix missing / duplicate keys in some renders * Fix missing react-is dependency (only seemed to cause problems from pruning on the heroku deploy) * Add nextjs tag to datadog-connect config when nextjs is a query param * Fix router.asPath usage to exclude query param * Fix styling inconsistencies noticed when testing * Add a few tests
This commit is contained in:
@@ -38,6 +38,7 @@ export const DefaultLayout = (props: Props) => {
|
||||
{page.languageVariants.map((languageVariant) => {
|
||||
return (
|
||||
<link
|
||||
key={languageVariant.href}
|
||||
rel="alternate"
|
||||
hrefLang={languageVariant.hreflang}
|
||||
href={`https://docs.github.com${languageVariant.href}`}
|
||||
|
||||
@@ -3,7 +3,7 @@ import Link from 'next/link'
|
||||
import { LinkExternalIcon, MarkGithubIcon } from '@primer/octicons-react'
|
||||
import { useTranslation } from './hooks/useTranslation'
|
||||
import { useMainContext } from './context/MainContext'
|
||||
import { ProductSiteTree } from './product/ProductSiteTree'
|
||||
import { SidebarProduct } from './product/SidebarProduct'
|
||||
import { AllProductsLink } from './product/AllProductsLink'
|
||||
import { useVersion } from './hooks/useVersion'
|
||||
|
||||
@@ -41,7 +41,7 @@ export const SidebarNav = (props: Props) => {
|
||||
</ul>
|
||||
) : (
|
||||
<ul className="sidebar-products">
|
||||
<ProductSiteTree />
|
||||
<SidebarProduct />
|
||||
</ul>
|
||||
)}
|
||||
</nav>
|
||||
|
||||
@@ -141,7 +141,11 @@ export const getMainContextFromRequest = (req: any): MainContextT => {
|
||||
),
|
||||
hidden: req.context.page.hidden || false,
|
||||
},
|
||||
enterpriseServerReleases: JSON.parse(JSON.stringify(req.context.enterpriseServerReleases)),
|
||||
enterpriseServerReleases: pick(req.context.enterpriseServerReleases, [
|
||||
'isOldestReleaseDeprecated',
|
||||
'oldestSupported',
|
||||
'nextDeprecationDate',
|
||||
]),
|
||||
enterpriseServerVersions: req.context.enterpriseServerVersions,
|
||||
currentLanguage: req.context.currentLanguage,
|
||||
languages: Object.fromEntries(
|
||||
@@ -158,12 +162,27 @@ export const getMainContextFromRequest = (req: any): MainContextT => {
|
||||
})
|
||||
),
|
||||
allVersions: req.context.allVersions,
|
||||
// this gets rid of some `undefined` values, which is necessary so next.js can serialize the data
|
||||
currentProductTree: JSON.parse(JSON.stringify(req.context.currentProductTree)),
|
||||
currentProductTree: getCurrentProductTree(req.context.currentProductTree),
|
||||
featureFlags: {},
|
||||
}
|
||||
}
|
||||
|
||||
// only pull things we need from the product tree, and make sure there are default values instead of `undefined`
|
||||
const getCurrentProductTree = (input: any): CurrentProductTree => {
|
||||
return {
|
||||
href: input.href,
|
||||
renderedShortTitle: input.renderedShortTitle || '',
|
||||
renderedFullTitle: input.renderedFullTitle || '',
|
||||
page: {
|
||||
hidden: input.page.hidden || false,
|
||||
documentType: input.page.documentType,
|
||||
title: input.page.title,
|
||||
shortTitle: input.page.shortTitle || '',
|
||||
},
|
||||
childPages: (input.childPages || []).map(getCurrentProductTree),
|
||||
}
|
||||
}
|
||||
|
||||
export const MainContext = createContext<MainContextT | null>(null)
|
||||
|
||||
export const useMainContext = (): MainContextT => {
|
||||
|
||||
@@ -21,7 +21,7 @@ export const FeaturedArticles = () => {
|
||||
{featuredArticles.map((section, i) => {
|
||||
return (
|
||||
<div
|
||||
key={section.label}
|
||||
key={section.label + i}
|
||||
className={cx('col-12 mb-4 mb-lg-0', changelog ? 'col-lg-4' : 'col-lg-6')}
|
||||
>
|
||||
<ArticleList
|
||||
@@ -72,7 +72,7 @@ const ArticleList = ({ title, viewAllHref, articles }: ArticleListProps) => {
|
||||
</div>
|
||||
|
||||
<ul className="list-style-none">
|
||||
{articles.map((link) => {
|
||||
{articles.map((link, i) => {
|
||||
return (
|
||||
<li key={link.href} className="border-top">
|
||||
<Link href={link.href}>
|
||||
|
||||
@@ -16,12 +16,12 @@ export const ProductArticlesList = () => {
|
||||
|
||||
return (
|
||||
<div className="d-flex gutter flex-wrap">
|
||||
{currentProductTree.childPages.map((childPage) => {
|
||||
{currentProductTree.childPages.map((childPage, i) => {
|
||||
if (childPage.page.documentType === 'article') {
|
||||
return null
|
||||
}
|
||||
|
||||
return <ArticleList key={childPage.href} page={childPage} />
|
||||
return <ArticleList key={childPage.href + i} page={childPage} />
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
@@ -45,7 +45,10 @@ const ArticleList = ({ page }: { page: CurrentProductTree }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<li className={cx('mb-3', index >= maxArticles ? 'd-none' : null)}>
|
||||
<li
|
||||
key={grandchildPage.href + index}
|
||||
className={cx('mb-3', index >= maxArticles ? 'd-none' : null)}
|
||||
>
|
||||
<Link href={grandchildPage.href}>
|
||||
<a>{grandchildPage.page.title}</a>
|
||||
</Link>
|
||||
|
||||
@@ -9,7 +9,11 @@ export const TableOfContents = (props: { items?: Array<TocItem> }) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
{(props.items || []).map(({ fullPath: href, title, intro }) => {
|
||||
{(props.items || []).map((obj) => {
|
||||
if (!obj) {
|
||||
return null
|
||||
}
|
||||
const { fullPath: href, title, intro } = obj
|
||||
const isActive = router.pathname === href
|
||||
return (
|
||||
<div key={href} className={cx('mb-5', isActive && 'color-auto-gray-4')}>
|
||||
|
||||
@@ -11,7 +11,7 @@ import { AllProductsLink } from 'components/product/AllProductsLink'
|
||||
// hierarchy of the current page. If an item's URL is also the same as the current URL, the item
|
||||
// also gets an `is-current-page` class.
|
||||
// -->
|
||||
export const ProductSiteTree = () => {
|
||||
export const SidebarProduct = () => {
|
||||
const router = useRouter()
|
||||
const { currentProductTree: currentProductTree } = useMainContext()
|
||||
|
||||
@@ -20,14 +20,16 @@ export const ProductSiteTree = () => {
|
||||
}
|
||||
|
||||
const productTitle = currentProductTree.renderedShortTitle || currentProductTree.renderedFullTitle
|
||||
const routePath = `/${router.locale}${router.asPath.split('?')[0]}` // remove query string
|
||||
return (
|
||||
<>
|
||||
<AllProductsLink />
|
||||
|
||||
{!currentProductTree.page.hidden && (
|
||||
<>
|
||||
<li title="" className="sidebar-product mb-2">
|
||||
<Link href={currentProductTree.href}>
|
||||
<a className="pl-4 pr-5 pb-1 f4">{productTitle}</a>
|
||||
<a className="pl-4 pr-5 pb-1 f4 color-text-primary">{productTitle}</a>
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
@@ -37,10 +39,11 @@ export const ProductSiteTree = () => {
|
||||
const isStandaloneCategory = childPage.page.documentType === 'article'
|
||||
|
||||
const childTitle = childPage.renderedShortTitle || childPage.renderedFullTitle
|
||||
const isActive = router.asPath.includes(childPage.href)
|
||||
const isCurrent = router.asPath === childPage.href
|
||||
const isActive = routePath.includes(routePath)
|
||||
const isCurrent = routePath === childPage.href
|
||||
return (
|
||||
<li
|
||||
key={childPage.href + i}
|
||||
className={cx(
|
||||
'sidebar-category py-1',
|
||||
isActive && 'active',
|
||||
@@ -50,21 +53,19 @@ export const ProductSiteTree = () => {
|
||||
>
|
||||
{isStandaloneCategory ? (
|
||||
<Link href={childPage.href}>
|
||||
<a className="pl-4 pr-2 py-2 f6 text-uppercase d-block flex-auto mr-3">
|
||||
<a className="pl-4 pr-2 py-2 f6 text-uppercase d-block flex-auto mr-3 color-text-primary">
|
||||
{childTitle}
|
||||
</a>
|
||||
</Link>
|
||||
) : (
|
||||
<details
|
||||
className={cx(
|
||||
'dropdown-withArrow details details-reset',
|
||||
router.asPath.includes(childPage.href) || i < 3 ? 'open' : ''
|
||||
)}
|
||||
className={cx('dropdown-withArrow details details-reset')}
|
||||
open={routePath.includes(childPage.href) || i < 3}
|
||||
>
|
||||
<summary>
|
||||
<div className="d-flex flex-justify-between">
|
||||
<Link href={childPage.href}>
|
||||
<a className="pl-4 pr-2 py-2 f6 text-uppercase d-block flex-auto mr-3">
|
||||
<a className="pl-4 pr-2 py-2 f6 text-uppercase d-block flex-auto mr-3 color-text-primary">
|
||||
{childTitle}
|
||||
</a>
|
||||
</Link>
|
||||
@@ -87,19 +88,20 @@ export const ProductSiteTree = () => {
|
||||
)}
|
||||
</div>
|
||||
</summary>
|
||||
{router.asPath.includes(childPage.href) || i < 3 ? (
|
||||
{routePath.includes(childPage.href) || i < 3 ? (
|
||||
<>
|
||||
{/* <!-- some categories have maptopics with child articles --> */}
|
||||
{childPage.childPages[0].page.documentType === 'mapTopic' ? (
|
||||
<ul className="sidebar-topics list-style-none position-relative">
|
||||
{childPage.childPages.map((grandchildPage) => {
|
||||
{childPage.childPages.map((grandchildPage, i) => {
|
||||
const grandchildTitle =
|
||||
grandchildPage.renderedShortTitle ||
|
||||
grandchildPage.renderedFullTitle
|
||||
const isActive = router.asPath.includes(grandchildPage.href)
|
||||
const isCurrent = router.asPath === grandchildPage.href
|
||||
const isActive = routePath.includes(grandchildPage.href)
|
||||
const isCurrent = routePath === grandchildPage.href
|
||||
return (
|
||||
<li
|
||||
key={childPage.href + i}
|
||||
className={cx(
|
||||
'sidebar-maptopic',
|
||||
isActive && 'active',
|
||||
@@ -107,7 +109,7 @@ export const ProductSiteTree = () => {
|
||||
)}
|
||||
>
|
||||
<Link href={grandchildPage.href}>
|
||||
<a className="pl-4 pr-5 py-2">{grandchildTitle}</a>
|
||||
<a className="pl-4 pr-5 py-2 color-text-primary">{grandchildTitle}</a>
|
||||
</Link>
|
||||
<ul className="sidebar-articles my-2">
|
||||
{grandchildPage.childPages.map(
|
||||
@@ -116,13 +118,13 @@ export const ProductSiteTree = () => {
|
||||
greatgrandchildPage.renderedShortTitle ||
|
||||
greatgrandchildPage.renderedFullTitle
|
||||
const isLast = i === arr.length - 1
|
||||
const isActive = router.asPath.includes(
|
||||
const isActive = routePath.includes(
|
||||
greatgrandchildPage.href
|
||||
)
|
||||
const isCurrent =
|
||||
router.asPath === greatgrandchildPage.href
|
||||
const isCurrent = routePath === greatgrandchildPage.href
|
||||
return (
|
||||
<li
|
||||
key={greatgrandchildPage.href + i}
|
||||
className={cx(
|
||||
'sidebar-article',
|
||||
isActive && 'active',
|
||||
@@ -132,7 +134,7 @@ export const ProductSiteTree = () => {
|
||||
<Link href={greatgrandchildPage.href}>
|
||||
<a
|
||||
className={cx(
|
||||
'pl-6 pr-5 py-1',
|
||||
'pl-6 pr-5 py-1 color-text-primary',
|
||||
isLast && 'pb-2'
|
||||
)}
|
||||
>
|
||||
@@ -156,10 +158,11 @@ export const ProductSiteTree = () => {
|
||||
grandchildPage.renderedShortTitle ||
|
||||
grandchildPage.renderedFullTitle
|
||||
const isLast = i === arr.length - 1
|
||||
const isActive = router.asPath.includes(grandchildPage.href)
|
||||
const isCurrent = router.asPath === grandchildPage.href
|
||||
const isActive = routePath.includes(grandchildPage.href)
|
||||
const isCurrent = routePath === grandchildPage.href
|
||||
return (
|
||||
<li
|
||||
key={grandchildPage.href + i}
|
||||
className={cx(
|
||||
'sidebar-article',
|
||||
isActive && 'active',
|
||||
@@ -167,7 +170,7 @@ export const ProductSiteTree = () => {
|
||||
)}
|
||||
>
|
||||
<Link href={grandchildPage.href}>
|
||||
<a className={cx('pl-6 pr-5 py-1', isLast && 'pb-2')}>
|
||||
<a className={cx('pl-6 pr-5 py-1 color-text-primary', isLast && 'pb-2')}>
|
||||
{grandchildTitle}
|
||||
</a>
|
||||
</Link>
|
||||
Reference in New Issue
Block a user