Material UI v5 迁移实战指南:为什么你应该立刻从 v4 升级
说明:本文对应仓库中发布于 2022 年 6 月的官方博客 mui-core-v5-migration-update.md。文中关于迁移命令、破坏性变更与代码示例的描述,均结合当前仓库中完整的 v4 → v5 迁移文档 与源码进行了核实与扩充。
导读
本文面向仍然停留在 Material UI v4、犹豫是否升级到 v5 的开发者。你将了解 v5 五大核心升级点的技术原理(React 18 支持、Emotion 样式引擎、sx prop、TypeScript IntelliSense、CSS variables 远景),并掌握仓库官方文档沉淀下来的一整套低摩擦升级路径:从版本要求、包重命名、peer 依赖安装,到用 @mui/codemod 自动改写破坏性变更。读完本文,你可以结合仓库中完整的 迁移指南 为自己的项目制定一份可落地的 v5 升级计划。
背景:v5 已发布,仍有大量用户停留在 v4
Material UI 于 2021 年底正式发布了 v5(详见仓库中的 v5 发布公告)。彼时官方观察到,尽管 v5 包含大量改进,仍有一部分用户迟迟没有迁移。官方判断,犹豫的主要原因在于:v5 相对 v4 包含大量破坏性变更(breaking changes),迁移工作量看起来很大。
为了降低这种顾虑,官方对 v4 → v5 迁移文档 进行了整体重构,把它组织成一套循序渐进的多步骤系列,减少升级过程中的摩擦。
需要说明的是,当前仓库主线的 Material UI 版本已经演进到 v9(例如 packages/mui-material/package.json 中版本号为 9.4.0),v4 → v5 迁移属于历史升级路径。但 v5 引入的许多设计(sx prop、Emotion 化、CSS 变量支持等)至今仍是现代 Material UI 的基石,理解这次迁移对读懂后续 v6/v7/v9 演进仍然非常有价值。仓库中该系列迁移文档也完整保留在 docs/data/material/migration/migration-v4/ 目录下。
官方重构后的迁移文档体系
在动手升级前,先了解官方迁移文档的完整骨架。这套多部分系列共五篇(均保留在仓库中),推荐按顺序阅读、逐步执行:
- 开始迁移:版本要求、安装新包、替换 import、运行 codemod;
- 破坏性变更(一):样式与主题;
- 破坏性变更(二):组件;
- 从 JSS 迁移到 Emotion(可选但推荐);
- 疑难排查 Troubleshooting。
官方给出的执行建议非常明确:每完成一步就运行一次应用、确认无报错并提交一次小的 commit,再进入下一步,从而保证整个迁移过程始终处于可控状态。遇到文档未覆盖的问题,可按 [Migration] 问题摘要 的标题格式反馈。
为什么应该尽快升级到 v5:五大核心理由
1. 对 React 18 的完整支持
v5 是当时唯一完整支持 React 18 的 Material UI 版本。React 18 引入的并发渲染(Concurrent Rendering)等能力,只有在完整适配的组件库上才能可靠使用。如果你希望使用新版本 React 特性,就必须升级。
从仓库中 v4 → v5 迁移文档 可以看到具体的版本门槛提升:
- 最低支持的 React 版本从 v16.8.0 提升到 v17.0.0(React 18 是 v5 时代的主流目标);
- 最低支持的 TypeScript 版本从 v3.2 提升到 v3.5;
- 如果项目使用
react-scripts、@types/react、@types/react-dom,也需要同步更新。
作为旁证,当前仓库中 packages/mui-material/package.json 的 peerDependencies 声明了 "react": "^17.0.0 || ^18.0.0 || ^19.0.0",说明这条以 React 17 起步、面向新版本 React 的支持路线被一直延续了下来。
2. 全新样式引擎:用 Emotion 取代 JSS
v5 最大的架构级变更,是用 Emotion 取代 JSS 成为默认样式引擎。这一变更的动机与演进细节最早记录在官方 RFC(issue #22342)中。它带来两个直接收益:
- 动态样式(dynamic styles)的性能显著提升:Emotion 在运行时针对动态样式做了大量优化;
- 更好的开发体验(DX):为多年来社区反复要求的定制能力铺路,例如自定义样式工具属性(style utility props)、颜色变体(color variants)与自定义主题变体(theme variants)。
仓库中 从 JSS 迁移的独立文档 明确指出:你不需要在升级当天就把全部 JSS 代码改写掉。新样式引擎是 100% 可渐进式采用的——在迁移组件期间,JSS(通过 @mui/styles 提供 makeStyles、withStyles)与 Emotion 可以共存于同一个应用。官方为此还专门提供了 Next.js + SSR 下 Emotion 与 JSS 共存的示例项目(仓库中保留在 examples/material-ui-nextjs-ts-v4-v5-migration/)。
需要特别提醒的边界事实:当时的 v5 迁移指南中,styled-components 也可作为可选替代方案,但官方明确记录了一个 SSR 场景下 Babel 插件的已知问题,因此默认强烈推荐使用 Emotion。Emotion 因此成为 v5 起不可绕开的 peer dependency——当前仓库中 packages/mui-material/package.json 仍声明 @emotion/react@^11.5.0 与 @emotion/styled@^11.3.0 为 peer 依赖。
渐进式迁移 JSS 的两条路径
仓库的 migrating-from-jss.md 给出了两条渐进迁移路径:
路径一:使用 codemod 自动转换到 styled API
npx @mui/codemod@latest v5.0.0/jss-to-styled <path>
该 codemod 会把 makeStyles 调用改写为 styled 组件。官方特别提示:这种自动改写会提升 CSS 优先级(specificity),而且并非所有情况都能完美覆盖,建议先在小范围文件上试跑、人工检查后再继续。它生成的代码形态大致是:用 ${PREFIX}-root 这类带前缀的 class 名声明 classes 映射,再把根节点替换为 styled('div') 生成的 Root 组件。
路径二:手动迁移到 sx API 或 styled API
官方推荐在"创建响应式样式、覆盖少量 CSS"这类场景优先使用 sx prop 而非 styled(),因为 styled() 对一次性样式来说属于过度设计。下方是官方示例中的手动迁移形态(theme.spacing、theme.shadows 等主题令牌在两种写法间一一对应):
import Chip from '@mui/material/Chip';
-import makeStyles from '@mui/styles/makeStyles';
+import Box from '@mui/material/Box';
-const useStyles = makeStyles((theme) => ({
- wrapper: {
- display: 'flex',
- },
- chip: {
- padding: theme.spacing(1, 1.5),
- boxShadow: theme.shadows[1],
- }
-}));
function App() {
- const classes = useStyles();
return (
- <div className={classes.wrapper}>
+ <Box sx={{ display: 'flex' }}>
{/* ... */}
- <Chip className={classes.chip} />
+ <Chip sx={{ padding: (theme) => theme.spacing(1, 1.5) }} />
- </div>
+ </Box>
);
}
3. 更好的定制工具:sx prop
v5 引入的 sx prop 是这篇文章最值得展开的实践性亮点。它允许你直接对单个组件应用样式规则,而无需动用整套 styled() API。sx 处理的是一套 CSS 超集,意味着如果你已熟悉 CSS,几乎可以零成本上手。
官方博客给出的完整示例(可直接复制运行)如下:
import * as React from 'react';
import Box from '@mui/material/Box';
export default function BoxSx() {
return (
<Box
sx={{
width: 300,
height: 300,
backgroundColor: 'primary.dark',
'&:hover': {
backgroundColor: 'primary.main',
opacity: [0.9, 0.8, 0.7],
},
}}
/>
);
}
这段代码展示了 sx 的三种关键能力,值得逐一展开说明:
- 直接消费主题令牌:
primary.dark、primary.main直接引用主题调色板,无需手工拼接颜色值; - 嵌套选择器:
'&:hover'用于书写伪类样式,作用域天然局限在当前组件上; - 数组形式的响应式值:
opacity: [0.9, 0.8, 0.7]按照 breakpoints 从小到大依次生效,等价于手写多组 media query,是官方文档中推荐的创建响应式样式的方式。
从源码实现看,sx 的底层逻辑位于 packages/mui-system/src/styleFunctionSx/styleFunctionSx.js:它把传入的样式对象按属性名拆解(如 spacing、palette、typography、breakpoints 等系统模块),逐条转成真实的 CSS 规则,并支持通过 extendSxProp 把 sx 展开到元素上。换句话说,sx 并不是某个组件的特例,而是整套 mui-system 的通用样式机制,因此 Box、Typography、Button 乃至所有 v5 组件都天然支持它。主题令牌类(如 primary.dark)之所以可用,正是因为它先解析自主题的调色板对象。
4. TypeScript 化的 prop 说明:IntelliSense 内联提示
v5 把所有组件的 prop 描述都改写为 TypeScript 定义书写,这意味着你在 IDE 里把鼠标悬停在某个 prop 上时,就能看到其用法说明、类型与默认值,不必再离开代码去查官方文档。这类"文档即类型"的工程化改进大幅提升了日常开发效率。
这一能力对 v5 而言属于"开箱即得"——只要项目本身启用了 TypeScript 语言服务,就能享受到组件自带 JSDoc/类型注释的补全与提示。
5. 远景:可选的 CSS variables 支持
在 v5 发布时,CSS variables(自定义属性)被官方列为"即将到来"(upcoming)的能力,它有望解决大量定制化痛点,其中最常被社区提及的就是 暗色模式首屏闪烁(dark mode flashing)问题——传统上暗色主题的切换发生在客户端 JS 执行之后,用户刷新页面时会先看到亮色再跳变到暗色;而通过把主题令牌下推到 CSS 变量、在 HTML 层直接注入,可以在首帧就应用正确主题。
这项能力在 v5 中设计为 opt-in(按需开启),用户升级到 v5 后不需要一次性接受全部变动。当时社区可在 issue #32049 中追踪其落地进度。作为佐证,当前仓库中 createTheme 的实现 仍保留着 cssVariables?: boolean | Pick<CssVarsThemeOptions, CssVarsConfigList> 参数(默认值为 false),说明这条"主题层支持 CSS 变量"的设计路线已从当年的远景变成了仓库中真实可配置的能力。
现在就升级:官方迁移文档中的可执行步骤
结合仓库中重构后的 migration-v4.md,官方给出的升级动线如下,按顺序执行即可。
第一步:升级 React 与 TypeScript
如果你的 React 低于 17.0.0,先升级基础依赖(建议至少 @material-ui/core@^4.11.2 + react@^17.0.0):
npm install @material-ui/core@^4.11.2 react@^17.0.0
同时确保 react-scripts、@types/react、@types/react-dom 版本足够新。官方提示:完成每一步后都要确认应用无报错并提交 commit。
第二步:在根部配置好 ThemeProvider
升级到 v5 前,请确保应用根部与测试中都包裹了 ThemeProvider(即便使用默认主题也要包),并避免在 ThemeProvider 之外调用 useStyles。原因在于:过渡期内你仍会通过废弃的 @mui/styles 包使用 JSS 工具(makeStyles 等),而该包强依赖 ThemeProvider 上下文。
import { ThemeProvider, createMuiTheme, makeStyles } from '@material-ui/core/styles';
const theme = createMuiTheme();
function App() {
// ❌ 若写成 const classes = useStyles(),请把它移入被 <ThemeProvider /> 包裹的组件内部
return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
}
第三步:安装 v5 包、替换 import 并清理旧包
按官方命名变更,v5 起所有包名从 @material-ui/* 改为 @mui/*。核心映射关系包括:
| 旧包(v4) | 新包(v5) |
|---|---|
@material-ui/core |
@mui/material |
@material-ui/styles |
@mui/styles |
@material-ui/icons |
@mui/icons-material |
@material-ui/lab |
@mui/lab |
@material-ui/system |
@mui/system |
@material-ui/unstyled |
@mui/base |
安装新包,同时补上 Emotion peer 依赖:
npm install @mui/material @mui/styles
npm install @emotion/react @emotion/styled
如果使用 @material-ui/lab、@material-ui/icons,分别安装 @mui/lab、@mui/icons-material;日期时间选择器(pickers)在 v5 中已移交到 MUI X 产品线,请迁移到 @mui/x-date-pickers。确认应用仍可运行后,再安全卸载旧包:
npm uninstall @material-ui/*
第四步:运行 codemod 处理破坏性变更
仓库迁移文档强调:绝大多数破坏性变更可以通过官方 codemod 自动改写。优先使用聚合了大部分转换器的 preset-safe,但它对同一目录只应运行一次:
npx @mui/codemod@latest v5.0.0/preset-safe <path>
另有三个针对性 codemod 值得了解(它们的产物可反推出 v5 中两个重要的默认值变更):
variant-prop:为未显式指定variant的<TextField />、<FormControl />、<Select />补上variant="standard"——因为默认值已从 v4 的"standard"改为 v5 的"outlined"。如果你已经在主题里把variant: 'outlined'设为默认值,就不要再运行它;link-underline-hover:为未指定underline的<Link />补上underline="hover"——默认值已从 v4 的"hover"改为 v5 的"always"。同理,若主题已把underline: 'always'设为默认,则无需运行。
npx @mui/codemod@latest v5.0.0/variant-prop <path>
npx @mui/codemod@latest v5.0.0/link-underline-hover <path>
第五步:处理 CSS 优先级与手动适配
codemod 无法覆盖全部变更,其余需要手动处理,例如 CSS 优先级调整:如果你习惯通过 import 普通 CSS 文件来覆盖组件样式,在 v5(Emotion 注入样式顺序变化后)需要提高选择器优先级。官方示例中,若想覆盖 Chip 的删除图标:
import './style.css';
import Chip from '@mui/material/Chip';
const ChipWithGreenIcon = () => (
<Chip
classes={{ deleteIcon: 'green' }}
label="delete icon is green"
onDelete={() => {}}
/>
);
单纯写 .green { color: green; } 无法命中,需要写成:
.MuiChip-root .green {
color: green;
}
附:兼容性范围的显著变化
从仓库迁移文档可以确认,v5 还大幅收紧了浏览器与运行时的支持基线:默认 bundle 不再支持 IE 11;按 browserslist 查询 > 0.5%, last 2 versions, Firefox ESR, not dead, not IE 11, maintained node versions 推导,最低版本要求大致为 Node 12、Chrome 90、Edge 91、Firefox 78、Safari 14(macOS)/12.5(iOS)。如果你的产品仍必须支持 IE 11,需要在升级前另行评估 legacy bundle 方案。这些边界事实在动手升级前值得逐条核对。
结语与进一步阅读
v4 → v5 的迁移体量虽大,但官方通过"小步提交 + codemod 自动改写 + 渐进式样式迁移"的组合拳,已经把摩擦降到最低。升级的意义不仅在于拿到 React 18 支持与新样式引擎的性能收益,更在于提前站上 Emotion 化、sx 优先、类型完善、CSS variables 化这条后续所有大版本演进的主线上。
需要深入时,请在仓库内按如下顺序查阅:
- 总入口:migration-v4.md
- 样式与主题破坏性变更:v5-style-changes.md
- 组件破坏性变更:v5-component-changes.md
- JSS → Emotion 渐进迁移:migrating-from-jss.md
- 遇到问题时:troubleshooting.md
sxprop 的完整 API 文档位于 docs/data/system/getting-started/the-sx-prop/,其底层实现可阅读 packages/mui-system/src/styleFunctionSx/styleFunctionSx.js- codemod 全量说明见 packages/mui-codemod/README.md
- 迁移期 Next.js + Emotion/JSS 共存的参考示例:examples/material-ui-nextjs-ts-v4-v5-migration/
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00

