首页
/ @mui/codemod 迁移脚本完全指南:从 v0.15 到 v9 一键升级 Material UI、Base UI、MUI System 与 Joy UI

@mui/codemod 迁移脚本完全指南:从 v0.15 到 v9 一键升级 Material UI、Base UI、MUI System 与 Joy UI

2026-09-07 15:35:19作者:柯茵沙

@mui/codemod 是 Material UI 官方开源的自动化迁移工具集,它基于 jscodeshift(改写 JS/TS 源码)并可选地通过 postcss(同步改写 CSS 文件)把历史版本的组件 API 自动升级到新版本,覆盖 Material UI、Base UI、MUI System 与 Joy UI。读完本文,你将掌握 @mui/codemod 的命令行用法、全部选项与自定义包名场景,了解 deprecations/ 下针对最新废弃 API 的迁移集合,以及 v9→v0.15 各历史大版本迁移脚本的适用场景和注意事项,从而在项目升级中安全、批量地完成代码改造。

一、@mui/codemod 是什么

在 Material UI 的历史演进中,多次出现破坏性 API 变更:属性改名、组件迁移包、components/componentsProps 统一为 slots/slotProps、主题函数签名变化、CSS 类名语义拆分等。手工迁移容易遗漏且极耗精力,于是官方把这些一次性改写逻辑封装成一个个 codemod 脚本,发布为独立的 npm 包 @mui/codemod

其核心特点如下:

  • 基于 jscodeshift 对 JavaScript/TypeScript 源码做 AST 变换;
  • 部分脚本还会附带 postcss 插件,同步改写项目里的 .css 文件(例如拆分后的类名选择器);
  • 脚本以迁移目标版本 命名并分层存放,历史脚本长期保留,方便任何旧版本项目逐级迁移;
  • 仓库内源码位于 packages/mui-codemod/src,按 v0.15.0v1.0.0v4.0.0v5.0.0v6.0.0v7.0.0v9.0.0deprecations/ 分目录组织,每个脚本通常配有独立的 .test.jstest-cases/ 夹具用于验证变换正确性;
  • 依据 packages/mui-codemod/package.json,当前包版本为 9.4.0,要求 node >= 20.19.0,核心依赖为 jscodeshift@^17.4.0postcssyargs

二、安装与命令行用法

该包无需显式安装,通过 npx 即可直接运行:

npx @mui/codemod@latest <codemod> <paths...>

其中:

  • codemod:要执行的迁移脚本名称(必填字符串),例如 v5.0.0/theme-spacing-apideprecations/all
  • paths:透传给 jscodeshift 的文件或目录路径(必填),可以传一个或多个。

官方 CLI 内建示例:

npx @mui/codemod@latest v4.0.0/theme-spacing-api src
npx @mui/codemod@latest v5.0.0/component-rename-prop src -- \
  --component=Grid --from=prop --to=newProp
npx @mui/codemod@latest v5.0.0/preset-safe src --parser=flow

命令行选项

完整选项由 CLI 入口源码 用 yargs 定义,汇总如下:

选项 含义 默认值
--version 显示版本号 false
--help 显示帮助 false
--dry 预演模式,不真正改动任何文件 false
--parser 指定 jscodeshift 使用的解析器 'tsx'
--print 把变换后的文件打印到 stdout(利于开发调试) false
--jscodeshift (高级)把字符串原样追加给 jscodeshift 进程 false
--packageName 在 import 语句中查找的包名 '@mui/material'

从源码可以确认的默认行为细节:

  • jscodeshift 阶段默认处理扩展名为 js,ts,jsx,tsx,json 的文件,并强制忽略 **/node_modules/****/*.css.css 交给后续 postcss 阶段);
  • 若指定的 transform 在源码中找不到,CLI 会抛出类似 Transform '<name>' not found 的错误并提示查阅 README;
  • 实际执行方式是 child_process.spawnSync('node', [jscodeshiftExecutable, '--transform', ...]),并在控制台打印完整命令供排查。

输出与预演

在正式改动前,建议先使用 --dry 观察将要发生的变化:

npx @mui/codemod@latest v7.0.0/grid-props src --dry

配合 --print 可以不改写文件而直接在终端查看每个文件的变换结果,对调试与审查非常有用。

三、自定义包名:--packageName

默认情况下脚本只识别从 @mui/material 导入的组件。如果你的项目使用自定义包名来转发(re-export)Material UI 组件,例如 @org/ui,就需要显式指定:

npx @mui/codemod@latest --packageName="@org/ui"

上面的命令会让脚本在源码里查找 @org/ui 而不是 @mui/material。从 v9.0.0 system-props 实现 可以看到,packageName 会被并入一个 importSources 数组,凡是匹配该字符串本身或以其 / 开头的 import 声明(例如 @org/ui/Button)都会被识别,从而支持路径级导入(import Button from '@mui/material/Button')与命名导入(import { Button } from '@mui/material')两种写法。

