fix: too many RSC props were being passed, inflating initial HTML size (#7474)
The following config caused the html size to grow to 500mb:
```ts
import type { ArrayField, Block, CollectionConfig } from 'payload'
import { BlocksFeature, lexicalEditor } from '@payloadcms/richtext-lexical'
const richTextLayoutBlockGridBoxes2: ArrayField = {
name: 'gridBx',
labels: { singular: 'Grid Box', plural: 'Grid Boxes' },
type: 'array',
fields: [
{
name: 'gridBx',
label: 'Grid Box Content',
type: 'blocks',
maxRows: 1,
blocks: [],
},
],
}
const richTextLayoutBlock2: Block = {
slug: 'layout',
interfaceName: 'RichTextLayoutBlock',
labels: { singular: 'Layout', plural: 'Layout' },
fields: [richTextLayoutBlockGridBoxes2],
}
const richTextBlock2: Block = {
slug: 'rich-text',
interfaceName: 'RichTextBlock',
labels: { singular: 'Rich Text', plural: 'Rich Text' },
fields: [
{
name: 'richTextContent',
label: 'Rich Text',
type: 'richText',
required: true,
editor: lexicalEditor({
features: ({ defaultFeatures }) => [
...defaultFeatures,
BlocksFeature({ blocks: [richTextLayoutBlock2] }),
],
}),
},
],
}
const richTextLayoutBlockGridBoxes1: ArrayField = {
name: 'gridBx',
labels: { singular: 'Grid Box', plural: 'Grid Boxes' },
type: 'array',
fields: [
{
name: 'gridBx',
label: 'Grid Box Content',
type: 'blocks',
maxRows: 1,
blocks: [richTextBlock2],
},
],
}
const richTextLayoutBlock1: Block = {
slug: 'layout',
interfaceName: 'RichTextLayoutBlock',
labels: { singular: 'Layout', plural: 'Layout' },
fields: [richTextLayoutBlockGridBoxes1],
}
const richTextBlock1: Block = {
slug: 'rich-text',
interfaceName: 'RichTextBlock',
labels: { singular: 'Rich Text', plural: 'Rich Text' },
fields: [
{
name: 'richTextContent',
label: 'Rich Text',
type: 'richText',
required: true,
editor: lexicalEditor({
features: ({ defaultFeatures }) => [
...defaultFeatures,
BlocksFeature({ blocks: [richTextLayoutBlock1] }),
],
}),
},
],
}
const richTextLayoutBlockGridBoxes: ArrayField = {
name: 'gridBx',
labels: { singular: 'Grid Box', plural: 'Grid Boxes' },
type: 'array',
fields: [
{
name: 'gridBx',
label: 'Grid Box Content',
type: 'blocks',
maxRows: 1,
blocks: [richTextBlock1],
},
],
}
const richTextLayoutBlock: Block = {
slug: 'layout',
interfaceName: 'RichTextLayoutBlock',
labels: { singular: 'Layout', plural: 'Layout' },
fields: [richTextLayoutBlockGridBoxes],
}
const richTextBlock: Block = {
slug: 'rich-text',
interfaceName: 'RichTextBlock',
labels: { singular: 'Rich Text', plural: 'Rich Text' },
fields: [
{
name: 'richTextContent',
label: 'Rich Text',
type: 'richText',
required: true,
editor: lexicalEditor({
features: ({ defaultFeatures }) => [
...defaultFeatures,
BlocksFeature({ blocks: [richTextLayoutBlock] }),
],
}),
},
],
}
const layoutBlockGridBoxes2: ArrayField = {
name: 'gridBx',
label: 'Grid Boxes',
type: 'array',
fields: [
{
name: 'gridBx',
label: 'Grid Box Content',
type: 'blocks',
maxRows: 1,
blocks: [richTextBlock],
},
],
}
const layoutBlock2: Block = {
slug: 'layout',
interfaceName: 'LayoutBlock',
labels: { singular: 'Layout', plural: 'Layout' },
fields: [layoutBlockGridBoxes2],
}
const layoutBlockGridBoxes1: ArrayField = {
name: 'gridBx',
label: 'Grid Boxes',
type: 'array',
fields: [
{
name: 'gridBx',
label: 'Grid Box Content',
type: 'blocks',
maxRows: 1,
blocks: [layoutBlock2, richTextBlock],
},
],
}
const layoutBlock1: Block = {
slug: 'layout',
interfaceName: 'LayoutBlock',
labels: { singular: 'Layout', plural: 'Layout' },
fields: [layoutBlockGridBoxes1],
}
const layoutBlockGridBoxes: ArrayField = {
name: 'gridBx',
labels: { singular: 'Grid Box', plural: 'Grid Boxes' },
type: 'array',
fields: [
{
name: 'gridBx',
label: 'Grid Box Content',
type: 'blocks',
maxRows: 1,
blocks: [layoutBlock1, richTextBlock],
},
],
}
const layoutBlock: Block = {
slug: 'layout',
interfaceName: 'LayoutBlock',
labels: { singular: 'Layout', plural: 'Layout' },
fields: [layoutBlockGridBoxes],
}
export const Pages: CollectionConfig = {
slug: 'pages',
fields: [
{
name: 'content',
type: 'blocks',
blocks: [layoutBlock],
},
],
}
```
---------
Co-authored-by: James <james@trbl.design>
This commit is contained in:
@@ -19,6 +19,5 @@ export type GenericDescriptionProps = {
|
|||||||
}
|
}
|
||||||
export type FieldDescriptionProps<T extends keyof FieldTypes = any> = {
|
export type FieldDescriptionProps<T extends keyof FieldTypes = any> = {
|
||||||
type: T
|
type: T
|
||||||
} & FieldComponentProps &
|
} & GenericDescriptionProps &
|
||||||
GenericDescriptionProps &
|
|
||||||
Partial<ServerProps>
|
Partial<ServerProps>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import type { CustomComponent, ServerProps } from '../../config/types.js'
|
import type { CustomComponent, ServerProps } from '../../config/types.js'
|
||||||
import type { FieldComponentProps } from '../fields/index.js'
|
|
||||||
import type { FormFieldBase } from './Field.js'
|
import type { FormFieldBase } from './Field.js'
|
||||||
import type { FieldTypes } from './FieldTypes.js'
|
import type { FieldTypes } from './FieldTypes.js'
|
||||||
|
|
||||||
@@ -11,11 +10,11 @@ export type GenericLabelProps = {
|
|||||||
} & FormFieldBase
|
} & FormFieldBase
|
||||||
|
|
||||||
export type LabelProps<T extends keyof FieldTypes = any> = {
|
export type LabelProps<T extends keyof FieldTypes = any> = {
|
||||||
|
label?: FormFieldBase['label']
|
||||||
|
required?: boolean
|
||||||
|
} & {
|
||||||
type: T
|
type: T
|
||||||
} & FieldComponentProps &
|
} & GenericLabelProps
|
||||||
GenericLabelProps &
|
|
||||||
Partial<ServerProps>
|
|
||||||
|
|
||||||
export type SanitizedLabelProps<T extends keyof FieldTypes = any> = Omit<
|
export type SanitizedLabelProps<T extends keyof FieldTypes = any> = Omit<
|
||||||
LabelProps<T>,
|
LabelProps<T>,
|
||||||
'label' | 'required'
|
'label' | 'required'
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import type {
|
|||||||
CustomComponent,
|
CustomComponent,
|
||||||
DateFieldProps,
|
DateFieldProps,
|
||||||
EmailFieldProps,
|
EmailFieldProps,
|
||||||
ErrorProps,
|
|
||||||
Field,
|
Field,
|
||||||
FieldComponentProps,
|
FieldComponentProps,
|
||||||
FieldDescriptionProps,
|
FieldDescriptionProps,
|
||||||
@@ -38,7 +37,7 @@ import type {
|
|||||||
} from 'payload'
|
} from 'payload'
|
||||||
|
|
||||||
import { MissingEditorProp } from 'payload'
|
import { MissingEditorProp } from 'payload'
|
||||||
import { deepCopyObject, fieldAffectsData, fieldIsPresentationalOnly } from 'payload/shared'
|
import { fieldAffectsData, fieldIsPresentationalOnly } from 'payload/shared'
|
||||||
import React, { Fragment } from 'react'
|
import React, { Fragment } from 'react'
|
||||||
|
|
||||||
import type { WithServerSidePropsPrePopulated } from './index.js'
|
import type { WithServerSidePropsPrePopulated } from './index.js'
|
||||||
@@ -57,20 +56,6 @@ function generateFieldPath(parentPath, name) {
|
|||||||
return tabPath
|
return tabPath
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareCustomComponentProps(
|
|
||||||
props: {
|
|
||||||
[key: string]: any
|
|
||||||
} & FieldComponentProps,
|
|
||||||
) {
|
|
||||||
return deepCopyObject({
|
|
||||||
...props,
|
|
||||||
fieldMap: undefined,
|
|
||||||
richTextComponentMap: undefined,
|
|
||||||
rows: undefined,
|
|
||||||
tabs: undefined,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export const mapFields = (args: {
|
export const mapFields = (args: {
|
||||||
WithServerSideProps: WithServerSidePropsPrePopulated
|
WithServerSideProps: WithServerSidePropsPrePopulated
|
||||||
config: SanitizedConfig
|
config: SanitizedConfig
|
||||||
@@ -675,11 +660,12 @@ export const mapFields = (args: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const labelProps: Omit<LabelProps, 'type'> = prepareCustomComponentProps({
|
const labelProps: LabelProps = {
|
||||||
...fieldComponentPropsBase,
|
type: field.type,
|
||||||
type: undefined,
|
label,
|
||||||
|
required: 'required' in field ? field.required : undefined,
|
||||||
schemaPath: path,
|
schemaPath: path,
|
||||||
})
|
}
|
||||||
|
|
||||||
const CustomLabelComponent =
|
const CustomLabelComponent =
|
||||||
('admin' in field &&
|
('admin' in field &&
|
||||||
@@ -756,11 +742,10 @@ export const mapFields = (args: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const descriptionProps: FieldDescriptionProps = prepareCustomComponentProps({
|
const descriptionProps: FieldDescriptionProps = {
|
||||||
...fieldComponentPropsBase,
|
type: field.type,
|
||||||
type: undefined,
|
|
||||||
description,
|
description,
|
||||||
})
|
}
|
||||||
|
|
||||||
let CustomDescriptionComponent = undefined
|
let CustomDescriptionComponent = undefined
|
||||||
|
|
||||||
@@ -782,11 +767,9 @@ export const mapFields = (args: {
|
|||||||
/>
|
/>
|
||||||
) : undefined
|
) : undefined
|
||||||
|
|
||||||
const errorProps: ErrorProps = prepareCustomComponentProps({
|
const errorProps = {
|
||||||
...fieldComponentPropsBase,
|
|
||||||
type: undefined,
|
|
||||||
path,
|
path,
|
||||||
})
|
}
|
||||||
|
|
||||||
const CustomErrorComponent =
|
const CustomErrorComponent =
|
||||||
('admin' in field &&
|
('admin' in field &&
|
||||||
|
|||||||
@@ -513,16 +513,16 @@ describe('admin1', () => {
|
|||||||
await expect(page.locator('#custom-field-description')).toBeVisible()
|
await expect(page.locator('#custom-field-description')).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('ensure custom components receive field props', async () => {
|
// test('ensure custom components receive field props', async () => {
|
||||||
await page.goto(customFieldsURL.create)
|
// await page.goto(customFieldsURL.create)
|
||||||
await page.waitForURL(customFieldsURL.create)
|
// await page.waitForURL(customFieldsURL.create)
|
||||||
await expect(page.locator('#custom-field-label')).toContainText(
|
// await expect(page.locator('#custom-field-label')).toContainText(
|
||||||
'The max length of this field is: 100',
|
// 'The max length of this field is: 100',
|
||||||
)
|
// )
|
||||||
await expect(page.locator('#custom-field-description')).toContainText(
|
// await expect(page.locator('#custom-field-description')).toContainText(
|
||||||
'The max length of this field is: 100',
|
// 'The max length of this field is: 100',
|
||||||
)
|
// )
|
||||||
})
|
// })
|
||||||
|
|
||||||
describe('field descriptions', () => {
|
describe('field descriptions', () => {
|
||||||
test('should render static field description', async () => {
|
test('should render static field description', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user