ロゴWeb開発ブログ

Next.jsでMaterial UIのコンポーネントやアイコンをまとめてimportできるようにする

更新
作成
  • 使用したバージョン
  • Next.js 13.4.12
  • @mui/material 5.14.2

Next.jsでMaterial UIのコンポーネントを使うために次のようにインポートしてみる。


import { Paper, Typography } from "@mui/material";

これでビルドすると生成されたバンドルファイルのサイズが大きくなり、ビルド時間も長くなってしまう。

bundle-analyzerでファイルを可視化してみると、使われていないMUIコンポーネントまでもバンドルされて巨大なファイルが生成されていた。
バンドル1

解決策 その1

コンポーネントごとに個別にインポートする。


import Paper from "@mui/material/Paper";
import Typography from "@mui/material/Typography";

これにより必要なモジュールだけがバンドルされ、ファイルサイズもだいぶ小さくなった。
バンドル2

でも、これだとひとつひとつimportを書くのは面倒だし、VSCodeの自動でまとめてimportしてくれる機能を使うと
import { Paper, Typography } from "@mui/material" のような書き方になってしまう。

大量のimportが並ぶのも可読性が低くなるしなにかと不便。

解決策 その2

next.config.jsにmodularizeImportsを設定する。


const nextConfig = {
...
modularizeImports: {
'@mui/material': {
transform: '@mui/material/{{member}}',
},
'@mui/icons-material': {
transform: '@mui/icons-material/{{member}}',
},
}
};

これにより、


import { Paper, Typography } from "@mui/material";

と書いたものが、ビルド時に


import Paper from "@mui/material/Paper";
import Typography from "@mui/material/Typography";

へと自動で変換してくれる。

生成されたファイルサイズも上記と同じだった。
バンドル3

注意点としては、まとめてインポートできるのは基本的にコンポーネントとアイコンだけである。

たとえば次のようなimportをしたとする。


import { css } from "@mui/material";

これは、


import css from "@mui/material/css";

と変換されるがそんなモジュールは存在しないのでエラーとなる。

この場合は個別にimportしなければならない。


import { css } from "@mui/material/styles";

Next.js 14.0.4では解決策その2は使用できない問題

Next.jsのバージョンを14.0.4にアップグレードして解決策その2を使ったところ、次のエラーが出てビルドできない問題が発生した。


Error: Element type is invalid. Received a promise that resolves to: undefined. Lazy element type must resolve to a class or function.

issuesにも同様の問題があがっていた。
[material-ui] Not working after upgrading Next.js to 14.0.4. Error: Element type is invalid.

Next.js 14.0.3にダウングレードするか、解決策その1に変更すればエラーは出なくなる。