四、透传 jscodeshift 与 recast 选项

--jscodeshift

想向底层 jscodeshift 透传更多参数时使用 --jscodeshift="...",字符串会被原样拼接到 jscodeshift 命令行:

npx @mui/codemod@latest --jscodeshift="--run-in-band --verbose=2"

recast printOptions

部分变换需要控制代码打印格式(如引号风格),可以借助 jscodeshift 的 printOptions 命令行参数间接传给 recast 的 printer:

npx @mui/codemod@latest <transform> <path> --jscodeshift="--printOptions='{\"quote\":\"double\"}'"

例如在 removeSystemProps.js 中,options.printOptions 会被取出并传给 root.toSource(printOptions),最终按你的偏好生成输出。

-- 后的 codemod 专用参数

-- 之后的参数不进入 jscodeshift,而是作为该 codemod 自己的输入。典型例子:

npx @mui/codemod@latest v5.0.0/component-rename-prop <path> -- \
  --component=Grid --from=prop --to=newProp

它会把任意组件 <Component prop="value" /> 泛化地重命名为 <Component newProp="value" />。还有 v7/v6 的 Grid 脚本接受自定义断点、v9 的 system-props 接受 --jsx,详见下文。

五、JS 与 CSS 双通道改写机制

升级中有一类常见的破坏性变更:把“组合型”状态类名拆成多个独立状态类。例如 .MuiButton-textPrimary 被拆为 .MuiButton-text.MuiButton-colorPrimary 的组合。这同时影响两种载体:

  1. JS 通道MuiButton: { styleOverrides: { root: { '& .MuiButton-textPrimary': {...} } } }[&.${buttonClasses.textPrimary}] 这样的模板字符串;
  2. CSS 通道:项目里真实的 .MuiButton-textPrimary { ... } 选择器。

因此对应的 -classes 类脚本在 README 中会并列给出 JS transformsCSS transforms 两段 diff。在底层实现上,codemod.jsrunPostcssTransform 会先探测 transform 目录下是否存在 postcss.config.js,若存在就把用户传入路径下解析出的 .css 文件(传入目录时为 目录/**/*.css)交给 postcss --replace --verbose 执行;若不存在则静默跳过 postcss 阶段(这是文档中"部分 codemod 会运行 postcss 插件"的实现基础)。

六、deprecations/:面向当前最新废弃 API 的迁移集合

deprecations/ 前缀集中收纳了紧跟最新版本废弃周期的所有迁移脚本,统一入口是:

npx @mui/codemod@latest deprecations/all <path>

all全部废弃脚本的组合。这一集合按变更性质可分为两大类,下面逐一说明(每个脚本都对应 src/deprecations 下的同名目录,并可用各自命令行单独执行)。

6.1 属性迁移到 slots / slotProps

Material UI 正在把面向"自定义内部渲染节点"的历史属性(componentscomponentsPropsXXComponentXXPropsTransitionComponentPaperProps 等)统一收敛到 slotsslotProps。以下是文档给出的代表性脚本:

Accordion:TransitionComponent/TransitionProps 归入 transition slot

 <Accordion
-  TransitionComponent={CustomTransition}
-  TransitionProps={{ unmountOnExit: true }}
+  slots={{ transition: CustomTransition }}
+  slotProps={{ transition: { unmountOnExit: true } }}
 />
npx @mui/codemod@latest deprecations/accordion-props <path>

Alert:components/componentsProps 迁移为 slots/slotProps(组件用法与 theme defaultProps 都会处理)

 <Alert
-  components={{ CloseButton: CustomButton }}
-  componentsProps={{ closeButton: { testid: 'test-id' } }}
+  slots={{ closeButton: CustomButton }}
+  slotProps={{ closeButton: { testid: 'test-id' } }}
 />
 MuiAlert: {
   defaultProps: {
-    components: { CloseButton: CustomButton }
-    componentsProps: { closeButton: { testid: 'test-id' }}
+    slots: { closeButton: CustomButton },
+    slotProps: { closeButton: { testid: 'test-id' } },
   },
 },
npx @mui/codemod@latest deprecations/alert-props <path>

Autocomplete:多个组件/属性一并收敛,且 renderTags/getTagProps/focusedTag 改名

 <Autocomplete
-  ChipProps={{ height: 10 }}
-  PaperComponent={CustomPaper}
-  PopperComponent={CustomPopper}
-  ListboxComponent={CustomListbox}
-  ListboxProps={{ height: 12 }}
-  renderTags={(value, getTagProps, ownerState) =>
-    value.map((option, index) => (
-      <Chip label={option.label} {...getTagProps({ index })} />
-    ))
-  }
-  componentsProps={{
-    clearIndicator: { width: 10 },
-    paper: { width: 12 },
-    popper: { width: 14 },
-    popupIndicator: { width: 16 },
-  }}
+  slots={{
+    paper: CustomPaper,
+    popper: CustomPopper
+  }}
+  slotProps={{
+    chip: { height: 10 },
+    listbox: {
+        component: CustomListbox,
+        ...{ height: 12 },
+    },
+    clearIndicator: { width: 10 },
+    paper: { width: 12 },
+    popper: { width: 14 },
+    popupIndicator: { width: 16 },
+  }}
+  renderValue={(value, getItemProps, ownerState) =>
+    value.map((option, index) => (
+      <Chip label={option.label} {...getItemProps({ index })} />
+    ))
+  }
 />

