Thanks to visit codestin.com
Credit goes to github.com

Skip to content

poc: remove importMap, import paths, form state endpoint#15774

Draft
AlessioGr wants to merge 43 commits intomainfrom
feat/get-rid-of-importmap-and-formstate
Draft

poc: remove importMap, import paths, form state endpoint#15774
AlessioGr wants to merge 43 commits intomainfrom
feat/get-rid-of-importmap-and-formstate

Conversation

@AlessioGr
Copy link
Member

Before

Custom admin components were referenced via string paths ('/components/MyField/index.js#MyField') in payload.config.ts. An auto-generated importMap.js resolved these strings to actual components at runtime. Every field interaction - adding array rows, opening blocks, rendering drawers - required a server roundtrip through the form state endpoint to render components, compute validation, evaluate conditions, and resolve default values. This made array/block row additions slow (shimmer loading state while waiting for server), drawer openings sluggish, and validation/conditions delayed until the server responded.

After

Custom components are directly imported in two new config files:

  • payload.config.admin.rsc.tsx (no directive) - RSC components, admin-level components (nav, logo, views, actions), collection/global-level components
  • payload.config.admin.client.tsx ('use client') - client components, validation functions, conditions
  • payload.config.shared.ts (optional) - validators/conditional logic that run on both client and server, auto-merged into both configs

The form state endpoint is removed entirely. Client-side validation and conditions run immediately in the browser without waiting for a server response. Array rows and block additions render instantly. Drawers open without delay. RSC field components render on-demand via a lightweight render-admin-rsc server action, called only when the client detects RSC components exist for a given schema path - pure client-side fields never hit the server.

All config keys are fully type-safe. A generated SchemaPathMap interface maps every schema path to its field type, providing autocomplete and field-type-appropriate component slots (e.g. RowLabel only on array fields, Block only on block paths).

Why

The importMap required auto-generation, used fragile string-based resolution, and provided no type safety. The form state endpoint was a big performance bottleneck in the admin panel - every field render, every array row addition, every drawer open, every validation check required a full server roundtrip. This architecture made the admin panel feel slow and unresponsive, especially for complex forms with many fields, nested arrays, or blocks.

Benefits

Instant array row and block rendering - no more loading shimmer waiting for server. Immediate client-side validation and condition evaluation on every keystroke. Fast drawer openings without server delay. Full IDE autocomplete and type checking for all config keys and component slots. No more auto-generated importMap file. Shared validators work across both API and admin UI without duplication. Simpler architecture with clear separation between server and client concerns.

Traverses all collections/globals fields recursively to generate
a TypeScript union type of all valid schema paths.
defineClientConfig, defineRscConfig, defineSharedConfig for the
new multi-file admin config architecture.
Rows no longer need to wait for server roundtrip since form state
endpoint was removed.
Adds payload.config.shared.ts, payload.config.client.ts,
payload.config.rsc.tsx with custom components and validators.
Also adds blocks and array fields to Posts collection.
Layout imports RSC config and passes to RootLayout.
ClientConfigBridge imports client + shared configs,
merges them, and provides via React context.
…ons (Option C)

The config types now support four sections:
- admin: admin-level components (logo, nav, views, etc.)
- collections: per-collection components (beforeList, edit buttons, etc.)
- globals: per-global components (elements, views, etc.)
- fields: field-level components keyed by schema path
Merges client and RSC configs into a single no-directive file that
can hold RSC components, client components, and client functions.
Shared config uses 'use client' so validators serialize across RSC
boundary while remaining executable in Node.js.

Threads adminConfig through handleServerFunctions like importMap was.
Architecture:
- payload.config.admin.client.tsx ('use client') for client components + functions
- payload.config.admin.rsc.tsx (no directive) for RSC components
- payload.config.shared.ts (no directive, optional) for shared validators
- Shared config auto-merged into client config via ClientConfigBridge
- RSC components rendered on-demand via render-admin-rsc server action
- Client components render immediately, no server roundtrip
- rscSchemaPaths metadata tells client which fields need server action
setAdminConfig() called in RootLayout, getAdminConfig() available
to all server components in the render tree for resolving admin-level
RSC components without threading props through every view.
Updates ~49 rendering points in packages/next/src to read
admin-level, collection-level, and global-level components
from the admin config (via getAdminConfig cache) instead of
from config.admin.components string paths.

