mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.92k stars 32.27k forks source link

Add support for the `top-level-imports` codemod for MUI v5 #31181

Closed greengiraffe closed 2 years ago

greengiraffe commented 2 years ago

Duplicates

Latest version

Summary 💡

Currently the top-level-imports codemod does not support MUI v5, while the current docs still link to it. The top-level-imports codemod should support MUI v5.

Examples 🌈

I have tried running the v4 codemod on a v5 codebase without success. I also tried setting two jscodeshift args --importModule and --targetModule to @mui/material, like this:

npx @mui/codemod v4.0.0/top-level-imports myfile.tsx --jscodeshift='--importModule="@mui/material" --targetModule="@mui/material"'

This results in:

Error: Cannot find module '"@mui/material" --targetModule="@mui/material"'

The error message appears as if the two jscodeshift args were concatenated to one arg. This may well be an error on my part, so please let me know if this should work. Setting only one of the args like --jscodeshift='--importModule="@mui/material" still results in the same error though: Error: Cannot find module '"@mui/material"'.

I found a related issue (https://github.com/mui/material-ui/issues/30907), but it talks about the babel-plugin-import, not the codemod.

Motivation 🔦

I have a large codebase with several submodule imports per file like this:

import MenuItem from '@mui/material/MenuItem';
import InputLabel from '@mui/material/InputLabel';
import FormControl from '@mui/material/FormControl';
import Select from '@mui/material/Select';

I want to transform these imports into top-level imports like this without having to refactor each file manually:

import { MenuItem, InputLabel, FormControl, Select } from '@mui/material';
mnajdova commented 2 years ago

Yep, we should adjust the top-level-imports to work with the new package names and add it in the v5.0.0 folder. Would be interested in creating a PR?

greengiraffe commented 2 years ago

I created a PR to lay the groundwork but probably need some help/guidance: https://github.com/mui/material-ui/pull/31195

greengiraffe commented 2 years ago

@mnajdova @siriwatknp

Unfortunately the new v5 codemod released in 5.4.4 does not work and results in an error similar to this:

 ERR /sandbox/pages/index.js Transformation error (Cannot find module '@mui/material' Require stack: - /home/sandbox/.npm/_npx/619/lib/node_modules/@mui/codemod/node/v5.0.0/top-level-imports.js - /home/sandbox/.npm/_npx/619/lib/node_modules/@mui/codemod/node_modules/jscodeshift/src/Worker.js)
Error: Cannot find module '@mui/material'
Require stack:
- /home/sandbox/.npm/_npx/619/lib/node_modules/@mui/codemod/node/v5.0.0/top-level-imports.js
All done.

To reproduce:

  1. Visit and then fork (to be able to open a custom console): https://codesandbox.io/s/mui-codemod-top-level-imports-bug-9o2353
  2. Open a new console in your forked sandbox
  3. Run npx @mui/codemod v5.0.0/top-level-imports ./pages

I would love to see a fix for this, but I'm not sure how to do it myself.

siriwatknp commented 2 years ago

@greengiraffe Have you tried it locally?

greengiraffe commented 2 years ago

@siriwatknp Yes, same error.

mnajdova commented 2 years ago

@greengiraffe could you provide the file on which you run the codemod?

greengiraffe commented 2 years ago

@mnajdova The original codebase is private but it's similar to the codesandbox linked above. This is what I expect the codemod to do:

Initial code:

import Button from "@mui/material/Button";
import ButtonGroup from "@mui/material/ButtonGroup";
import { Link } from "@mui/material";

export default function IndexPage() {
  return (
    <div>
      <ButtonGroup>
        <Button variant="outlined">Button 1</Button>
        <Button variant="outlined">Button 2</Button>
      </ButtonGroup>
      <Link>MUI Link</Link>
    </div>
  );
}

Expected output:

import { Button, ButtonGroup, Link } from "@mui/material";

export default function IndexPage() {
  return (
    <div>
      <ButtonGroup>
        <Button variant="outlined">Button 1</Button>
        <Button variant="outlined">Button 2</Button>
      </ButtonGroup>
      <Link>MUI Link</Link>
    </div>
  );
}

but as stated, the codemod returns the error Cannot find module '@mui/material'.

mnajdova commented 2 years ago

Taking a look @greengiraffe

mnajdova commented 2 years ago

@greengiraffe sorry for the delay, had to run on a meeting :D It should be fixed with https://github.com/mui/material-ui/pull/31308 (I've tested locally, but would be great if you can double check). You can fetch that branch, build the @mui/codemod package locally, by going in the folder and running yarn build and then you can test it with:

node D:\workspace\mui\packages\mui-codemod\build\codemod.js v5.0.0\top-level-imports ./src/App.js

You can replace the D:\workspace with your location :)

The alternative is to wait for the build on the branch and test with the packages build on the PR.

greengiraffe commented 2 years ago

@mnajdova great, thanks so much for the fix, will test it and report back tomorrow.

mnajdova commented 2 years ago

You should be able to test using this package: https://pkg.csb.dev/mui/material-ui/commit/8bb44325/@mui/codemod

greengiraffe commented 2 years ago

@mnajdova it works!

jagadeesh93 commented 1 year ago

@greengiraffe Sir if we convert the second level import to top level import it will increase the bundle size right ?