同时该脚本还会处理 useAutocomplete 返回值与 renderInput 内部对 params.InputProps 的访问:

 const {
-  getTagProps,
-  focusedTag,
+  getItemProps,
+  focusedItem,
 } = useAutocomplete(props);
npx @mui/codemod@latest deprecations/autocomplete-props <path>

AvatarGroup:slot 名从 additionalAvatar 调整为 surplus

 <AvatarGroup
-  componentsProps={{
-    additionalAvatar: { color: 'red' },
+  slotProps={{
+    surplus: { color: 'red' },
   }}
 />
npx @mui/codemod@latest deprecations/avatar-group-props <path>

Checkbox / Radio / Switch:inputPropsinputRef 合入 slotProps.input

 <Checkbox
-  inputProps={{ 'aria-label': 'Checkbox' }}
-  inputRef={ref}
+  slotProps={{ input: { 'aria-label': 'Checkbox', ref } }}
 />
npx @mui/codemod@latest deprecations/checkbox-props <path>
npx @mui/codemod@latest deprecations/radio-props <path>
npx @mui/codemod@latest deprecations/switch-props <path>

Drawer(含 SwipeableDrawer)与 Popover、Menu、Dialog:背板/纸面/过渡等统一进 slot

 <Drawer
-  BackdropComponent={CustomBackdrop}
-  BackdropProps={{ transitionDuration: 300 }}
-  PaperProps={{ elevation: 20 }}
-  SlideProps={{ direction: 'right' }}
+  slots={{ backdrop: CustomBackdrop }}
+  slotProps={{
+    backdrop: { transitionDuration: 300 },
+    paper: { elevation: 20 },
+    transition: { direction: 'right' },
+  }}
 />
npx @mui/codemod@latest deprecations/drawer-props <path>

TextField:五类属性全部并入 slotProps(注意命名语义变化)

 <TextField
-  InputProps={CustomInputProps}
-  inputProps={CustomHtmlInputProps}
-  SelectProps={CustomSelectProps}
-  InputLabelProps={CustomInputLabelProps}
-  FormHelperTextProps={CustomFormHelperProps}
+  slotProps={{
+    input: CustomInputProps,
+    htmlInput: CustomHtmlInputProps,
+    select: CustomSelectProps,
+    inputLabel: CustomInputLabelProps,
+    formHelper: CustomFormHelperProps,
+  }}
 />
npx @mui/codemod@latest deprecations/text-field-props <path>

这一类别下,README 还记录了以下脚本(命令一律为 npx @mui/codemod@latest deprecations/<name> <path>):

脚本名 迁移要点
avatar-props imgPropsslotProps.img
backdrop-props components(Root)/componentsPropsslots/slotPropsTransitionComponentslots.transition
badge-props 同上,components/componentsProps → slots/slotProps
card-header-props titleTypographyProps/subheaderTypographyPropsslotProps.title/slotProps.subheader
dialog-props PaperPropsslotProps.paperTransitionComponentslots.transitionTransitionPropsslotProps.transition
filled-input-propsinput-base-propsinput-propsoutlined-input-props 各类 Input 的 components/componentsProps → slots/slotProps
form-control-label-props componentsProps.typographyslotProps.typography
list-item-props components/componentsProps → slots/slotProps
list-item-text-props primaryTypographyProps/secondaryTypographyPropsslotProps.primary/slotProps.secondary
menu-props TransitionComponent/MenuListProps/TransitionProps → slots/slotProps(list/transition)
mobile-stepper-props LinearProgressPropsslotProps.progress
modal-props components(Root/Backdrop)/componentsProps → slots/slotProps
pagination-item-props components 导航图标 → slots
popover-props Backdrop/Paper/Transition 系列属性 → slots/slotProps
popper-props components(Root)/componentsProps → slots/slotProps
rating-props IconContainerComponentslots.icon.component
slider-props components(Track)/componentsProps → slots/slotProps
snackbar-props ClickAwayListener/Content/Transition 系列 → slots/slotProps
speed-dial-propsspeed-dial-action-props 过渡与 Fab/Tooltip 属性 → slots/slotProps
step-content-propsstep-label-props Transition/StepIcon/Typography 属性 → slots/slotProps
tabs-props ScrollButtonComponent/TabIndicatorProps/TabScrollButtonProps → slots/slotProps;slots.StartScrollButtonIcon 等改为小驼峰 startScrollButtonIcon
tooltip-props Popper/Transition/components/componentsProps 全量 → slots/slotProps

6.2 复合状态类名拆分(含 CSS 同步)

第二类废弃是针对"一个类名同时编码多个状态"的历史 CSS 结构。新版把变体类名拆成相互独立的类(如 text+colorSuccess),并让子元素状态类转移为对父级组合类名的后代选择。

Button 为例(JS 通道):

 import { buttonClasses } from '@mui/material/Button';

 MuiButton: {
   styleOverrides: {
     root: {
-      [`&.${buttonClasses.textPrimary}`]: {
+      [`&.${buttonClasses.text}.${buttonClasses.colorPrimary}`]: {
         color: 'red',
       },
-      [`& .${buttonClasses.iconSizeSmall}`]: {
+      [`&.${buttonClasses.sizeSmall} > .${buttonClasses.icon}`]: {
         color: 'red',
       },
     },
   },
 },

CSS 通道同步改写:

-.MuiButton-textPrimary
+.MuiButton-text.MuiButton-colorPrimary
-.MuiButton-root .MuiButton-iconSizeSmall
+.MuiButton-root.MuiButton-sizeSmall > .MuiButton-icon
npx @mui/codemod@latest deprecations/button-classes <path>

AccordionSummary 同理,把容器上的 contentGutters 组合拆开:

-      [`& .${accordionSummaryClasses.contentGutters}`]: {
+      [`&.${accordionSummaryClasses.gutters} .${accordionSummaryClasses.content}`]: {
         color: 'red',
       },

CSS:

-.MuiAccordionSummary-root .MuiAccordionSummary-contentGutters
+.MuiAccordionSummary-root.MuiAccordionSummary-gutters .MuiAccordionSummary-content
npx @mui/codemod@latest deprecations/accordion-summary-classes <path>

Select 的图标选择器改为兄弟选择器形式:

-      [`& .${selectClasses.iconFilled}`]: {
+      [`& .${selectClasses.filled} ~ .${selectClasses.icon}`]: {
         color: 'red',
       },
npx @mui/codemod@latest deprecations/select-classes <path>

该类目下其余脚本(均同时提供 JS transforms 与 CSS transforms,命令格式相同):

脚本名 典型拆分语义(举例)
alert-classes standardSuccessstandard + colorSuccess(filled/outlined/standard × success/info/warning/error)
button-group-classes groupedTextHorizontaltext.horizontal 下的 grouped 后代
chip-classes clickableColorPrimaryclickable + colorPrimaryavatarSmall/iconSmall/deleteIcon... → 尺寸类下的子元素
circular-progress-classes circleDeterminate/circleIndeterminatedeterminate/indeterminate 下的 circle
dialog-classes paperScrollBody/paperScrollPaper → scroll 类下的 > .paper
drawer-classes paperAnchorLeft/paperAnchorDockedLeft 等 → anchorLeft/docked.anchorLeft 下的 > .paper
image-list-item-bar-classes titleWrapBelow/titleWrapActionPosLeft 等 → position/actionPosition 类下的 titleWrap/actionIcon
input-base-classes inputSizeSmall/inputMultiline 等 → 根状态类下的 > .input
linear-progress-classes bar1Buffer/barColorPrimary 等 → 状态类下的 bar1/bar2/bar/dashed
pagination-item-classes textPrimary/outlinedSecondary 等 → text/outlined + colorXxx
slider-classes thumbSizeSmall/thumbColorPrimary 等 → size/color 类下的 > .thumb
step-connector-classes lineHorizontal/lineVertical → horizontal/vertical 下的 line
tab-classes iconWrapper 更名为 icon
table-sort-label-classes iconDirectionAsc/iconDirectionDesc → direction 类下的 > .icon
toggle-button-group-classes groupedHorizontal/groupedVertical → 方向类下的 grouped

6.3 属性删除或迁移到 sx

另一些废弃属性被直接移除并建议改用 sx 表达。典型示例:

Divider 的 light

 <Divider
-  light
+  sx={{ opacity: 0.6 }}
 />
npx @mui/codemod@latest deprecations/divider-props <path>

Typography 的 paragraph

 <Typography
-  paragraph
+  sx={{ marginBottom: '16px' }}
 />
 <Typography
-  paragraph={isTypographyParagraph}
+  sx={isTypographyParagraph ? { marginBottom: '16px' } : undefined}
 />
 MuiTypography: {
   defaultProps: {
-    paragraph: true
+    sx: { marginBottom: '16px' },
   },
 },
npx @mui/codemod@latest deprecations/typography-props <path>

七、版本化迁移脚本纵览

7.1 v9.0.0/system-props

npx @mui/codemod@latest v9.0.0/system-props <path>

把 Box、Stack、Typography、Link、Grid、DialogContentText、TimelineContent、TimelineOppositeContent 上的系统属性(布局、间距、颜色、字体等)搬进 sx。相比 v6 版本,v9 版本还额外处理:

  • Typography 的 color="inherit"(移入 sx);
  • Link 的 color="text.secondary"(移入 sx,同时保留 "primary""inherit" 这类具名颜色作为组件属性);
  • DialogContentText、TimelineContent、TimelineOppositeContent 组件。
-<Typography color="inherit" />
+<Typography sx={{ color: "inherit" }} />

-<Link color="text.secondary" href="#" />
+<Link href="#" sx={{ color: "text.secondary" }} />

实现上(见 removeSystemProps.js),脚本内部维护了一份从 @mui/systemdefaultSxConfig 派生出的系统属性名单(border、p/margin、display、flexbox、grid、position、shadow、sizing、typography 等约百项),先通过 import 扫描识别目标组件,再把 JSX 属性与既有 sx 智能合并(对象合并、数组前置、展开符处理等),并对颜色类组件使用单独的"匹配器"决定哪些颜色值保留为属性。

处理无显式 import 的项目(--jsx):如果项目使用 unplugin-auto-import 这类自动导入插件,组件可能没有显式 import 语句,此时可跳过 import 检测、直接用 --jsx 指定元素名:

npx @mui/codemod@latest v9.0.0/system-props <path> -- --jsx=Box,Typography,Stack,Link,Grid,DialogContentText

7.2 v7.0.0

theme-color-functions:把从 @mui/system/colorManipulator 导入的 alpha()/lighten()/darken() 换成 theme 上的方法:

- import { alpha, lighten, darken } from '@mui/system/colorManipulator';

- alpha(theme.palette.primary.main, 0.8)
+ theme.alpha((theme.vars || theme).palette.primary.main, 0.8)

- lighten(theme.palette.primary.main, 0.1)
+ theme.lighten(theme.palette.primary.main, 0.1)

- darken(theme.palette.primary.main, 0.3)
+ theme.darken(theme.palette.primary.main, 0.3)
npx @mui/codemod@latest v7.0.0/theme-color-functions <path>

grid-props:更新 @mui/material/Grid@mui/system/Grid@mui/joy/Grid 的响应式尺寸/偏移写法:

 <Grid
-   xs={12}
-   sm={6}
-   xsOffset={2}
-   smOffset={3}
+   size={{ xs: 12, sm: 6 }}
+   offset={{ xs: 2, sm: 3 }}
 />

可通过 --jscodeshift='--muiBreakpoints=mobile,desktop' 传入主题自定义断点,让变换使用项目自己的断点名:

npx @mui/codemod@latest v7.0.0/grid-props <path> --jscodeshift='--muiBreakpoints=mobile,desktop'
- <Grid mobile={12} mobileOffset={2} desktop={6} desktopOffset={4} >
+ <Grid size={{ mobile: 12, desktop: 6 }} offset={{ mobile: 2, desktop: 4 }} >

lab-removed-components:修正一批从 @mui/lab 移入 @mui/material 的组件/hook 的 import,包括 Alert、AlertTitle、Autocomplete、AvatarGroup、Pagination、PaginationItem、Rating、Skeleton、SpeedDial、SpeedDialAction、SpeedDialIcon、ToggleButton、ToggleButtonGroup、usePagination。既处理 @mui/lab 顶层命名导入,也处理组件级文件导入:

- import { Alert } from '@mui/lab';
+ import { Alert } from '@mui/material';

- import Alert, { alertClasses } from '@mui/lab/Alert';
+ import Alert, { alertClasses } from '@mui/material/Alert';
npx @mui/codemod@latest v7.0.0/lab-removed-components <path>

input-label-size-normal-medium:把 InputLabel 的 size 取值 "normal" 改为 "medium"

-<InputLabel size="normal">Label</InputLabel>
+<InputLabel size="medium">Label</InputLabel>
npx @mui/codemod@latest v7.0.0/input-label-size-normal-medium <path>

7.3 v6.0.0

sx-prop:把 sx 中的函数写法改写为与 @pigment-css/react 兼容的形式——将 theme.palette.mode 条件判断替换为 theme.applyStyles()

 <Box
-  sx={{
-    backgroundColor: (theme) =>
-      theme.palette.mode === 'light' ? theme.palette.grey[100] : theme.palette.grey[900],
-  }}
+  sx={theme => ({
+    backgroundColor: theme.palette.grey[900],
+    ...theme.applyStyles("light", {
+      backgroundColor: theme.palette.grey[100]
+    })
+  })}
 />
npx @mui/codemod@latest v6.0.0/sx-prop <path>

system-props:移除 Box 等的系统属性并放入 sx

-<Box ml="2px" py={1} color="primary.main" />
+<Box sx={{ ml: '2px', py: 1, color: 'primary.main' }} />
npx @mui/codemod@latest v6.0.0/system-props <path>

theme-v6:把 @mui/system@v5 的主题创建升级到与 Pigment CSS 兼容:用 theme.applyStyles() 替换 palette mode 条件;用 variants 替换 ownerState 分支;把主题 variants 移到根 slot:

 createTheme({
   components: {
     MuiButton: {
-      variants: [ { props: { color: 'primary' }, style: { color: 'red' } } ],
       styleOverrides: {
-        root: ({ theme, ownerState }) => ({
+        root: ({ theme }) => ({
           ...ownerState.variant === 'contained' && {
             backgroundColor: alpha(theme.palette.primary.main, 0.8),
             ...theme.palette.mode === 'dark' && { ... }
           },
+          variants: [
+            { prop: { variant: 'contained' }, style: { ... } },
+            { prop: { color: 'primary' }, style: { color: 'red' } },
+          ],
         })
       }
     }
   }
 })
npx @mui/codemod@latest v6.0.0/theme-v6 <path>

styled:把 @mui/system@v5 风格、基于 props 的 styled 样式改写为 variants

 styled('div')(({ theme, disabled }) => ({
   color: theme.palette.primary.main,
-  ...(disabled && {
-    opacity: 0.5,
-  }),
+  variants: [
+    {
+      prop: 'disabled',
+      style: { opacity: 0.5 },
+    },
+  ],
 }));
npx @mui/codemod@latest v6.0.0/styled <path>

该脚本能处理含展开符、三元表达式与嵌套对象的复杂样式,但文档明确列出两类局限性,需要人工兜底:

  1. 动态值不转换:如 width: ownerState.width ?? '100%',建议手动声明 CSS 变量并用内联样式赋值:

    const ResizableContainer = styled('div')({
      width: 'var(--ResizableContainer-width, 100%)',
      height: 'var(--ResizableContainer-height, 100%)',
    });
    
  2. 动态引用主题不转换:如 backgroundColor: (theme.vars || theme).palette[ownerState.color]?.main,需要手动遍历主题为每个颜色生成 variants

    const Test = styled('div')(({ theme }) => ({
      variants: Object.entries(theme.palette)
        .filter(([color, value]) => value.main)
        .map(([color, value]) => ({
          props: { color },
          style: { backgroundColor: value.main },
        })),
    }));
    

grid-v2-props:针对 @mui/material/Grid2@mui/system/Grid@mui/joy/Gridsize/offset 迁移,行为与 v7 的 grid-props 一致,同样支持 --muiBreakpoints

npx @mui/codemod@latest v6.0.0/grid-v2-props <path>

7.4 v5.0.0:史上最大规模的一批迁移脚本

v5 迁移脚本数量最多,其中 preset-safe 是"一键组合",官方提示它包含所有重要变换器、只能运行一次

npx @mui/codemod@latest v5.0.0/preset-safe <path|folder>

preset-safe 的组合清单见 READMEsrc/v5.0.0/preset-safe.js,涵盖下列脚本中的大部分。下面按用途分类说明这些独立脚本。

包名与模块路径迁移(改名 @material-ui/*@mui/*、模块搬迁)

脚本 作用
mui-replace 全局替换包名:`@material-ui/core
moved-lab-modules 把已从 lab 移入 core 的组件 import 改到 @material-ui/core(Skeleton、SpeedDial、Alert、Autocomplete、Pagination、ToggleButton 等)
date-pickers-moved-to-x 日期/时间选择器 import 由 @mui/lab 改为 @mui/x-date-pickers@mui/x-date-pickers-pro
tree-view-moved-to-x Tree View import 由 @mui/lab 改为 @mui/x-tree-view
optimal-imports 把过深的私有导入收敛到公开入口,利于 tree shaking
path-imports 顶层命名导入转路径导入(top-level-imports 的逆操作,并增加 @mui/icons-material
top-level-imports @mui/material 子模块导入合并为根模块命名导入
core-styles-import core/styles/* 私有路径导入改到 core/styles
material-ui-styles 把 JSS 相关导出从 @material-ui/core/styles 拆分到 @material-ui/styles

Base UI / Joy UI 专属

脚本 作用
base-use-named-exports Base UI 默认导出改具名导出(import/reexport 同步更新)
base-remove-unstyled-suffix 去掉组件/类型名中的 Unstyled 后缀
base-remove-component-prop 移除 Base UI 的 component prop,值转移到 slots.root
base-hook-imports hooks 的导入路径改为新目录
base-rename-components-to-slots Base UI 的 components/componentsProps → slots/slotProps,slot 字段改小驼峰
rename-css-variables Joy UI CSS 变量命名规范化,例如 --List-divider-gap--ListDivider-gap--Switch-track-width--Switch-trackWidth
joy-rename-classname-prefix Joy UI 类名前缀 JoyMui
joy-rename-row-prop Card/List/RadioGroup 的 roworientation="horizontal"
joy-avatar-remove-imgProps Joy Avatar 的 imgProps 并入 slotProps.img
joy-text-field-to-input Joy <TextField> 拆成 FormControl + FormLabel + Input + FormHelperText 组合
joy-rename-components-to-slots Joy UI 的 components/componentsProps → slots/slotProps

主题 API 迁移

脚本 作用
create-theme createMuiTheme() 改名 createTheme()
adapter-v4 引入 adaptV4Theme 并包裹 createTheme(),衔接 v4 主题结构
theme-augment 为 TS 项目补充 DefaultTheme 模块增强
theme-options ThemeOptions 类型改名 DeprecatedThemeOptions
theme-palette-mode palette typemode(对象与 theme.palette.type 访问)
theme-provider MuiThemeProvider 改名 ThemeProvider
theme-breakpoints 修正 down('sm')/between('sm','md') 断点语义(⚠️ 非幂等,只能运行一次)
theme-breakpoints-width theme.breakpoints.width('md')theme.breakpoints.values.md
theme-spacing 去掉 theme.spacing(n) 拼接字符串中的多余 px
theme-typography-round theme.typography.round($n)Math.round($n * 1e5) / 1e5
transitions transitions 导入改名 createTransitions
material-ui-types Omit 类型改名 DistributiveOmit

组件属性/样式迁移

脚本 作用
component-rename-prop 泛化 prop 改名器(--component/--from/--to
autocomplete-rename-closeicon closeIconclearIcon
autocomplete-rename-option getOptionSelectedisOptionEqualToValue
avatar-circle-circularpagination-round-circularskeleton-variantfab-variantcircularprogress-variant 变体/形状取值统一,如 circlecircularroundcircularrectrectangularstaticdeterminate
badge-overlap-value `overlap="circle
box-borderradius-values borderRadius="borderRadius"/{16} 等旧语义值改为 v5 的 1/"16px"
box-rename-css Box 的 css prop → sx
box-rename-gap gridGap/gridColumnGap/gridRowGapgap/columnGap/rowGap
box-sx-prop 支持的 Box 系统属性移入 sx
button-color-prop 删除 color="default"
chip-variant-prop 删除 variant="default"
collapse-rename-collapsedheight collapsedHeightcollapsedSizeclasses.containerclasses.root
dialog-props 移除 disableBackdropClick
dialog-title-props 移除 disableTypography
expansion-panel-component ExpansionPanel*Accordion* 组件改名
grid-justify-justifycontent justifyjustifyContent
grid-list-component GridList*ImageList*
hidden-down-props Hidden 相关迁移(源码位于 src/v5.0.0
icon-button-size 未指定 size 的 IconButton 补 size="large" 保持 v4 外观
link-underline-hover 未指定 underline 的 Link 补 underline="hover"
modal-props 移除 disableBackdropClickonEscapeKeyDown
root-ref 整体移除 RootRef
styled-engine-provider 给包含 ThemeProvider 的文件包上 StyledEngineProvider
table-props Table 系列改名:onChangeRowsPerPageonRowsPerPageChangeonChangePageonPageChangepadding="default""normal"classes.inputclasses.select
tabs-scroll-buttons `scrollButtons="on
textarea-minmax-rows TextField/TextareaAutosize 的 rowsMin/rowsMaxminRows/maxRowsrows 收敛到 TextareaAutosize 的 minRows
use-autocomplete useAutocomplete 的 lab import 改 core
use-transitionprops Dialog/Menu/Popover/Snackbar 的 onEnter*/onExit* 收拢进 TransitionProps
variant-prop TextField/Select/FormControl 未指定 variant 时补 variant="standard";⚠️ 若你已在主题 defaultProps 中设置过 outlined/filled,不要运行它
with-mobile-dialog 移除 withMobileDialog import,插入硬编码回退(含 // FIXME 注释),避免应用崩溃
with-width 移除 withWidth import,插入硬编码回退

JSS → styled / tss-react(两条耗时的样式迁移路线)

  • jss-to-styled:把 makeStyles/withStyles 的 JSS 写法改写成 styled API,示例中会把首个返回元素替换为 styled 组件并生成 PREFIX 化的类名常量。文档附注:这种方式把返回语句的第一个元素转成 styled 组件,会提升 CSS 特异性,建议在解决全部破坏性变更之后再执行。

    npx @mui/codemod@latest v5.0.0/jss-to-styled <path>
    
  • jss-to-tss-react:迁移到等价的 tss-react/mui API。它未处理以下场景,会在对应位置留下 "TODO jss-to-tss-react codemod" 注释,需人工跟进:

    • makeStyles 返回的 hook(如 useStyles)被导出并在其他文件使用时,其他文件的用法不会被转换;
    • CSS 属性值位置的箭头函数不会被转换(规则级箭头函数支持,但有条件);
    • 规则级箭头函数要求参数使用对象解构(如 root: ({ color, padding }) => (...)),未解构的参数(如 (props) => ...)不转换;
    • 规则级箭头函数若包含显式 return 的代码块而非对象表达式,不转换。
    npx @mui/codemod@latest v5.0.0/jss-to-tss-react <path>
    

7.5 v4.0.0

脚本 作用
theme-spacing-api theme.spacing.unit * xtheme.spacing(x);会做基础表达式化简(乘除换算),但超过一个运算的表达式化简不完善,例如 theme.spacing.unit * 5 * 5 只变成 theme.spacing(5) * 5
optimal-imports 把超过一层的 @material-ui/core 深路径导入收敛为利于 tree shaking 的公开导入(v4 语义)
top-level-imports @material-ui/core 子模块导入合并到根模块(v4 语义)
npx @mui/codemod@latest v4.0.0/theme-spacing-api <path>

7.6 v1.0.0

脚本 作用
import-path 适配 v1.0.0 扁平化组件导入路径:@material-ui/core/MenuMenuItem 改为 @material-ui/core/MenuItem。注意:从 pre-v1.0 迁移时需先手工把 material-ui/* 全部替换为 @material-ui/core/* 再运行
color-imports 颜色调色板改新位置,如 blueteal500@material-ui/core/colors/blueteal['500']。支持附加选项:-- --importPath='mui/styles/colors' --targetPath='mui/colors'
svg-icon-imports material-ui/svg-icons/<category>/<icon-name>@material-ui/icons/<IconName>
menu-item-primary-text <MenuItem primaryText="Profile" /><MenuItem>Profile</MenuItem>
npx @mui/codemod@latest v1.0.0/import-path <path>
npx @mui/codemod@latest v1.0.0/color-imports <path> -- --importPath='mui/styles/colors' --targetPath='mui/colors'

7.7 v0.15.0

import-path 适配 v0.15.0 重新组织的目录结构:源码导入 material-ui/src/flat-buttonmaterial-ui/src/FlatButton;npm 导入 material-ui/lib/raised-buttonmaterial-ui/RaisedButton

npx @mui/codemod@latest v0.15.0/import-path <path>

八、完整迁移路径的建议顺序

版本化脚本按目录命名,天然给出了一条逐级升级的主线:项目处于哪个大版本,就按 v0.15.0 → v1.0.0 → v4.0.0 → v5.0.0 → v6.0.0 → v7.0.0 的顺序执行对应脚本;v9 与 deprecations/ 则用于处理最新主版本之后的持续废弃。各版本破坏性变更的详细说明可以在仓库的 docs/data/material-ui/migration 迁移指南目录中查找,与 codemod 一一对应。

实操建议:

  1. 迁移前先把代码提交为干净基线(或生成 patch),便于审查与回滚;
  2. 先用 --dry(必要时加 --print)检查将产生的改动是否符合预期;
  3. 官方对部分脚本给出"仅可运行一次"警告:v5.0.0/preset-safev5.0.0/theme-breakpoints 均非幂等,重复执行可能产生错误结果;
  4. 留意脚本的适用范围标注:base-*joy-* 只影响对应 UI 体系的组件;variant-prop 等对主题默认值有前提假设;
  5. --packageName 适用于封装了二次转发包名的企业级项目;--parser=flow 等参数可按项目语言切换到 Flow/TS 解析器。

九、如何运行包内测试验证迁移器

每个 codemod 都配套了完整的单元测试与"输入/期望输出"夹具。以 v5 脚本为例,src/v5.0.0/ 下每个 .js 变换旁都有同名 .test.js 与同名 .test/ 目录,存放 actual//expected/ 之类的待变换源码与期望产物;v9 与 deprecations/ 中则使用 *.test.jstest-cases/ 目录。可在包内直接跑测试验证:

# 在仓库根目录(pnpm workspace)运行 @mui/codemod 的全部单测
pnpm --workspace-root test:unit --project "*:@mui/codemod"

参见 packages/mui-codemod/package.jsontest 脚本定义。若要本地构建发布产物,可执行 pnpm build(其构建命令会忽略 **/*.test/**actual.jsexpected.jstest-cases/** 等测试夹具,只产出可发布的 CJS bundle)。

十、小结

@mui/codemod 把 MUI 家族横跨十余个大版本、数百条破坏性变更沉淀为可重复执行的 AST 变换:deprecations/all 面向最新废弃周期,v9.0.0 起则逐步兼容 Pigment CSS 的 sx/variants/applyStyles 体系,而 v7v6v5v4v1v0.15 目录完整保留了历史升级路径。使用前先确认脚本适用范围与"一次性运行"类警告,善用 --dry--packageName-- 透传参数,再配合仓库内每个脚本自带的测试夹具校验结果,即可把 MUI 升级这类高风险的大规模改动变成可控、可审计的机械流程。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.74 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.81 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
595
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
920
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.63 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
518
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
389