Admin config takes priority, falls back to original config.
- Created payload.config.admin.rsc.tsx and payload.config.admin.client.tsx
- Removed string-path component references from config.ts and all
  collection/global configs
- Fixed RSC serialization: don't pass rscAdminConfig to RootProvider,
  use server-side cache (getAdminConfig) instead
- rscSchemaPaths passed as serializable string[] for client-side checks
Admin-level components (nav hooks, logout, settings, views) must be
in the RSC config since they're rendered by Server Components.
Client config now only holds field-level overrides.
Also removed rscAdminConfig from RootProvider props to avoid
RSC serialization errors.
Fixed getCustomViewByRoute, isCustomAdminView, getDocumentView,
getMetaBySegment, and Versions metadata to read views and meta
from admin config instead of config.admin.components.
Pass component functions with clientProps instead of pre-rendered JSX.
This allows on-demand rendering with proper props.
getTabs now checks admin config views first for tab configuration,
including custom tab labels, components, order, and paths.
…nput/AfterInput

Custom field components from admin config now receive field, path,
and schemaPath props so they can access field configuration.
…custom Field

When a custom Field component is set alongside Label/Description
overrides, render them all in a wrapper div.
…igation

React cache() is per-request. On client-side navigation, new server
requests don't go through RootLayout, so the admin config cache was
empty. Now handleServerFunctions also sets the cache.
…he()

React cache() is per-request and doesn't persist across client
navigations. Module-level state persists across all requests
within the same process.
- generateSchemaPathTypes now outputs SchemaPathMap interface mapping
  every schema path to its field type ('text', 'array', 'blocks', etc.)
- GeneratedSchemaPathMap module augmentation flows types through
- Conditional FieldConfigFor<T> provides type-appropriate component
  slots per field type (e.g. RowLabel only on array fields,
  Block only on block paths)
- CollectionSlug/GlobalSlug used for collection/global keys
- Admin test configs use hardcoded string literals instead of
  template literal slug variables
@github-actions
Copy link
Contributor

Pull Request titles must follow the Conventional Commits specification and have valid scopes.

Unknown release type "poc" found in pull request title "poc: remove importMap, import paths, form state endpoint".

Available types:

  • build
  • chore
  • ci
  • docs
  • examples
  • feat
  • fix
  • perf
  • refactor
  • revert
  • style
  • templates
  • test
feat(ui): add Button component
^    ^    ^
|    |    |__ Subject
|    |_______ Scope
|____________ Type

@github-actions
Copy link
Contributor

📦 esbuild Bundle Analysis for payload

This analysis was generated by esbuild-bundle-analyzer. 🤖

Meta File Out File Size (raw) Note
packages/next/meta_index.json esbuild/index.js 960.12 KB ⚠️ +164 B (+0.0%)
packages/payload/meta_index.json esbuild/index.js 1.31 MB ✅ -9.04 KB (-0.7%)
packages/payload/meta_shared.json esbuild/exports/shared.js 190.55 KB ✅ -49 B (-0.0%)
packages/richtext-lexical/meta_client.json esbuild/exports/client_optimized/index.js 281.80 KB ✅ No change
packages/ui/meta_client.json esbuild/exports/client_optimized/index.js 1.18 MB ⚠️ +2.93 KB (+0.2%)
packages/ui/meta_shared.json esbuild/exports/shared_optimized/index.js 16.32 KB ✅ No change
Largest paths These visualization shows top 20 largest paths in the bundle.

Meta file: packages/next/meta_index.json, Out file: esbuild/index.js

