Codemod скрипты

Codemod — это скрипт автоматического преобразования кода, используемый для массового обновления синтаксиса, API или структуры проекта. В экосистеме MUI (Material-UI) codemod широко применяется при переходе между версиями библиотеки, особенно при крупных обновлениях, например с v4 на v5, где изменились названия компонентов, пропсов и способы стилизации.

Codemod работает на базе jscodeshift — инструмента для манипуляции AST (Abstract Syntax Tree) JavaScript-кода. Основная задача codemod — преобразовать старый код в новый, минимизируя ручную работу и ошибки при масштабных проектах.


Установка и настройка jscodeshift

Для запуска codemod скриптов необходим Node.js и пакет jscodeshift. Установка выполняется через npm:

npm install -g jscodeshift

Проверка версии:

jscodeshift --version

Codemod скрипты для MUI обычно поставляются в виде отдельных файлов .js и содержат инструкции для преобразования конкретных компонентов или API.


Структура codemod скрипта

Codemod скрипт состоит из нескольких ключевых элементов:

  1. Import jscodeshift Основной инструмент для анализа AST и поиска узлов:
const j = require('jscodeshift');
  1. Export функции трансформации Экспортируемая функция принимает file, api и options:
module.exports = function(file, api, options) {
  const j = api.jscodeshift;
  const root = j(file.source);

  // Здесь выполняются преобразования

  return root.toSource();
};
  1. Поиск и модификация узлов AST Основной метод root.find() используется для поиска элементов:
root.find(j.ImportDeclaration, { source: { value: '@mui/core' } })
  .forEach(path => {
    path.node.source.value = '@mui/material';
  });

Основные виды преобразований в MUI codemod

  1. Изменение путей импортов В MUI v5 многие компоненты были перемещены в новые пакеты. Codemod автоматически меняет:
// до
import { Button } from '@material-ui/core';
// после
import { Button } from '@mui/material';
  1. Переименование пропсов компонентов Например, в MUI v5 проп variant="raised" у Button заменяется на variant="contained":
root.find(j.JSXAttribute, { name: { name: 'variant' } })
  .filter(path => path.value.value.value === 'raised')
  .forEach(path => {
    path.value.value.value = 'contained';
  });
  1. Обновление styled API и sx Codemod может автоматически переносить кастомные стили из makeStyles в sx:
root.find(j.CallExpression, { callee: { name: 'makeStyles' } })
  .forEach(path => {
    // Логика преобразования в sx объект
  });
  1. Обработка устаревших компонентов Устаревшие компоненты, такие как GridList, заменяются на новые аналоги ImageList:
root.find(j.ImportSpecifier, { imported: { name: 'GridList' } })
  .forEach(path => {
    path.node.imported.name = 'ImageList';
  });

Практические рекомендации по использованию codemod

  • Создание резервной копии проекта перед запуском скриптов — обязательное требование, так как преобразования могут быть необратимыми.
  • Проверка на отдельной ветке Git позволяет контролировать изменения и интегрировать их постепенно.
  • Комбинация нескольких скриптов: для крупных обновлений MUI обычно запускают последовательность codemod скриптов, начиная с импортов, затем пропсы и завершая стилизацией.
  • Использование опции --dry или --dry-run для предварительного просмотра изменений без их применения:
jscodeshift -t path/to/codemod.js src --dry
  • Фильтрация по файлам: codemod можно запускать только на тех директориях, где находятся компоненты MUI, чтобы ускорить процесс и снизить риск случайных изменений:
jscodeshift -t codemod.js src/components

Логирование и отладка

Для сложных преобразований полезно использовать логирование:

console.log('Преобразован файл:', file.path);

Также можно проверять AST узлы через console.dir(node, { depth: null }), чтобы понимать структуру и корректно модифицировать элементы.


Примеры комплексного использования

  1. Массовая замена всех Typography с устаревшим пропом type:
root.find(j.JSXElement, { openingElement: { name: { name: 'Typography' } } })
  .find(j.JSXAttribute, { name: { name: 'type' } })
  .forEach(path => {
    path.value.name.name = 'variant';
  });
  1. Перенос кастомных тем из createMuiTheme в createTheme:
root.find(j.ImportSpecifier, { imported: { name: 'createMuiTheme' } })
  .forEach(path => {
    path.node.imported.name = 'createTheme';
  });
  1. Конвертация компонентов с withStyles на использование styled или sx:
root.find(j.CallExpression, { callee: { name: 'withStyles' } })
  .forEach(path => {
    // Логика конвертации в styled компонент
  });

Интеграция codemod в CI/CD

Codemod скрипты можно интегрировать в пайплайн CI/CD для автоматической проверки совместимости кода при обновлении зависимостей MUI. Например, на этапе сборки можно запускать:

jscodeshift -t codemods/mui5-imports.js src --dry

Ошибки или неподдерживаемые конструкции могут быть зафиксированы как предупреждения, что облегчает миграцию крупных проектов.


Итоговая структура workflow

  1. Обновление импортов компонентов.
  2. Переименование пропсов.
  3. Миграция устаревших компонентов.
  4. Перенос кастомных стилей в sx.
  5. Тестирование изменений и интеграция в CI/CD.

Этот подход обеспечивает системный и безопасный переход между версиями MUI, позволяя сократить ручные исправления и ускорить обновление больших проектов.