Fix/primeng render performance regression - #19597
Open
devidevio wants to merge 7 commits into
Open
Conversation
added 7 commits
May 23, 2026 13:05
… and opt-out flags
4 tasks
4 tasks
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.
This PR reduces PrimeNG table rendering overhead in component-heavy rows. Spent a lot of time on it, because it really annoyed me.
The issue is most visible in large, non-virtualized
p-tableinstances where each row contains nested PrimeNG components likep-button,p-chip, andp-tag. In v21, these components all go through the newerBaseComponent, PassThrough, metadata, style, and theme-reactivity infrastructure. That infrastructure is useful, but in dense tables the per-instance cost multiplies quickly.The changes keep default behavior backwards compatible and add explicit opt-out paths for performance-sensitive use cases.
New global config options:
New component-level attributes:
All options default to the current behavior (enabled /
true).The Root Cause
PrimeNG v21 does more work per component instance than v17:
BaseComponentprepares theme and scoped token handlingpBindapplies PassThrough attributes/classes/styles/eventsdata-pc-sectionare generated even when no custom PT is usedFor a table with many rows, this becomes a large amount of repeated setup and DOM work.
File-by-file Changes
packages/primeng/src/base/base.tsAdds shared theme-change wiring and grouped theme listeners.
Before, many component instances could register equivalent theme-change listeners. Now shared style invalidation is wired once, and listeners can be grouped by style name.
Impact:
packages/primeng/src/basecomponent/basecomponent.tsMain performance work.
Changes:
$style$paramscx()class valuessx()style valuesptm()/ptms()resultsptm(),ptms(), andptmo()when PT binding is disabledthemeReactivescopedTokensPERFORMANCE_CONTEXTso those options can flow through PrimeNG component subtreesImpact:
packages/primeng/src/bind/bind.tsMakes
pBindcheaper.Changes include:
pBindbecomes a no-op whenptBindingis disabledsetAttrs()calls avoid deep equality checks when object identity is unchangedImpact:
[pBind]packages/primeng/src/button/button.tsAdds performance-context propagation through:
p-buttonpButtonpButtonLabelpButtonIconAlso fixes a bug exposed by disabling PT metadata.
The legacy dynamic
pButtonpath searched for generated icon/label elements usingdata-pc-section. When metadata was disabled, those lookups failed and repeated icon updates could create duplicate icons. This affected expandable table row toggles.The fix stores direct references to dynamically-created icon/label elements and only uses the metadata selector as a fallback.
Impact:
packages/primeng/src/chip/chip.tspackages/primeng/src/tag/tag.tsAdds
PERFORMANCE_CONTEXTprovider.Impact:
p-chipandp-tagcan inherit table-levelthemeReactive/scopedTokenssettingspackages/primeng/src/config/primeng.tsAdds two global config signals:
ptMetadataptBindingThese are wired through
providePrimeNG.Impact:
packages/primeng/src/config/primeng.types.tsAdds the public config typings:
ptMetadata?: booleanptBinding?: booleanUsage:
Defaults are
true.packages/primeng/src/table/table.tsAdds
PERFORMANCE_CONTEXTprovider top-table.This allows a table to act as the local performance boundary:
Impact:
New Options
ptMetadataDisables automatic PrimeNG metadata attributes such as:
data-pc-namedata-pc-sectiondata-pc-extendpc-*attrsUse when the app does not rely on these attributes for tests, styling, or tooling.
ptBindingDisables PassThrough binding entirely.
This disables:
pt[pt]Use only when the app does not use PassThrough.
themeReactiveComponent-level opt-out for runtime theme reactivity.
Use when a component/subtree does not need to react to theme changes after initial render.
scopedTokensComponent-level opt-out for scoped
dttoken handling.Use when the component/subtree does not use scoped design tokens.
Compatibility Notes
Default behavior is unchanged.
The new performance options are opt-in.
Caveats:
ptMetadata: falsecan break tests or selectors relying ondata-pc-*ptBinding: falsedisables PassThrough completelythemeReactive: falsemeans runtime theme changes are not applied reactively in that subtreescopedTokens: falsedisables scopeddthandling in that subtreeValidation
Checked with:
The local PrimeNG package build completed successfully.
Performance
Based on the Stackblitz demo: https://stackblitz.com/edit/ypa916vr-a8fnitry?file=package.json
So the performance of the patch is about 1.87x faster / 87% speed increase.
I'm providing also two demo cases:
You can also check the package out and try it in your own application:
Or via:
Clone the repo locally, run
npm install&npm start- open the browser and play around (open dev tools / console to see the performance logs).Additional note
I've only added the
PERFORMANCE_CONTEXTto a few components, the most common used in an table. May this needs to be extended too.As this includes an change on the base component level, it needs some more testing and more eyes on it without breaking anything else, as this is an fundamental change.
Official.mov
Patched.mov