Path Size
../../node_modules ${{\color{Goldenrod}{ ████████████████████▌ }}}$ 82.0%, 783.61 KB
dist/views/Version ${{\color{Goldenrod}{ █▎ }}}$ 5.4%, 51.44 KB
dist/views/Dashboard ${{\color{Goldenrod}{ ▌ }}}$ 2.2%, 21.35 KB
dist/views/Document ${{\color{Goldenrod}{ ▍ }}}$ 1.8%, 17.00 KB
dist/views/List ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 11.22 KB
dist/views/Root ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 9.46 KB
dist/views/Versions ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 6.16 KB
dist/views/API ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 6.08 KB
dist/elements/Nav ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 5.87 KB
dist/views/Account ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 5.53 KB
dist/elements/DocumentHeader ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 4.84 KB
dist/views/Login ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 4.37 KB
dist/views/ForgotPassword ${{\color{Goldenrod}{ }}}$ 0.3%, 3.09 KB
dist/layouts/Root ${{\color{Goldenrod}{ }}}$ 0.3%, 2.86 KB
dist/views/CreateFirstUser ${{\color{Goldenrod}{ }}}$ 0.3%, 2.81 KB
dist/views/BrowseByFolder ${{\color{Goldenrod}{ }}}$ 0.3%, 2.59 KB
dist/templates/Default ${{\color{Goldenrod}{ }}}$ 0.3%, 2.51 KB
dist/views/CollectionFolders ${{\color{Goldenrod}{ }}}$ 0.3%, 2.42 KB
dist/views/ResetPassword ${{\color{Goldenrod}{ }}}$ 0.3%, 2.40 KB
dist/views/Logout ${{\color{Goldenrod}{ }}}$ 0.2%, 1.94 KB
(other) ${{\color{Goldenrod}{ ████▌ }}}$ 18.0%, 171.83 KB

Meta file: packages/payload/meta_index.json, Out file: esbuild/index.js

Path Size
../../node_modules ${{\color{Goldenrod}{ █████████████████ }}}$ 68.1%, 887.21 KB
dist/fields/hooks ${{\color{Goldenrod}{ ▊ }}}$ 3.3%, 43.59 KB
dist/collections/operations ${{\color{Goldenrod}{ ▊ }}}$ 3.1%, 39.77 KB
dist/versions/migrations ${{\color{Goldenrod}{ ▎ }}}$ 1.4%, 18.50 KB
dist/auth/operations ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 15.74 KB
dist/globals/operations ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 13.17 KB
dist/utilities/configToJSONSchema.js ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 13.15 KB
dist/queues/operations ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 12.80 KB
dist/fields/config ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 12.64 KB
dist/fields/validations.js ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 10.54 KB
dist/collections/config ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 8.30 KB
dist/uploads/fetchAPI-multipart ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.67 KB
dist/database/migrations ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.54 KB
dist/index.js ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.46 KB
dist/config/orderable ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 6.83 KB
dist/collections/endpoints ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 6.22 KB
dist/config/sanitize.js ${{\color{Goldenrod}{ }}}$ 0.4%, 5.80 KB
dist/auth/strategies ${{\color{Goldenrod}{ }}}$ 0.4%, 5.50 KB
dist/auth/endpoints ${{\color{Goldenrod}{ }}}$ 0.4%, 5.42 KB
dist/queues/config ${{\color{Goldenrod}{ }}}$ 0.4%, 5.34 KB
(other) ${{\color{Goldenrod}{ ███████▉ }}}$ 31.9%, 415.07 KB

Meta file: packages/payload/meta_shared.json, Out file: esbuild/exports/shared.js

