poc: remove importMap, import paths, form state endpoint#15774
Draft
poc: remove importMap, import paths, form state endpoint#15774
Conversation
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
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:
|
Contributor
📦 esbuild Bundle Analysis for payloadThis analysis was generated by esbuild-bundle-analyzer. 🤖
Largest pathsThese visualization shows top 20 largest paths in the bundle.Meta file: packages/next/meta_index.json, Out file: esbuild/index.js
Meta file: packages/payload/meta_index.json, Out file: esbuild/index.js
Meta file: packages/payload/meta_shared.json, Out file: esbuild/exports/shared.js
Meta file: packages/richtext-lexical/meta_client.json, Out file: esbuild/exports/client_optimized/index.js
Meta file: packages/ui/meta_client.json, Out file: esbuild/exports/client_optimized/index.js
Meta file: packages/ui/meta_shared.json, Out file: esbuild/exports/shared_optimized/index.js
DetailsNext to the size is how much the size has increased or decreased compared with the base branch of this PR.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Before
Custom admin components were referenced via string paths (
'/components/MyField/index.js#MyField') inpayload.config.ts. An auto-generatedimportMap.jsresolved 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 componentspayload.config.admin.client.tsx('use client') - client components, validation functions, conditionspayload.config.shared.ts(optional) - validators/conditional logic that run on both client and server, auto-merged into both configsThe 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-rscserver 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
SchemaPathMapinterface maps every schema path to its field type, providing autocomplete and field-type-appropriate component slots (e.g.RowLabelonly on array fields,Blockonly 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.