fix: normalize v9 peer dependencies - #36559
Conversation
📊 Bundle size reportUnchanged fixtures
|
| @@ -0,0 +1,7 @@ | |||
| { | |||
There was a problem hiding this comment.
🕵🏾♀️ visual changes to review in the Visual Change Report
vr-tests-react-components/Menu Converged - submenuIndicator slotted content 2 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/Menu Converged - submenuIndicator slotted content.default - RTL.submenus open.chromium.png | 404 | Changed |
| vr-tests-react-components/Menu Converged - submenuIndicator slotted content.default.submenus open.chromium.png | 413 | Changed |
vr-tests-react-components/Positioning 2 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/Positioning.Positioning end.chromium.png | 745 | Changed |
| vr-tests-react-components/Positioning.Positioning end.updated 2 times.chromium.png | 512 | Changed |
vr-tests-react-components/ProgressBar converged 2 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/ProgressBar converged.Indeterminate + thickness - High Contrast.default.chromium.png | 181 | Changed |
| vr-tests-react-components/ProgressBar converged.Indeterminate + thickness.default.chromium.png | 40 | Changed |
vr-tests-react-components/TagPicker 3 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/TagPicker.disabled - Dark Mode.disabled input hover.chromium.png | 658 | Changed |
| vr-tests-react-components/TagPicker.disabled - RTL.chromium.png | 635 | Changed |
| vr-tests-react-components/TagPicker.disabled.disabled input hover.chromium.png | 677 | Changed |
vr-tests-web-components/Accordion 1 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-web-components/Accordion. - Dark Mode.normal.chromium_1.png | 3398 | Changed |
vr-tests-web-components/Badge 1 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-web-components/Badge. - Dark Mode.normal.chromium.png | 443 | Changed |
vr-tests-web-components/MenuList 1 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-web-components/MenuList. - RTL.2nd selected.chromium.png | 17 | Changed |
vr-tests/Callout 3 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests/Callout.Bottom right edge - RTL.default.chromium.png | 1124 | Changed |
| vr-tests/Callout.Left bottom edge.default.chromium.png | 3182 | Changed |
| vr-tests/Callout.Top left edge.default.chromium.png | 2212 | Changed |
vr-tests/Facepile 2 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests/Facepile.Add face.default.chromium.png | 579 | Changed |
| vr-tests/Facepile.Custom button styles.default.chromium.png | 541 | Changed |
vr-tests/FocusTrapZones 2 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests/FocusTrapZones.Dialog nested in Panel - RTL.click on panel close button.chromium.png | 12773 | Changed |
| vr-tests/FocusTrapZones.Dialog nested in Panel.default.chromium.png | 12877 | Changed |
vr-tests/Keytip 2 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests/Keytip.Disabled.default.chromium.png | 26 | Changed |
| vr-tests/Keytip.Root.default.chromium.png | 55 | Changed |
vr-tests/react-charting-AreaChart 1 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests/react-charting-AreaChart.Custom Accessibility.default.chromium.png | 11 | Changed |
vr-tests/react-charting-LineChart 3 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests/react-charting-LineChart.Multiple - RTL.default.chromium.png | 200 | Changed |
| vr-tests/react-charting-LineChart.Multiple - Dark Mode.default.chromium.png | 181 | Changed |
| vr-tests/react-charting-LineChart.Events.default.chromium.png | 17 | Changed |
vr-tests/react-charting-MultiStackBarChart 3 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests/react-charting-MultiStackBarChart.Basic_Absolute - Dark Mode.default.chromium.png | 363 | Changed |
| vr-tests/react-charting-MultiStackBarChart.Basic_Absolute - RTL.default.chromium.png | 343 | Changed |
| vr-tests/react-charting-MultiStackBarChart.Basic_PartToWhole.default.chromium.png | 359 | Changed |
vr-tests/react-charting-VerticalBarChart 2 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests/react-charting-VerticalBarChart.Basic - Secondary Y Axis.default.chromium.png | 3 | Changed |
| vr-tests/react-charting-VerticalBarChart.Grouped - Wrap Labels.default.chromium.png | 3105 | Changed |
There were 6 duplicate changes discarded. Check the build logs for more information.
095103a to
ff2f405
Compare
|
Pull request demo site: URL |
879408f to
80df2f2
Compare
7078329 to
fe1e1de
Compare
6fb3147 to
b7bf4e5
Compare
There was a problem hiding this comment.
Pull request overview
Removes unnecessary v9 peers and adds automated peer-contract validation.
Changes:
- Prunes
react-dom/@types/react-dompeers and makes@types/reactoptional. - Adds and tests the peer-dependency verifier.
- Updates dependency ranges, CI enforcement, lockfile, templates, and change files.
Reviewed changes
Copilot reviewed 168 out of 169 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/pr.yml |
Runs peer verification in PR CI. |
yarn.lock |
Synchronizes peer metadata and resolved dependencies. |
tools/workspace-plugin/generators.json |
Registers the verifier generator. |
tools/workspace-plugin/src/types.ts |
Types optional peer metadata. |
tools/workspace-plugin/src/generators/verify-peer-dependencies/README.md |
Documents verifier behavior and usage. |
tools/workspace-plugin/src/generators/verify-peer-dependencies/index.ts |
Implements peer-contract validation and fixes. |
tools/workspace-plugin/src/generators/verify-peer-dependencies/index.spec.ts |
Tests verifier behavior. |
tools/workspace-plugin/src/generators/verify-peer-dependencies/schema.json |
Defines the generator CLI schema. |
tools/workspace-plugin/src/generators/verify-peer-dependencies/schema.ts |
Defines generator option types. |
tools/workspace-plugin/src/generators/react-library/files/package.json__tmpl__ |
Updates generated peer defaults. |
packages/react-components/component-selector-preview/library/package.json |
Prunes unused DOM peers. |
packages/react-components/deprecated/react-alert/package.json |
Updates React peer metadata. |
packages/react-components/deprecated/react-infobutton/package.json |
Updates React peer metadata. |
packages/react-components/deprecated/react-virtualizer/package.json |
Retains runtime DOM peer and updates type metadata. |
packages/react-components/eslint-plugin-react-components/package.json |
Narrows tooling peer ranges. |
packages/react-components/global-context/package.json |
Makes React types optional. |
packages/react-components/react-accordion/library/package.json |
Updates React peer metadata. |
packages/react-components/react-aria/library/package.json |
Updates React peer metadata. |
packages/react-components/react-avatar/library/package.json |
Updates React peer metadata. |
packages/react-components/react-badge/library/package.json |
Updates React peer metadata. |
packages/react-components/react-breadcrumb/library/package.json |
Updates React peer metadata. |
packages/react-components/react-button/library/package.json |
Updates React peer metadata. |
packages/react-components/react-calendar-compat/library/package.json |
Updates React peer metadata. |
packages/react-components/react-card/library/package.json |
Updates React peer metadata. |
packages/react-components/react-carousel/library/package.json |
Updates React peer metadata. |
packages/react-components/react-checkbox/library/package.json |
Updates React peer metadata. |
packages/react-components/react-color-picker/library/package.json |
Updates React peer metadata. |
packages/react-components/react-colorpicker-compat/package.json |
Prunes unused DOM peers. |
packages/react-components/react-combobox/library/package.json |
Retains runtime DOM peer and updates type metadata. |
packages/react-components/react-components/package.json |
Prunes aggregate-package DOM peers. |
packages/react-components/react-conformance-griffel/package.json |
Adds its runtime react-dom peer. |
packages/react-components/react-context-selector/package.json |
Updates React peer metadata. |
packages/react-components/react-datepicker-compat/library/package.json |
Updates React peer metadata. |
packages/react-components/react-dialog/library/package.json |
Updates React peer metadata. |
packages/react-components/react-divider/library/package.json |
Updates React peer metadata. |
packages/react-components/react-drawer/library/package.json |
Updates React peer metadata. |
packages/react-components/react-field/library/package.json |
Updates React peer metadata. |
packages/react-components/react-headless-components-preview/library/package.json |
Updates React peer metadata. |
packages/react-components/react-icons-compat/library/package.json |
Updates React peer metadata. |
packages/react-components/react-image/library/package.json |
Updates React peer metadata. |
packages/react-components/react-infolabel/library/package.json |
Updates React peer metadata. |
packages/react-components/react-input/library/package.json |
Updates React peer metadata. |
packages/react-components/react-jsx-runtime/package.json |
Makes React types optional. |
packages/react-components/react-label/library/package.json |
Updates React peer metadata. |
packages/react-components/react-link/library/package.json |
Updates React peer metadata. |
packages/react-components/react-list/library/package.json |
Updates React peer metadata. |
packages/react-components/react-menu-grid-preview/library/package.json |
Updates React peer metadata. |
packages/react-components/react-menu/library/package.json |
Updates React peer metadata. |
packages/react-components/react-message-bar/library/package.json |
Updates React peer metadata. |
packages/react-components/react-migration-v0-v9/library/package.json |
Updates React peer metadata. |
packages/react-components/react-migration-v8-v9/library/package.json |
Updates React peer metadata. |
packages/react-components/react-motion-components-preview/library/package.json |
Updates React peer metadata. |
packages/react-components/react-motion/library/package.json |
Updates React peer metadata. |
packages/react-components/react-nav/library/package.json |
Updates React peer metadata. |
packages/react-components/react-overflow/library/package.json |
Updates React peer metadata. |
packages/react-components/react-persona/library/package.json |
Updates React peer metadata. |
packages/react-components/react-popover/library/package.json |
Updates React peer metadata. |
packages/react-components/react-portal-compat-context/package.json |
Makes React types optional. |
packages/react-components/react-portal-compat/package.json |
Makes React types optional. |
packages/react-components/react-portal/library/package.json |
Retains runtime DOM peer and updates type metadata. |
packages/react-components/react-positioning/library/package.json |
Updates peers and React 19 shim support. |
packages/react-components/react-progress/library/package.json |
Updates React peer metadata. |
packages/react-components/react-provider/library/package.json |
Updates React peer metadata. |
packages/react-components/react-radio/library/package.json |
Updates React peer metadata. |
packages/react-components/react-rating/library/package.json |
Updates React peer metadata. |
packages/react-components/react-search/library/package.json |
Updates React peer metadata. |
packages/react-components/react-select/library/package.json |
Updates React peer metadata. |
packages/react-components/react-shared-contexts/library/package.json |
Makes React types optional. |
packages/react-components/react-skeleton/library/package.json |
Updates React peer metadata. |
packages/react-components/react-slider/library/package.json |
Updates React peer metadata. |
packages/react-components/react-spinbutton/library/package.json |
Updates React peer metadata. |
packages/react-components/react-spinner/library/package.json |
Updates React peer metadata. |
packages/react-components/react-storybook-addon/package.json |
Updates React peer metadata. |
packages/react-components/react-swatch-picker/library/package.json |
Updates React peer metadata. |
packages/react-components/react-switch/library/package.json |
Updates React peer metadata. |
packages/react-components/react-table/library/package.json |
Updates React peer metadata. |
packages/react-components/react-tabs/library/package.json |
Updates React peer metadata. |
packages/react-components/react-tabster/package.json |
Updates React peer metadata. |
packages/react-components/react-tag-picker/library/package.json |
Retains runtime DOM peer and updates type metadata. |
packages/react-components/react-tags/library/package.json |
Updates React peer metadata. |
packages/react-components/react-teaching-popover/library/package.json |
Updates peers and React 19 shim support. |
packages/react-components/react-text/library/package.json |
Updates React peer metadata. |
packages/react-components/react-textarea/library/package.json |
Updates React peer metadata. |
packages/react-components/react-timepicker-compat/library/package.json |
Updates React peer metadata. |
packages/react-components/react-toast/library/package.json |
Updates React peer metadata. |
packages/react-components/react-toolbar/library/package.json |
Updates React peer metadata. |
packages/react-components/react-tooltip/library/package.json |
Updates React peer metadata. |
packages/react-components/react-tree/library/package.json |
Retains runtime DOM peer and updates type metadata. |
packages/react-components/react-utilities-compat/library/package.json |
Prunes unused DOM peers. |
packages/react-components/react-utilities/package.json |
Makes React types optional. |
packages/react-components/recipes/package.json |
Prunes unused DOM peers. |
packages/react-components/theme-designer/package.json |
Removes unused React DOM types. |
change/@fluentui-eslint-plugin-react-components-bc46323e-82ab-4878-998b-5dd19fa5f0d9.json |
Records tooling peer-range changes. |
change/@fluentui-global-context-7a997068-d2cd-40e5-bc0e-fe1c1c49dac8.json |
Records global-context metadata changes. |
change/@fluentui-react-accordion-3ff07725-b0de-40fd-a3c0-03f8888556a5.json |
Records package metadata changes. |
change/@fluentui-react-alert-c334ef5b-3340-456e-9b20-01518f659b0d.json |
Records package metadata changes. |
change/@fluentui-react-aria-46908b84-678b-4100-bbda-a2746a4e245b.json |
Records package metadata changes. |
change/@fluentui-react-avatar-d51a264b-1cbd-4f2d-8003-4a4a5bb8b3df.json |
Records package metadata changes. |
change/@fluentui-react-badge-ca23953a-a40c-44ff-887c-0c9cff112211.json |
Records package metadata changes. |
change/@fluentui-react-breadcrumb-e405c510-0fc5-48b6-b885-8dc9d8180580.json |
Records package metadata changes. |
change/@fluentui-react-button-ce466318-9c22-47eb-bf13-4f3a2f31fadb.json |
Records package metadata changes. |
change/@fluentui-react-calendar-compat-ccbf7c15-84c9-4b0f-8efc-6e7fa748c1e8.json |
Records package metadata changes. |
change/@fluentui-react-card-88431a56-c924-462a-bbec-aefa053dced8.json |
Records package metadata changes. |
change/@fluentui-react-carousel-4cf526f8-7a78-4be2-ab93-64b9286345d5.json |
Records package metadata changes. |
change/@fluentui-react-checkbox-b7a78cf5-b865-4683-b144-7cc13d1ab386.json |
Records package metadata changes. |
change/@fluentui-react-color-picker-366022a2-cc45-49f5-b386-90a0ca7985a6.json |
Records package metadata changes. |
change/@fluentui-react-combobox-69be7590-10a9-47d5-8390-a8a9b65a28dc.json |
Records package metadata changes. |
change/@fluentui-react-components-c784fdce-0d58-458e-b1dc-5fe22cb0b73a.json |
Records aggregate-package metadata changes. |
change/@fluentui-react-conformance-griffel-38db03f4-bf4d-4f96-aff7-15a08a9c54ff.json |
Records corrected runtime peer. |
change/@fluentui-react-context-selector-078ddf89-1482-4df3-9d02-c5a7298f91fd.json |
Records package metadata changes. |
change/@fluentui-react-datepicker-compat-e36857fc-25fa-443a-9aec-4c41609b46af.json |
Records package metadata changes. |
change/@fluentui-react-dialog-1dd8d5d1-b227-41e2-a6b5-8737120b6b33.json |
Records package metadata changes. |
change/@fluentui-react-divider-4fc13923-6ea1-4d06-b7aa-66b049b36170.json |
Records package metadata changes. |
change/@fluentui-react-drawer-314fddc3-532d-4707-a65a-6532c7721d59.json |
Records package metadata changes. |
change/@fluentui-react-field-2523d3e4-82e7-42e6-ae9c-b68efbb42626.json |
Records package metadata changes. |
change/@fluentui-react-headless-components-preview-e5d562de-3d30-4e15-922f-e81cae9a596b.json |
Records package metadata changes. |
change/@fluentui-react-icons-compat-daf9887e-90ce-4592-bc2a-6aae3697d3d1.json |
Records package metadata changes. |
change/@fluentui-react-image-630316f7-ca60-4df7-8180-6f4937686471.json |
Records package metadata changes. |
change/@fluentui-react-infobutton-eb9ddf83-dc46-427d-af2e-e127c4467d7d.json |
Records package metadata changes. |
change/@fluentui-react-infolabel-ce184655-6e81-476a-a9f9-be2bcf9c6035.json |
Records package metadata changes. |
change/@fluentui-react-input-58a45833-5a26-4dee-a996-a87263ce8b3d.json |
Records package metadata changes. |
change/@fluentui-react-jsx-runtime-52085c6f-b83c-4653-a8f6-20ac8c91db18.json |
Records optional type peer. |
change/@fluentui-react-label-1b43f503-c66e-468d-adbd-76f3a3c245a4.json |
Records package metadata changes. |
change/@fluentui-react-link-ee550c4d-6833-4673-9f64-9b617fbea249.json |
Records package metadata changes. |
change/@fluentui-react-list-e8b5f1e8-b6ef-4f94-888c-969d88cf26e1.json |
Records package metadata changes. |
change/@fluentui-react-menu-a71d8733-d2b2-45c4-8d52-c31430d8f337.json |
Records package metadata changes. |
change/@fluentui-react-menu-grid-preview-834999cd-0767-47b9-9e71-e73617fe3719.json |
Records package metadata changes. |
change/@fluentui-react-message-bar-fb5cfe30-3120-4734-a72d-0abc58f12ef7.json |
Records package metadata changes. |
change/@fluentui-react-migration-v0-v9-89851263-3e34-4a40-8c47-f45cc4c36057.json |
Records package metadata changes. |
change/@fluentui-react-migration-v8-v9-c6ef9430-cae4-4c7f-9e2a-946d50c4a88b.json |
Records package metadata changes. |
change/@fluentui-react-motion-aa4a3ccb-9b7e-4715-8017-31482f566cc1.json |
Records package metadata changes. |
change/@fluentui-react-motion-components-preview-d9979335-86c4-4403-9bd7-23af3384ce63.json |
Records package metadata changes. |
change/@fluentui-react-nav-71a8cfb1-fa18-46c8-964e-7e7281f11af3.json |
Records package metadata changes. |
change/@fluentui-react-overflow-2382dd3a-946b-4392-a56f-4569fe7726d9.json |
Records package metadata changes. |
change/@fluentui-react-persona-472e5b4d-d4f8-4fe4-8c38-80ac99fdff3f.json |
Records package metadata changes. |
change/@fluentui-react-popover-122a1340-9508-44e8-8d25-a715770abd23.json |
Records package metadata changes. |
change/@fluentui-react-portal-588ea710-2e69-4705-8651-2d4b5dda1caa.json |
Records package metadata changes. |
change/@fluentui-react-portal-compat-bce75f2c-7faa-4471-998d-9f85934372a5.json |
Records optional type peer. |
change/@fluentui-react-portal-compat-context-a62389b7-9981-41b2-afa8-e5dcde741353.json |
Records optional type peer. |
change/@fluentui-react-positioning-b9b4dd75-457b-4aea-966d-bbcf6a5245f6.json |
Records peer and shim updates. |
change/@fluentui-react-progress-a1a624fe-a4f6-47a5-86ad-1107e48f5ce5.json |
Records package metadata changes. |
change/@fluentui-react-provider-f3b506e3-3f11-4631-8e0d-88ab6b0c77f9.json |
Records package metadata changes. |
change/@fluentui-react-radio-114fbcf1-b0e1-412c-9b04-57e6b85247d6.json |
Records package metadata changes. |
change/@fluentui-react-rating-da5b2fde-4ff2-4385-8dba-89e74da8a996.json |
Records package metadata changes. |
change/@fluentui-react-search-4fbf0876-311c-4bc8-8e7e-d7adc93e8bf0.json |
Records package metadata changes. |
change/@fluentui-react-select-b7c3dbad-b6ad-4eba-9a96-b8c791725828.json |
Records package metadata changes. |
change/@fluentui-react-shared-contexts-95aa313c-6bb2-4f9e-9ba3-a2df3faaba3e.json |
Records optional type peer. |
change/@fluentui-react-skeleton-10f28d03-dee9-487c-8dbf-d627461b197c.json |
Records package metadata changes. |
change/@fluentui-react-slider-586ccb38-8fec-468e-a814-a303e7686bb2.json |
Records package metadata changes. |
change/@fluentui-react-spinbutton-6b3ce138-040a-47f7-813c-b71a31f6fe3f.json |
Records package metadata changes. |
change/@fluentui-react-spinner-7729a37d-5349-42ca-be6c-af1f8b013490.json |
Records package metadata changes. |
change/@fluentui-react-storybook-addon-5a140b97-f264-4192-ac32-d88f616d79e1.json |
Records package metadata changes. |
change/@fluentui-react-swatch-picker-b955caa8-53ae-466d-93da-52246e107fa5.json |
Records package metadata changes. |
change/@fluentui-react-switch-5ae26c41-a156-428a-b245-162495f9f31f.json |
Records package metadata changes. |
change/@fluentui-react-table-46094913-ec55-4985-8a4f-1136d7b29f77.json |
Records package metadata changes. |
change/@fluentui-react-tabs-0aa07b00-91d5-4f6d-9d78-3b233b30dd5f.json |
Records package metadata changes. |
change/@fluentui-react-tabster-684d953d-5fd6-47df-bcf7-6beffc58604a.json |
Records package metadata changes. |
change/@fluentui-react-tag-picker-c7f186a6-ef65-487f-8110-d8dc73aaeb5e.json |
Records package metadata changes. |
change/@fluentui-react-tags-09d81c82-e6dc-40d7-86a0-cd246bb2808a.json |
Records package metadata changes. |
change/@fluentui-react-teaching-popover-0d4ced75-add8-49dc-a00d-d630a03bebb6.json |
Records peer and shim updates. |
change/@fluentui-react-text-5230b567-1687-438b-9098-72265f16df66.json |
Records package metadata changes. |
change/@fluentui-react-textarea-1ce1688e-982d-44d3-a824-32d74ddf59c2.json |
Records package metadata changes. |
change/@fluentui-react-timepicker-compat-dec37e01-a46e-4670-9581-069a85c300d5.json |
Records package metadata changes. |
change/@fluentui-react-toast-3935b55c-5193-42fd-83aa-00573ec5e77e.json |
Records package metadata changes. |
change/@fluentui-react-toolbar-14684d1b-d5e7-4cd6-bbe0-8a603d78d947.json |
Records package metadata changes. |
change/@fluentui-react-tooltip-50be0942-91c8-4df6-b83c-134dcd067bd7.json |
Records package metadata changes. |
change/@fluentui-react-tree-9bdd7730-b0e4-4a28-9827-142279a42978.json |
Records package metadata changes. |
change/@fluentui-react-utilities-d4dd17bf-1221-4061-a710-804f121d4e05.json |
Records optional type peer. |
change/@fluentui-react-virtualizer-c60d58e2-39b7-4ccd-bc2c-ce543bc738fc.json |
Records package metadata changes. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Verifies that the peer dependency promises we publish are internally consistent
and satisfiable. All checks are derived from the package.json graph, so results
are deterministic.
- incompatible-peer-range a declared range accepts versions the dependency does
not support
- invalid-peer-range peer range is not a valid semver range
- orphaned-peer-meta peerDependenciesMeta entry with no peerDependencies
- missing-peer-forward a dependency requires a non-optional peer this package
neither declares nor owns (opt-in, see below)
`missing-peer-forward` is off by default because whether it matters depends
entirely on the installer. Hoisted layouts (npm, yarn classic) resolve a peer by
walking up the directory tree to the nearest ancestor that provides it. Isolated
layouts (pnpm, midgard-yarn-strict / npm RFC 0042) additionally propagate peer
metadata up the graph themselves, stopping at a real dependency or a local
workspace. In both, re-declaring a dependency's peer is a no-op. Only Yarn PnP
strict has no ancestor walk and requires every package in the chain to declare
it. Since a package's peer set is part of its virtual instance key, declaring
peers it never imports actively forks the virtual store and asks consumers to
satisfy a module that is never loaded.
Only publishable packages are verified: a private package is never installed by
a consumer, so it carries no peer contract. It is still read, because publishable
packages depend on it. Scoping is available by `project`, nx `tag` and `checks`;
an unknown value throws rather than silently verifying nothing.
Range containment is decided by probing the boundary versions of both ranges
rather than by `semver.subset`, which tests containment against each comparator
set of the dominant range in isolation and so rejects a range spanning several
carets even when their union covers it:
subset('>=16.14.0 <20.0.0', '>=16.8.0 <20.0.0') -> true
subset('>=16.14.0 <20.0.0', '^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0') -> false
Both describe the same set, and the second form is how the react ecosystem
usually expresses support.
`--fix` runs to a fixpoint because forwarding cascades, and never throws:
throwing from a generator makes nx discard the whole tree, which would silently
drop the fixes just applied.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
76 packages under packages/react-components declared `react-dom` and/or
`@types/react-dom` as peers. Only 7 reference `react-dom` in shipped code,
verified against source and built `lib/` output. The rest inherited the
declaration from the scaffolding template.
A package's peer set is part of its virtual instance key, so declaring a peer it
never imports forks the virtual store on a dimension the package does not care
about, and asks consumers who never render to the DOM to satisfy a module that is
never loaded. Removing them is safe in every install model: hoisted layouts
resolve `react-dom` from the consuming app, which always has it, and isolated
layouts propagate the peer from the packages that genuinely declare it.
`@types/react-dom` is dropped everywhere except `react-migration-v8-v9`, which
depends on `@fluentui/react` (v8) and inherits that peer from the v8 contract. It
appears in 0 of 337 checked-in api.md reports and 0 of 698 emitted .d.ts files,
so it was never part of the published type surface.
`@fluentui/react-conformance-griffel` had the inverse problem: it declared
`@types/react-dom` but not `react-dom`, while doing `await import('react-dom')`
and `await import('react-dom/client')` at runtime. Those are now swapped.
The react-library generator template is updated to match, so newly scaffolded
packages no longer start with peers they do not use.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
react-positioning and react-teaching-popover declared `use-sync-external-store` as `^1.2.0` while promising react `>=16.14.0 <20.0.0`. React 19 support was only added to that package in 1.4.0, so the declared floor did not match the react support contract - the caret happened to allow a working version, but nothing guaranteed it and the lockfile was pinned to 1.2.2, i.e. the combination we shipped was the broken one. The floor is now `^1.4.0`, the first release whose peer range includes `^19.0.0`. Lower-end support is unaffected: 1.4.0 still accepts react 16.8+. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
`@types/react` and `@types/react-dom` are erased at build time, so a consumer only needs them to type-check - a plain JS app never does. Declaring them as required peers made npm 7+ auto-install react types into projects that have no use for them, and made resolvers warn about a package that is never loaded at runtime. They are marked optional on all 76 publishable packages/react-components packages. The react-library generator template matches, so newly scaffolded packages do not reintroduce the required declaration. This is safe only because they are types-only. `optional` silences the install warning without making the module resolvable, so for a peer that is actually imported it would convert a loud install-time warning into a silent runtime crash. `react` and `react-dom` therefore stay required. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…-components
The package declared `eslint: >= 8.0.0` and `typescript: >= 5.0.0`, both wider
than `@typescript-eslint/utils` supports, so it promised support its own
dependency cannot honour. On eslint 8.0.0 the failure is immediate:
TypeError: Class extends value undefined is not a constructor or null
at @typescript-eslint/utils/dist/ts-eslint/eslint/FlatESLint.js:12
class FlatESLint extends use_at_your_own_risk_1.FlatESLint
`FlatESLint` was added to eslint's `use-at-your-own-risk` entry point in 8.57.0,
which is exactly why typescript-eslint pins that floor.
The eslint range is set to `^8.57.0 || ^9.0.0` rather than also allowing
`^10.0.0`. eslint 10 support is only present from `@typescript-eslint/utils`
8.56.0, while this package declares `^8.46.2` - a consumer lockfile may legally
resolve 8.46.2 and would then receive an unsatisfiable contract. Advertising
eslint 10 requires raising that dependency floor first.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Runs the installer-independent checks - incompatible ranges, invalid ranges and orphaned peer metadata - so a package cannot promise support its dependencies cannot honour. `missing-peer-forward` stays off by default, since it only applies under Yarn PnP strict. Scoped to `--tag=vNext`, which is green as of the preceding commits. v8 and the docsite still carry incompatible ranges and stay out of scope, so the gate holds from the start instead of being introduced red. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Generated from the final state of the branch rather than incrementally, so each file describes what actually ships for that package. The earlier files had gone stale: they still described the scheduler forwarding and the react-dom forwarding that were reverted after the 1JS feedback, and one covered a package that is no longer modified at all. 77 packages, matching `yarn check:change` exactly. `none` is used for the four packages whose beachball config disallows patch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
b7bf4e5 to
48c8b4f
Compare
|
Thanks — all five were valid and are now addressed. Each was verified empirically rather than taken at face value. 1. 2. Boundary probe missed ranges unbounded below. Confirmed — 3. Optional peers suppressed range validation. Correct — 4. ESLint 10 over-advertised. Confirmed, and the sharpest catch. Verified the concrete failure on eslint 8.0.0:
This also exposed a real limitation: the checker reads the installed manifest (8.57.1), not the declared floor (8.46.2) — which is why it missed this. Added an opt-in 5. Strict-PnP inconsistency. Fair — the body claimed universal safety while the README documented PnP strict needing forwarding. Made the position explicit rather than implicit: Fluent UI targets hoisted and isolated installs, PnP strict is deliberately not targeted, and Also corrected the reporter wording, which said 297 tests pass, |
|
Is the missing version check on dependencies[peer] vs requiredRange intentional (npm/yarn's job at install time) or worth adding here too? |
|
Was keeping react-dom on theme-designer deliberate since it's private, or should it follow the same rule as react-positioning? |

Removes v9 peer dependencies we never use, and adds a generator that stops us re-introducing inconsistent ones.
Why
Peers we don't import aren't free. A package's peer set is part of its virtual instance key, so declaring
react-domin a package that never touches the DOM forks the virtual store on a dimension the package doesn't care about, and asks consumers to satisfy a module that is never loaded.What changed
react-dompeer (v9)@types/react-dompeer (v9)@types/reactrequired peerreact-dom/@types/react-dom— only 7 packages referencereact-domin shipped code, verified against source and builtlib/. The rest inherited the declaration from the scaffolding template.@types/react-domis dropped everywhere; it appears in 0 of 337 api.md reports and 0 of 698 emitted.d.ts, so it was never part of the published type surface.Removal is safe in the install models Fluent UI targets: hoisted layouts resolve
react-domfrom the consuming app, which always has it, and isolated layouts propagate the peer from the packages that genuinely declare it. Yarn PnP strict is explicitly not targeted — it has no ancestor walk, so it would require every package in the chain to re-declare peers it never imports. That is the trade-off this PR makes deliberately, andmissing-peer-forwardremains available (--checks=all) for anyone who needs to audit it.@types/react— erased at build time, so only TypeScript consumers need it. Markedoptional, which stops npm 7+ auto-installing React types into JS-only projects. Safe only because it's types-only:optionalsilences the install warning without making a module resolvable, soreactandreact-domstay required.use-sync-external-store— declared^1.2.0while promising react<20.0.0, but React 19 support landed in 1.4.0 and the lockfile was pinned to 1.2.2, so the combination we shipped was the broken one. Floor is now^1.4.0.eslint-plugin-react-components— declaredeslint >= 8.0.0andtypescript >= 5.0.0, both wider than@typescript-eslint/utilssupports, promising eslint 8.0–8.56 and typescript 6 support its own dependency can't honour.Enforcement
New
verify-peer-dependenciesgenerator, run on PRs as--tag=vNext:Default checks are installer-independent:
incompatible-peer-range,invalid-peer-range,orphaned-peer-meta. All derived from the package.json graph, so results are deterministic. Only publishable packages are verified.A fourth check,
missing-peer-forward, is opt-in (--checks=all) because whether it matters depends on the installer:requirewalks up the tree; nearest ancestor providing the peer winsOnly the last requires re-declaring a dependency's peers, so enforcing it by default would push us toward declaring peers we don't use — the opposite of this PR.
Notes for review
react-positioningandreact-storybook-addon-export-to-sandboxmatchreact-domonly in a comment URL and in sandbox template strings, so they correctly get no peer.react-conformance-griffelhad the inverse bug — it declared@types/react-dombut notreact-dom, while doingawait import('react-dom')at runtime. Swapped.semver.subset, which rejects>=16.14.0 <20.0.0⊆^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0even though the caret union is exactly>=16.8.0 <20.0.0.yarn install --immutableexits 0, 285 workspace-plugin tests pass,--tag=vNextreports no violations.Related Issue(s)