Path Size
../../node_modules ${{\color{Goldenrod}{ ███████████████████▉ }}}$ 79.5%, 148.51 KB
dist/fields/validations.js ${{\color{Goldenrod}{ █▍ }}}$ 5.6%, 10.54 KB
dist/config/orderable ${{\color{Goldenrod}{ ▍ }}}$ 1.7%, 3.13 KB
dist/fields/baseFields ${{\color{Goldenrod}{ ▍ }}}$ 1.5%, 2.79 KB
dist/utilities/deepCopyObject.js ${{\color{Goldenrod}{ ▎ }}}$ 1.4%, 2.54 KB
dist/auth/cookies.js ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 1.55 KB
dist/utilities/flattenTopLevelFields.js ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 1.42 KB
dist/fields/config ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 1.28 KB
dist/utilities/getVersionsConfig.js ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 1.04 KB
dist/utilities/flattenAllFields.js ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 943 B
dist/folders/utils ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 916 B
dist/utilities/unflatten.js ${{\color{Goldenrod}{ }}}$ 0.4%, 779 B
dist/utilities/sanitizeUserDataForEmail.js ${{\color{Goldenrod}{ }}}$ 0.4%, 713 B
dist/utilities/getFieldPermissions.js ${{\color{Goldenrod}{ }}}$ 0.3%, 651 B
dist/collections/config ${{\color{Goldenrod}{ }}}$ 0.3%, 570 B
dist/auth/sessions.js ${{\color{Goldenrod}{ }}}$ 0.3%, 525 B
dist/fields/getFieldPaths.js ${{\color{Goldenrod}{ }}}$ 0.3%, 485 B
dist/errors/APIError.js ${{\color{Goldenrod}{ }}}$ 0.2%, 438 B
dist/admin/buildClientConfig.js ${{\color{Goldenrod}{ }}}$ 0.2%, 433 B
dist/utilities/getSafeRedirect.js ${{\color{Goldenrod}{ }}}$ 0.2%, 423 B
(other) ${{\color{Goldenrod}{ █████▏ }}}$ 20.5%, 38.30 KB

Meta file: packages/richtext-lexical/meta_client.json, Out file: esbuild/exports/client_optimized/index.js

Path Size
dist/features/blocks ${{\color{Goldenrod}{ ███▏ }}}$ 12.6%, 35.15 KB
dist/lexical/plugins ${{\color{Goldenrod}{ ██▉ }}}$ 11.5%, 32.00 KB
dist/lexical/ui ${{\color{Goldenrod}{ ██▏ }}}$ 8.7%, 24.36 KB
dist/features/experimental_table ${{\color{Goldenrod}{ ██▏ }}}$ 8.5%, 23.70 KB
dist/packages/@lexical ${{\color{Goldenrod}{ █▋ }}}$ 6.8%, 18.99 KB
dist/features/link ${{\color{Goldenrod}{ █▋ }}}$ 6.6%, 18.25 KB
dist/features/toolbars ${{\color{Goldenrod}{ █▌ }}}$ 6.4%, 17.75 KB
dist/features/upload ${{\color{Goldenrod}{ █▏ }}}$ 4.9%, 13.77 KB
dist/features/textState ${{\color{Goldenrod}{ █ }}}$ 4.0%, 11.08 KB
dist/features/relationship ${{\color{Goldenrod}{ ▊ }}}$ 3.2%, 9.03 KB
dist/lexical/utils ${{\color{Goldenrod}{ ▊ }}}$ 3.0%, 8.49 KB
dist/features/debug ${{\color{Goldenrod}{ ▋ }}}$ 2.7%, 7.39 KB
dist/utilities/fieldsDrawer ${{\color{Goldenrod}{ ▋ }}}$ 2.6%, 7.15 KB
dist/features/converters ${{\color{Goldenrod}{ ▋ }}}$ 2.5%, 7.05 KB
dist/lexical/config ${{\color{Goldenrod}{ ▍ }}}$ 1.8%, 5.08 KB
dist/features/lists ${{\color{Goldenrod}{ ▍ }}}$ 1.8%, 5.00 KB
dist/features/format ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 3.46 KB
dist/lexical/LexicalEditor.js ${{\color{Goldenrod}{ ▎ }}}$ 1.1%, 3.17 KB
dist/lexical/theme ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 2.62 KB
dist/features/indent ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 2.50 KB
(other) ${{\color{Goldenrod}{ █████████████████████▊ }}}$ 87.4%, 243.39 KB

Meta file: packages/ui/meta_client.json, Out file: esbuild/exports/client_optimized/index.js

