Upgrade to MUI v6, MUI X v7, styled-components v6, and Vite 8 - #607
Draft
somethingnew2-0 wants to merge 1 commit into
Draft
Upgrade to MUI v6, MUI X v7, styled-components v6, and Vite 8#607somethingnew2-0 wants to merge 1 commit into
somethingnew2-0 wants to merge 1 commit into
Conversation
Vite 8 replaced the dependency optimizer's CJS interop, and it no longer unwraps
a Babel-style `__esModule` default export. @mui/icons-material v5 ships CJS at
the top level with no `exports` map, so every `@mui/icons-material/X` deep import
resolved to `{default: Icon}` instead of the component and React refused to render
it. This affected dev and production builds alike, while `vite build` still
succeeded, so CI stayed green.
@mui/icons-material v6 adds an `exports` map routing the `import` condition to its
ESM build, so the interop step disappears rather than being worked around. Getting
there requires moving MUI, the styled-components engine, and MUI X together,
because each pins the others through peer ranges.
Three call-site changes fall out of the majors: `renderOption` now supplies its own
`key`, so the explicit one has to come after the spread to keep winning;
`UseDateFieldProps` and `BaseSingleInputFieldProps` each take an extra type argument
for the field DOM structure, which the picker still defaults to the value ButtonField
expects; and the stale `@rollup/rollup-*` platform pins are dropped, since Vite 8
bundles with rolldown and the lockfile already carries all 15 rolldown bindings.
Also addresses two warnings Vite 8 raises about its future native config loader:
the extensionless config import, and `__dirname` in an ESM module that only worked
because the config was bundled to CJS first.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Stacked on #606. Review that one first; this PR targets its branch, so retarget to
mainonce it merges.Supersedes #490, which cannot work on its own.
Why #490 fails today
Vite 8 replaced the dependency optimizer's CommonJS interop and no longer unwraps a Babel-style
__esModuledefault export.@mui/icons-materialv5 ships CJS at the top level with noexportsmap, so every@mui/icons-material/Xdeep import resolves to{default: Icon}rather than the component, and React refuses to render it. That is theElement type is invalid ... but got: objectflood: 109 icon imports across 40 files.Two things made it worse than it looked. It affects the production build identically, not just dev, so it is not a dev-server quirk. And
vite buildstill exits zero, so CI stays green while the app is unusable.@mui/icons-materialv6 adds anexportsmap routing theimportcondition to its ESM build, so the interop step disappears rather than being worked around. That is the actual fix, and it is why the version bump has to come with it.Why these packages move together
Each pins the others through peer ranges, so a partial bump just produces
ERESOLVE:@mui/material ^5.4.1, so MUI v6 requires X v7.@mui/styled-engine-scv6 peersstyled-components ^6.0.0.@mui/labfor the v6 line is still a prerelease, consistent with the v5 alpha it replaces.Call-site changes
Only three things needed touching, all narrow:
renderOptionnow supplies its ownkey, so the explicitkey={id}has to come after the spread to keep winning. Three search fields.UseDateFieldPropsandBaseSingleInputFieldPropseach take an extra type argument for the field DOM structure. Passingfalseselects the structure the picker still defaults to and thatButtonFieldreadsInputProps/inputPropsfrom, so this is a type-level change with no runtime effect.@rollup/rollup-*platform pins are dropped. Vite 8 bundles with rolldown,rollupis no longer in the tree, and the lockfile already carries all 15@rolldown/binding-*platforms, so the cross-platform install the pins existed to protect is covered without them.Also fixes two warnings Vite 8 raises about its future native config loader: the extensionless config import, and
__dirnameinside an ESM module, which only worked because the config is bundled to CJS first.Verification and one gap
The bundle grows about 10 kB gzipped, expected for the major. Worth noting it is not a duplicated styling engine: there is a single MUI copy and emotion is not bundled, with the styled-components engine still generating the classes. Lazy code splitting still emits its own chunk.
A browser pass covered the app shell and every previously broken icon, the forms, and the date range picker with its custom field and day-highlight slots.
Not runtime-verified: the MUI X DataGrid. Local seed data has no expiring access and no role members, and both entry points render empty states instead of a grid, so the four DataGrid call sites are typecheck-only here and want a look with real data.
Separately, the ending-date-range picker mishandles the second click of a range, keeping the previous start date. That reproduces identically on
main, so it is pre-existing and left alone rather than folded in here.🤖 Generated with Claude Code