Skip to content

chore: add verify-bundle-isolation to workspace plugin, cleanup deps and onboard react-components to track base hooks creep - #36587

Merged
Martin Hochel (Hotell) merged 2 commits into
microsoft:masterfrom
Hotell:chore/bundle-isolation-react-components
Aug 24, 2026
Merged

chore: add verify-bundle-isolation to workspace plugin, cleanup deps and onboard react-components to track base hooks creep#36587
Martin Hochel (Hotell) merged 2 commits into
microsoft:masterfrom
Hotell:chore/bundle-isolation-react-components

Conversation

@Hotell

@Hotell Martin Hochel (Hotell) commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Previous Behavior

@fluentui/react-components had no bundle isolation guarantee — bundle-size/BaseHooks.fixture.js contained only // TODO add all base hooks.

The verify-bundle-isolation target was also copy-pasted into each consuming project.json, and each consumer declared the tool as a devDependency purely to create an Nx graph edge so cache and affected stayed correct.

New Behavior

1. Base hooks are now guarded

BaseHooks.fixture.js imports all 103 use*Base_unstable hooks from the 39 suite dependencies that export them, enumerated from the etc/*.api.md rollups.

Named imports are deliberate — a namespace import would retain every styled component and make the check meaningless. The narrow result (11 Griffel modules, not 200+) confirms tree shaking works and the findings below are real reachability.

Forbidden: tabster, @griffel/*, @fluentui/react-icons, @fluentui/react-motion.

The base hooks are not clean. Three violations, recorded as tracked debt rather than fixed here:

Package Reached via
tabster react-tabster/lib/hooks/useTabster.js55 base-hook modules across 22 packages, mostly useArrowNavigationGroup / useFocusFinders. e.g. useToolbarBase_unstable calls useArrowNavigationGroup directly.
@griffel/* react-combobox/.../Listbox/useListboxStyles.styles.js, react-positioning/.../SafeZoneArea.styles.js
@fluentui/react-motion react-nav/.../useNavCategoryItem.js (createPresenceComponentVariant)

Griffel and motion look like bugs — a base hook should not reach a *.styles.js. tabster is a design question: base hooks own keyboard/focus behaviour and tabster is that layer, so it may not belong in forbiddenPackages for this suite at all. Worth deciding before anyone tries to pay that debt down.

The four monosize fixtures in the same folder stay unlisted — still measured for bytes, not held to a guarantee they were never meant to carry. They report as SKIPPED.

2. The target is inferred by the workspace plugin

buildVerifyBundleIsolationTarget keys off the presence of bundle-isolation.config.json, exactly as buildBundleSizeTarget keys off a bundle-size/ directory. Both project.json blocks and both devDependencies are deleted; adding a config file is now the entire setup.

A {workspaceRoot}/tools/verify-bundle-isolation/** input replaces the graph edge for both cache invalidation and affected — the convention the rit targets already use. Verified: with no graph edge to the tool, both consumers still appear in nx show projects --affected --files=tools/verify-bundle-isolation/src/report.ts.

Verification

  • react-componentsPASS WITH DEBT - 1 fixture, 4 skipped, 0 regressions, 4 allowed violations; preview → PASS
  • Target inferred for both consumers, absent on react-button
  • New plugin test covers presence/absence; mutation-testing the gate (if (false)) fails it
  • sourceResolved empty on every fixture, proving built output was bundled
  • Negative test: a @fluentui/react-icons import in the fixture produces REGRESSION + exit 1
  • monosize still green; base hooks fixture measures 217.4 kB / 68.1 kB gz

Related Issue(s)

@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown

📊 Bundle size report

Package & Exports Baseline (minified/GZIP) PR Change
react-components
react-components: all base hooks
0 B
0 B
217.385 kB
68.173 kB
🆕 New entry
Unchanged fixtures
Package & Exports Size (minified/GZIP)
global-context
createContext
510 B
326 B
global-context
createContextSelector
531 B
334 B
keyboard-key
keyboard-key package
3.927 kB
1.99 kB
keyboard-keys
Multiple keyCodes
50 B
70 B
keyboard-keys
Multiple keys
87 B
94 B
keyboard-keys
Single key
44 B
64 B
keyboard-keys
Single keyCode
39 B
59 B
priority-overflow
createOverflowManager
5.372 kB
2.174 kB
react
ActivityItem
71.511 kB
23.466 kB
react
Announced
38.766 kB
13.382 kB
react
Autofill
15.557 kB
4.803 kB
react
Breadcrumb
200.779 kB
59.775 kB
react
Button
194.363 kB
56.054 kB
react
ButtonGrid
179.244 kB
54.067 kB
react
Calendar
121.293 kB
36.952 kB
react
Callout
84.456 kB
27.693 kB
react
Check
53.471 kB
17.936 kB
react
Checkbox
60.225 kB
19.994 kB
react
ChoiceGroup
65.717 kB
21.576 kB
react
ChoiceGroupOption
59.03 kB
19.464 kB
react
Coachmark
92.829 kB
29.434 kB
react
Color
7.94 kB
3.172 kB
react
ColorPicker
135.091 kB
42.254 kB
react
ComboBox
250.592 kB
71.678 kB
react
CommandBar
201.824 kB
59.54 kB
react
ContextualMenu
154.274 kB
47.7 kB
react
DatePicker
183.22 kB
56.023 kB
react
DateTimeUtilities
5.447 kB
1.917 kB
react
DetailsList
230.008 kB
66.014 kB
react
Dialog
210.074 kB
62.5 kB
react
Divider
19.893 kB
6.936 kB
react
DocumentCard
215.813 kB
63.838 kB
react
DragDrop
8.546 kB
2.789 kB
react
DraggableZone
34.582 kB
11.592 kB
react
Dropdown
233.079 kB
68.135 kB
react
ExtendedPicker
97.086 kB
27.95 kB
react
Fabric
42.006 kB
14.453 kB
react
Facepile
209.377 kB
62.564 kB
react
FloatingPicker
240.836 kB
68.395 kB
react
FocusTrapZone
17.113 kB
5.936 kB
react
FocusZone
55.391 kB
17.548 kB
react
Grid
179.244 kB
54.067 kB
react
GroupedList
135.213 kB
40.822 kB
react
GroupedListV2
122.837 kB
37.889 kB
react
HoverCard
96.917 kB
30.798 kB
react
Icon
52.159 kB
17.378 kB
react
Icons
66.627 kB
24.479 kB
react
Image
47.183 kB
15.787 kB
react
Keytip
81.486 kB
26.762 kB
react
KeytipData
14.201 kB
4.644 kB
react
KeytipLayer
103.226 kB
32.003 kB
react
Keytips
106 kB
33.025 kB
react
Label
38.627 kB
13.349 kB
react
Layer
48.346 kB
16.468 kB
react
Link
39.947 kB
13.766 kB
react
List
39.648 kB
12.531 kB
react
MarqueeSelection
74.764 kB
22.533 kB
react
MessageBar
189.392 kB
56.484 kB
react
Modal
93.845 kB
30.319 kB
react
Nav
186.842 kB
55.869 kB
react
OverflowSet
33.636 kB
11.36 kB
react
Overlay
41.175 kB
14.19 kB
react
Panel
200.3 kB
59.482 kB
react
Persona
114.726 kB
36.572 kB
react
PersonaCoin
114.726 kB
36.572 kB
react
PersonaPresence
58.341 kB
19.48 kB
react
Pickers
297.834 kB
83.212 kB
react
Pivot
187.719 kB
56.623 kB
react
Popup
12.427 kB
4.226 kB
react
Positioning
23.112 kB
7.761 kB
react
PositioningContainer
73.679 kB
23.818 kB
react
ProgressIndicator
39.765 kB
13.638 kB
react
Rating
82.323 kB
26.225 kB
react
Fluent UI React (entire library)
1.017 MB
283.569 kB
react
ResizeGroup
13.467 kB
4.42 kB
react
ResponsiveMode
8.271 kB
3.006 kB
react
ScrollablePane
55.802 kB
17.829 kB
react
SearchBox
187.632 kB
56.064 kB
react
SelectableOption
927 B
479 B
react
SelectedItemsList
231.319 kB
67.352 kB
react
Selection
42.719 kB
12.376 kB
react
Separator
35.667 kB
12.227 kB
react
Shimmer
49.51 kB
16.36 kB
react
ShimmeredDetailsList
240.74 kB
68.726 kB
react
Slider
57.89 kB
19.313 kB
react
SpinButton
191.276 kB
57.148 kB
react
Spinner
42.053 kB
14.565 kB
react
Stack
42.343 kB
14.467 kB
react
Sticky
32.868 kB
10.589 kB
react
Styling
46.377 kB
15.242 kB
react
SwatchColorPicker
189.597 kB
57.615 kB
react
TeachingBubble
204.608 kB
60.477 kB
react
Text
37.19 kB
12.879 kB
react
TextField
81.017 kB
25.418 kB
react
Theme
43.822 kB
14.276 kB
react
ThemeGenerator
12.525 kB
4.15 kB
react
TimePicker
240.406 kB
69.476 kB
react
Toggle
46.48 kB
16.079 kB
react
Tooltip
87.247 kB
28.262 kB
react
Utilities
83.123 kB
25.271 kB
react
Viewport
24.178 kB
7.716 kB
react
WeeklyDayPicker
101.544 kB
31.769 kB
react
WindowProvider
1.262 kB
614 B
react-accordion
Accordion (including children components)
91.918 kB
29.05 kB
react-aria
ARIA - useARIAButtonProps
1.35 kB
631 B
react-aria
ARIA - AriaLiveAnnouncer
3.265 kB
1.499 kB
react-avatar
Avatar
48.382 kB
15.299 kB
react-avatar
AvatarGroup
17.259 kB
6.885 kB
react-avatar
AvatarGroupItem
61.366 kB
19.157 kB
react-badge
Badge
24.116 kB
7.78 kB
react-badge
CounterBadge
24.838 kB
8.039 kB
react-badge
PresenceBadge
24.084 kB
8.712 kB
react-breadcrumb
@fluentui/react-breadcrumb - package
103.659 kB
29.076 kB
react-button
Button
33.813 kB
8.929 kB
react-button
CompoundButton
40.693 kB
10.24 kB
react-button
MenuButton
38.759 kB
10.311 kB
react-button
SplitButton
48.177 kB
12.046 kB
react-button
ToggleButton
53.469 kB
11.065 kB
react-calendar-compat
Calendar Compat
143.32 kB
40.566 kB
react-card
Card - All
94.094 kB
27.347 kB
react-card
Card
86.69 kB
25.464 kB
react-card
CardFooter
12.653 kB
5.024 kB
react-card
CardHeader
15.2 kB
5.872 kB
react-card
CardPreview
12.73 kB
5.137 kB
react-charting
AreaChart
305.154 kB
95.909 kB
react-charting
ChartHoverCard
37.29 kB
12.738 kB
react-charting
DeclarativeChart
680.459 kB
193.864 kB
react-charting
DonutChart
204.416 kB
64.319 kB
react-charting
GanttChart
287.222 kB
90.82 kB
react-charting
GaugeChart
197.731 kB
61.769 kB
react-charting
GroupedVerticalBarChart
297.023 kB
93.155 kB
react-charting
HeatMapChart
287.919 kB
90.559 kB
react-charting
HorizontalBarChart
127.475 kB
40.118 kB
react-charting
HorizontalBarChartWithAxis
298.395 kB
93.219 kB
react-charting
Legends
152.037 kB
46.832 kB
react-charting
LineChart
334.72 kB
102.945 kB
react-charting
MultiStackedBarChart
182.57 kB
55.844 kB
react-charting
PieChart
135.059 kB
42.757 kB
react-charting
PolarChart
235.701 kB
74.718 kB
react-charting
SankeyChart
158.576 kB
49.642 kB
react-charting
ScatterChart
291.196 kB
92.181 kB
react-charting
Sparkline
88.144 kB
29.862 kB
react-charting
StackedBarChart
176.145 kB
53.411 kB
react-charting
TreeChart
85.764 kB
27.102 kB
react-charting
VerticalBarChart
308.085 kB
95.291 kB
react-charting
VerticalStackedBarChart
305.195 kB
94.973 kB
react-charts
AreaChart
406.848 kB
127.167 kB
react-charts
DeclarativeChart
758.392 kB
222.671 kB
react-charts
DonutChart
317.679 kB
97.962 kB
react-charts
FunnelChart
309.079 kB
94.761 kB
react-charts
GanttChart
389.978 kB
121.648 kB
react-charts
GaugeChart
317.029 kB
97.386 kB
react-charts
GroupedVerticalBarChart
398.061 kB
124.439 kB
react-charts
HeatMapChart
392.118 kB
122.69 kB
react-charts
HorizontalBarChart
297.355 kB
90.454 kB
react-charts
HorizontalBarChartWithAxis
63 B
83 B
react-charts
Legends
236.542 kB
71.038 kB
react-charts
LineChart
418.197 kB
130.296 kB
react-charts
PolarChart
345.534 kB
107.992 kB
react-charts
SankeyChart
213.787 kB
68.717 kB
react-charts
ScatterChart
397.521 kB
124.355 kB
react-charts
Sparkline
80.888 kB
26.864 kB
react-charts
VerticalBarChart
434.512 kB
129.325 kB
react-charts
VerticalStackedBarChart
404.076 kB
125.831 kB
react-checkbox
Checkbox
30.771 kB
10.912 kB
react-color-picker
ColorArea
31.022 kB
11.702 kB
react-color-picker
ColorPicker
16.039 kB
6.434 kB
react-color-picker
ColorSlider
26.053 kB
10.219 kB
react-combobox
Combobox (including child components)
139.308 kB
45.062 kB
react-combobox
Dropdown (including child components)
139.073 kB
44.814 kB
react-components
react-components: Button, FluentProvider & webLightTheme
67.461 kB
19.461 kB
react-components
react-components: Accordion, Button, FluentProvider, Image, Menu, Popover
227.126 kB
68.407 kB
react-components
react-components: FluentProvider & webLightTheme
40.684 kB
13.549 kB
react-components
react-components: entire library
1.283 MB
322.083 kB
react-datepicker-compat
DatePicker Compat
217.437 kB
64.403 kB
react-dialog
Dialog (including children components)
90.974 kB
28.25 kB
react-divider
Divider
16.233 kB
5.843 kB
react-field
Field
22.301 kB
8.308 kB
react-headless-components-preview
react-headless-components-preview: entire library
238.015 kB
67.01 kB
react-headless-components-preview
@fluentui/react-headless-components-preview/tag-picker
53.982 kB
17.74 kB
react-headless-components-preview
@fluentui/react-headless-components-preview/teaching-popover
36.041 kB
11.992 kB
react-image
Image
13.487 kB
5.444 kB
react-input
Input
26.23 kB
8.639 kB
react-jsx-runtime
Classic Pragma
1.282 kB
613 B
react-jsx-runtime
JSX Dev Runtime
2.137 kB
988 B
react-jsx-runtime
JSX Runtime
2.134 kB
948 B
react-label
Label
12.833 kB
5.166 kB
react-link
Link
16.397 kB
6.46 kB
react-list
List
75.535 kB
23.403 kB
react-list
ListItem
99.05 kB
30.27 kB
react-menu
Menu (including children components)
160.778 kB
51.107 kB
react-menu
Menu (including selectable components)
163.944 kB
51.736 kB
react-message-bar
MessageBar (all components)
25.283 kB
8.941 kB
react-motion
@fluentui/react-motion - createMotionComponent()
4.275 kB
1.864 kB
react-motion
@fluentui/react-motion - createPresenceComponent()
6.007 kB
2.484 kB
react-motion
@fluentui/react-motion - PresenceGroup
1.715 kB
816 B
react-overflow
hooks only
10.159 kB
3.679 kB
react-persona
Persona
55.335 kB
17.235 kB
react-popover
Popover
126.59 kB
40.869 kB
react-portal
Portal
13.844 kB
5.392 kB
react-portal-compat
PortalCompatProvider
5.341 kB
2.146 kB
react-positioning
usePositioning
28.985 kB
10.198 kB
react-positioning
useSafeZoneArea
13.398 kB
5.365 kB
react-progress
ProgressBar
20.207 kB
7.832 kB
react-provider
FluentProvider
20.076 kB
7.697 kB
react-radio
Radio
28.156 kB
9.153 kB
react-radio
RadioGroup
13.921 kB
5.609 kB
react-select
Select
26.099 kB
9.399 kB
react-slider
Slider
33.395 kB
11.506 kB
react-spinbutton
SpinButton
33.651 kB
11.009 kB
react-spinner
Spinner
23.593 kB
7.782 kB
react-swatch-picker
@fluentui/react-swatch-picker - package
93.176 kB
27.605 kB
react-switch
Switch
33.392 kB
10.562 kB
react-table
DataGrid
147.799 kB
43.973 kB
react-table
Table (Primitives only)
38.032 kB
12.685 kB
react-table
Table as DataGrid
119.67 kB
33.75 kB
react-table
Table (Selection only)
66.547 kB
18.953 kB
react-table
Table (Sort only)
65.21 kB
18.575 kB
react-tag-picker
@fluentui/react-tag-picker - package
174.753 kB
54.556 kB
react-tags
InteractionTag
13.619 kB
5.381 kB
react-tags
Tag
29.532 kB
9.334 kB
react-tags
TagGroup
70.796 kB
21.806 kB
react-teaching-popover
TeachingPopover
101.77 kB
32.204 kB
react-text
Text - Default
15.174 kB
5.877 kB
react-text
Text - Wrappers
18.333 kB
6.192 kB
react-textarea
Textarea
24.596 kB
8.908 kB
react-theme
Single theme token import
69 B
89 B
react-theme
Teams: all themes
37.967 kB
7.989 kB
react-theme
Teams: Light theme
20.797 kB
5.863 kB
react-timepicker-compat
TimePicker
142.027 kB
46.435 kB
react-toast
Toast (including Toaster)
91.478 kB
28.537 kB
react-tooltip
Tooltip
54.69 kB
19.443 kB
react-tree
FlatTree
136.683 kB
40.816 kB
react-tree
PersonaFlatTree
138.546 kB
41.356 kB
react-tree
PersonaTree
134.627 kB
40.138 kB
react-tree
Tree
132.77 kB
39.634 kB
react-utilities
SSRProvider
182 B
160 B
🤖 This report was generated against 3685a680cd5b0331decc14729c062172948b64a9

@github-actions

Copy link
Copy Markdown

Pull request demo site: URL

BaseHooks.fixture.js imports all 103 use*Base_unstable hooks from the 39 suite
dependencies that export them. Named imports, since a namespace import would
retain every styled component and defeat the check.

Baselines what base hooks currently drag in as tracked debt: tabster (55 modules
across 22 packages, via useArrowNavigationGroup and useFocusFinders), Griffel
(react-combobox Listbox styles, react-positioning SafeZoneArea) and react-motion
(react-nav useNavCategoryItem).

The four styled monosize fixtures in the same folder are left unlisted, so they
are measured for bytes without being held to an isolation guarantee they were
never meant to carry.
@Hotell
Martin Hochel (Hotell) force-pushed the chore/bundle-isolation-react-components branch from 75847d1 to 27d1495 Compare August 19, 2026 17:49
The target was copy-pasted into each consuming project.json, and each consumer
declared the tool as a devDependency purely to create an nx graph edge so cache
and affected stayed correct.

The plugin now infers the target from the presence of bundle-isolation.config.json,
the same way bundle-size is inferred from a bundle-size directory, and a
{workspaceRoot} input on the tool covers both cache invalidation and affected -
the convention already used by the rit targets. Both devDependencies go away.
@Hotell Martin Hochel (Hotell) changed the title chore(react-components): verify bundle isolation of base hooks chore: add verify-bundle-isolation to workspace plugin, cleanup deps and onboard react-components to track base hooks creep Aug 20, 2026
@Hotell
Martin Hochel (Hotell) merged commit c1f8330 into microsoft:master Aug 24, 2026
15 checks passed
@Hotell
Martin Hochel (Hotell) deleted the chore/bundle-isolation-react-components branch August 24, 2026 09:17
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.

2 participants