Path Size
../../node_modules ${{\color{Goldenrod}{ ████████████▎ }}}$ 49.4%, 579.02 KB
dist/elements/FolderView ${{\color{Goldenrod}{ ▋ }}}$ 2.5%, 29.37 KB
dist/elements/BulkUpload ${{\color{Goldenrod}{ ▌ }}}$ 2.4%, 27.63 KB
dist/elements/WhereBuilder ${{\color{Goldenrod}{ ▍ }}}$ 1.5%, 17.27 KB
dist/views/Edit ${{\color{Goldenrod}{ ▍ }}}$ 1.5%, 17.14 KB
dist/fields/Relationship ${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 15.78 KB
dist/elements/Table ${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 15.77 KB
dist/forms/Form ${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 15.30 KB
dist/fields/Upload ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 14.24 KB
dist/fields/Blocks ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 13.69 KB
dist/elements/QueryPresets ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 10.36 KB
dist/elements/PublishButton ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 9.07 KB
dist/providers/Folders ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.47 KB
dist/elements/HTMLDiff ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.38 KB
dist/elements/LivePreview ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.38 KB
dist/elements/ListHeader ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 7.99 KB
dist/fields/Array ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 7.73 KB
dist/views/CollectionFolder ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.50 KB
dist/views/List ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.35 KB
dist/elements/ReactSelect ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.34 KB
(other) ${{\color{Goldenrod}{ ████████████▋ }}}$ 50.6%, 593.67 KB

Meta file: packages/ui/meta_shared.json, Out file: esbuild/exports/shared_optimized/index.js

Path Size
dist/graphics/Logo ${{\color{Goldenrod}{ █████ }}}$ 20.0%, 3.12 KB
../../node_modules ${{\color{Goldenrod}{ ████▎ }}}$ 17.0%, 2.65 KB
dist/graphics/Icon ${{\color{Goldenrod}{ ██▍ }}}$ 9.8%, 1.52 KB
dist/utilities/formatDocTitle ${{\color{Goldenrod}{ ██▏ }}}$ 8.5%, 1.32 KB
dist/providers/TableColumns ${{\color{Goldenrod}{ █▍ }}}$ 5.5%, 862 B
dist/utilities/groupNavItems.js ${{\color{Goldenrod}{ █▎ }}}$ 5.2%, 814 B
dist/utilities/getGlobalData.js ${{\color{Goldenrod}{ █▏ }}}$ 4.9%, 762 B
dist/utilities/api.js ${{\color{Goldenrod}{ █▏ }}}$ 4.8%, 756 B
dist/elements/Translation ${{\color{Goldenrod}{ ▊ }}}$ 3.2%, 493 B
dist/utilities/handleTakeOver.js ${{\color{Goldenrod}{ ▋ }}}$ 2.8%, 440 B
dist/utilities/traverseForLocalizedFields.js ${{\color{Goldenrod}{ ▋ }}}$ 2.6%, 399 B
dist/elements/withMergedProps ${{\color{Goldenrod}{ ▌ }}}$ 2.2%, 339 B
dist/utilities/getVisibleEntities.js ${{\color{Goldenrod}{ ▌ }}}$ 2.1%, 329 B
dist/utilities/getNavGroups.js ${{\color{Goldenrod}{ ▍ }}}$ 1.9%, 301 B
dist/elements/WithServerSideProps ${{\color{Goldenrod}{ ▍ }}}$ 1.5%, 232 B
dist/utilities/handleGoBack.js ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 180 B
dist/fields/mergeFieldStyles.js ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 159 B
dist/utilities/handleBackToDashboard.js ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 152 B
dist/forms/Form ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 147 B
dist/utilities/abortAndIgnore.js ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 146 B
(other) ${{\color{Goldenrod}{ ████████████████████ }}}$ 80.0%, 12.51 KB
Details

Next to the size is how much the size has increased or decreased compared with the base branch of this PR.

  • ‼️: Size increased by 20% or more. Special attention should be given to this.
  • ⚠️: Size increased in acceptable range (lower than 20%).
  • ✅: No change or even downsized.
  • 🗑️: The out file is deleted: not found in base branch.
  • 🆕: The out file is newly found: will be added to base branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant