Improvement: reduce component serialization payload by excluding defaults and None values#577
Draft
krzysztof-causalens wants to merge 6 commits intomasterfrom
Draft
Improvement: reduce component serialization payload by excluding defaults and None values#577krzysztof-causalens wants to merge 6 commits intomasterfrom
krzysztof-causalens wants to merge 6 commits intomasterfrom
Conversation
Reduce payload size by not serializing styling fields when they match their class defaults. Uses _exclude_when_default ClassVar on ComponentInstance and StyledComponentInstance, resolved via model_fields for correct per-class defaults. Client-side fixes for bold/italic/underline, hug inheritance, and Stack hug defaulting.
…on-side override, simplify Text align default
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.
Motivation and Context
Component serialization included all field values — even defaults like
bold: false,italic: false,underline: false,background: null,direction: 'vertical',searchable: false, etc. — on every single component instance. For a typical page with dozens of Stacks, Buttons, Tables, and other components this wastes significant bandwidth, since the client already knows the defaults.Before:
After:

22% decrease on the demo components page, depends on the components used. In a different local app I've seen almost a 50% decrease (125KB -> 75KB)
Implementation Description
1.
_exclude_when_defaultmechanism (definitions.py)Added a
_exclude_when_defaultClassVar onComponentInstanceandStyledComponentInstancethat lists fields to omit from serialization when they match their declared default. The serializer resolves defaults per-class viatype(self).model_fields, so subclass overrides (e.g.Stack.hug=FalsevsStyledComponentInstance.hug=None) are handled correctly.ComponentInstanceexcludes:raw_css,track_progress,error_handler,fallback,id_,for_StyledComponentInstanceextends with ~25 styling fields (bold,italic,underline,align,background,hug, all dimensions, etc.)positionis intentionally kept —LayoutComponentoverrides it to'relative'and clients depend on receiving it2. Opt-in None exclusion via
_exclude_none_when_defaultflag (definitions.py)Added a
_exclude_none_when_default: ClassVar[bool]flag onComponentInstance(defaultFalse). WhenTrue, the serializer strips any field where the value isNoneand the field's declared default isNone. This catches everyOptional[X] = Nonefield automatically without needing to list them in_exclude_when_default.This is opt-in, not global, to avoid breaking downstream components that may use strict
=== nullchecks on props. First-party components opt in via:BaseDashboardComponent(the base for all dara-components) sets the flag toTrueFor(extendsComponentInstancedirectly) sets the flag toTrueDownstream components extending
ComponentInstanceorStyledComponentInstancedirectly keep the defaultFalse(backwards compatible).Fields where
Noneis not the default (e.g.track_progress: bool | None = False) are NOT stripped when explicitly set toNone.3. Component-specific
_exclude_when_defaultextensionsExtended
_exclude_when_defaulton commonly used components to also exclude their component-specific fields at defaults:collapsed,direction,scroll(keepshug— itsFalsedefault differs from parent'sNone)outline,stop_click_propagationformattedmultiselect,searchable,max_rowsmulti_select,searchable,include_index,show_checkboxes,suppress_click_events_for_selection4. Client-side fixes
For fields where
undefined(missing prop) doesn't behave identically to the Python default, added client-side fallbacks via destructuring defaults:{ direction = 'vertical', ...props }—DisplayCtx.Providerand styled component need an explicit value{ max_rows = 3, ...props }— direct passthrough to UI component{ include_index = true, show_checkboxes = true, ...props }— truthy/falsy checks invert forTrue-default booleans!== null→!= nullfortitle/subtitle— only component with strict null checks on props=== null→== nullforvirtualization— prevented fallthrough to virtualized render pathbold/italic/underlineternaries now emitundefinedinstead of'normal'/'none'useComponentStyles: hug-inheritance check changed from!== falseto== null;Text.aligndefault changed from'left'toNone5. Other
Text.aligndefault changed from'left'toNone— CSStext-aligndefaults tostartanywayAny new dependencies Introduced
None.
How Has This Been Tested?
PR Checklist: