Skip to content

Commit

Permalink
perf: significantly reduce HTML we send to the client. Up to 4x small…
Browse files Browse the repository at this point in the history
…er (#9321)

The biggest difference comes from calling `RenderServerComponent` as a
function, instead of rendering it by using `<RenderServerComponent`.

This gets rid of wasteful blocks of codes sent to the client that look
like this:

![CleanShot 2024-11-18 at 20 41
20@2x](https://github.com/user-attachments/assets/edb67d72-f4a5-459b-93f4-68dc65aeffb6)


HTML size comparison:

## Admin test suite

| View | Before | After |
|------|---------|--------|
| Dashboard | 331 kB | 83 kB |
| collections/custom-views-one Edit | 285 kB | 76.6 kB |

## Fields test suite

| View | Before | After |
|------|---------|--------|
| collections/lexical Edit | 189 kB | 94.4 kB |
| collections/lexical List | 152 kB | 62.9 kB |

## Community test suite

| View | Before | After |
|------|---------|--------|
| Dashboard | 78.9 kB | 43.1 kB |
  • Loading branch information
AlessioGr authored Nov 19, 2024
1 parent 1425d58 commit 5d2b0b3
Show file tree
Hide file tree
Showing 25 changed files with 456 additions and 515 deletions.
14 changes: 7 additions & 7 deletions packages/next/src/elements/DocumentHeader/Tabs/Tab/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,16 @@ export const DocumentTab: React.FC<
{Pill || Pill_Component ? (
<Fragment>
&nbsp;
<RenderServerComponent
Component={Pill}
Fallback={Pill_Component}
importMap={payload.importMap}
serverProps={{
{RenderServerComponent({
Component: Pill,
Fallback: Pill_Component,
importMap: payload.importMap,
serverProps: {
i18n,
payload,
permissions,
}}
/>
},
})}
</Fragment>
) : null}
</span>
Expand Down
32 changes: 15 additions & 17 deletions packages/next/src/elements/DocumentHeader/Tabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,23 +80,21 @@ export const DocumentTabs: React.FC<{
const { path, tab } = CustomView

if (tab.Component) {
return (
<RenderServerComponent
clientProps={{
path,
}}
Component={tab.Component}
importMap={payload.importMap}
key={`tab-custom-${index}`}
serverProps={{
collectionConfig,
globalConfig,
i18n,
payload,
permissions,
}}
/>
)
return RenderServerComponent({
clientProps: {
path,
},
Component: tab.Component,
importMap: payload.importMap,
key: `tab-custom-${index}`,
serverProps: {
collectionConfig,
globalConfig,
i18n,
payload,
permissions,
},
})
}

return (
Expand Down
32 changes: 15 additions & 17 deletions packages/next/src/elements/Logo/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { ServerProps } from 'payload'
import type React from 'react'

import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent'
import { PayloadLogo } from '@payloadcms/ui/shared'
import React from 'react'

export const Logo: React.FC<ServerProps> = (props) => {
const { i18n, locale, params, payload, permissions, searchParams, user } = props
Expand All @@ -17,20 +17,18 @@ export const Logo: React.FC<ServerProps> = (props) => {
} = {},
} = payload.config

return (
<RenderServerComponent
Component={CustomLogo}
Fallback={PayloadLogo}
importMap={payload.importMap}
serverProps={{
i18n,
locale,
params,
payload,
permissions,
searchParams,
user,
}}
/>
)
return RenderServerComponent({
Component: CustomLogo,
Fallback: PayloadLogo,
importMap: payload.importMap,
serverProps: {
i18n,
locale,
params,
payload,
permissions,
searchParams,
user,
},
})
}
56 changes: 28 additions & 28 deletions packages/next/src/elements/Nav/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,52 +59,52 @@ export const DefaultNav: React.FC<NavProps> = async (props) => {

const navPreferences = await getNavPrefs({ payload, user })

const LogoutComponent = RenderServerComponent({
Component: logout?.Button,
Fallback: Logout,
importMap: payload.importMap,
serverProps: {
i18n,
locale,
params,
payload,
permissions,
searchParams,
user,
},
})

return (
<NavWrapper baseClass={baseClass}>
<nav className={`${baseClass}__wrap`}>
<RenderServerComponent
Component={beforeNavLinks}
importMap={payload.importMap}
serverProps={{
{RenderServerComponent({
Component: beforeNavLinks,
importMap: payload.importMap,
serverProps: {
i18n,
locale,
params,
payload,
permissions,
searchParams,
user,
}}
/>
},
})}
<DefaultNavClient groups={groups} navPreferences={navPreferences} />
<RenderServerComponent
Component={afterNavLinks}
importMap={payload.importMap}
serverProps={{
{RenderServerComponent({
Component: afterNavLinks,
importMap: payload.importMap,
serverProps: {
i18n,
locale,
params,
payload,
permissions,
searchParams,
user,
}}
/>
<div className={`${baseClass}__controls`}>
<RenderServerComponent
Component={logout?.Button}
Fallback={Logout}
importMap={payload.importMap}
serverProps={{
i18n,
locale,
params,
payload,
permissions,
searchParams,
user,
}}
/>
</div>
},
})}
<div className={`${baseClass}__controls`}>{LogoutComponent}</div>
</nav>
<div className={`${baseClass}__header`}>
<div className={`${baseClass}__header-content`}>
Expand Down
30 changes: 14 additions & 16 deletions packages/next/src/layouts/Root/NestProviders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,18 @@ type Args = {
}

export function NestProviders({ children, importMap, providers }: Args): React.ReactNode {
return (
<RenderServerComponent
clientProps={{
children:
providers.length > 1 ? (
<NestProviders importMap={importMap} providers={providers.slice(1)}>
{children}
</NestProviders>
) : (
children
),
}}
Component={providers[0]}
importMap={importMap}
/>
)
return RenderServerComponent({
clientProps: {
children:
providers.length > 1 ? (
<NestProviders importMap={importMap} providers={providers.slice(1)}>
{children}
</NestProviders>
) : (
children
),
},
Component: providers[0],
importMap,
})
}
17 changes: 9 additions & 8 deletions packages/next/src/routes/rest/og/image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ export const OGImage: React.FC<{
leader,
title,
}) => {
const IconComponent = RenderServerComponent({
clientProps: {
fill: 'white',
},
Component: Icon,
Fallback,
importMap,
})
return (
<div
style={{
Expand Down Expand Up @@ -95,14 +103,7 @@ export const OGImage: React.FC<{
width: '38px',
}}
>
<RenderServerComponent
clientProps={{
fill: 'white',
}}
Component={Icon}
Fallback={Fallback}
importMap={importMap}
/>
{IconComponent}
</div>
</div>
)
Expand Down
86 changes: 45 additions & 41 deletions packages/next/src/templates/Default/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,15 @@ export const DefaultTemplate: React.FC<DefaultTemplateProps> = ({
? viewActions.reduce((acc, action) => {
if (action) {
if (typeof action === 'object') {
acc[action.path] = (
<RenderServerComponent Component={action} importMap={payload.importMap} />
)
acc[action.path] = RenderServerComponent({
Component: action,
importMap: payload.importMap,
})
} else {
acc[action] = (
<RenderServerComponent Component={action} importMap={payload.importMap} />
)
acc[action] = RenderServerComponent({
Component: action,
importMap: payload.importMap,
})
}
}

Expand All @@ -72,15 +74,32 @@ export const DefaultTemplate: React.FC<DefaultTemplateProps> = ({
}
}, [viewActions, payload])

const NavComponent = RenderServerComponent({
clientProps: { clientProps: { visibleEntities } },
Component: CustomNav,
Fallback: DefaultNav,
importMap: payload.importMap,
serverProps: {
i18n,
locale,
params,
payload,
permissions,
searchParams,
user,
visibleEntities,
},
})

return (
<EntityVisibilityProvider visibleEntities={visibleEntities}>
<BulkUploadProvider>
<ActionsProvider Actions={Actions}>
<RenderServerComponent
clientProps={{ clientProps: { visibleEntities } }}
Component={CustomHeader}
importMap={payload.importMap}
serverProps={{
{RenderServerComponent({
clientProps: { clientProps: { visibleEntities } },
Component: CustomHeader,
importMap: payload.importMap,
serverProps: {
i18n,
locale,
params,
Expand All @@ -89,8 +108,8 @@ export const DefaultTemplate: React.FC<DefaultTemplateProps> = ({
searchParams,
user,
visibleEntities,
}}
/>
},
})}
<div style={{ position: 'relative' }}>
<div className={`${baseClass}__nav-toggler-wrapper`} id="nav-toggler">
<div className={`${baseClass}__nav-toggler-container`} id="nav-toggler">
Expand All @@ -100,39 +119,24 @@ export const DefaultTemplate: React.FC<DefaultTemplateProps> = ({
</div>
</div>
<Wrapper baseClass={baseClass} className={className}>
<RenderServerComponent
clientProps={{ clientProps: { visibleEntities } }}
Component={CustomNav}
Fallback={DefaultNav}
importMap={payload.importMap}
serverProps={{
i18n,
locale,
params,
payload,
permissions,
searchParams,
user,
visibleEntities,
}}
/>
{NavComponent}
<div className={`${baseClass}__wrap`}>
<AppHeader
CustomAvatar={
avatar !== 'gravatar' && avatar !== 'default' ? (
<RenderServerComponent
Component={avatar.Component}
importMap={payload.importMap}
/>
) : undefined
avatar !== 'gravatar' && avatar !== 'default'
? RenderServerComponent({
Component: avatar.Component,
importMap: payload.importMap,
})
: undefined
}
CustomIcon={
components?.graphics?.Icon ? (
<RenderServerComponent
Component={components.graphics.Icon}
importMap={payload.importMap}
/>
) : undefined
components?.graphics?.Icon
? RenderServerComponent({
Component: components.graphics.Icon,
importMap: payload.importMap,
})
: undefined
}
/>
{children}
Expand Down
Loading

0 comments on commit 5d2b0b3

Please sign in to comment.