Open6

Vite 環境で MUI5 のツリーシェイクを動作させる

RyoRyo

Babel プラグインを使って MUI5 のツリーシェイクをする。

This option provides the best user experience and developer experience:

UX: The Babel plugin enables top-level tree-shaking even if your bundler doesn't support it.
DX: The Babel plugin makes startup time in dev mode as fast as Option 1.
DX: This syntax reduces the duplication of code, requiring only a single import for multiple modules. Overall, the code is easier to read, and you are less likely to make a mistake when importing a new module.

このオプションは、最高のユーザーエクスペリエンスと開発者エクスペリエンスを提供します。

UX: Babel プラグインは、バンドルがサポートしていない場合でも、トップレベルのツリーシェイクを可能にします。
DX: Babel プラグインは、開発モードでのスタートアップ時間をオプション 1 と同じくらい速くします。
DX: この構文はコードの重複を減らし、複数のモジュールに対して1つのインポートで済みます。全体として、コードが読みやすくなり、新しいモジュールをインポートする際にミスをする可能性が低くなります。

https://mui.com/material-ui/guides/minimizing-bundle-size/#option-two-use-a-babel-plugin

RyoRyo

vite.config.ts を以下のようにした。

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react({
    babel: {
      plugins: [
        [
          'babel-plugin-import',
          {
            libraryName: '@mui/material',
            libraryDirectory: '',
            camel2DashComponentName: false,
          },
          'core',
        ],
        [
          'babel-plugin-import',
          {
            libraryName: '@mui/icons-material',
            libraryDirectory: '',
            camel2DashComponentName: false,
          },
          'icons',
        ],
      ]
    }
  })],
  server: {
    host: true,
  }
})
RyoRyo
App.tsx
import {
  AppBar,
  Box,
  Toolbar,
  Typography,
  Button,
  IconButton,
} from '@mui/material';
import {
  Menu as MenuIcon
} from '@mui/icons-material';

export default function ButtonAppBar() {
  return (
    <Box sx={{ flexGrow: 1 }}>
      <AppBar position="static">
        <Toolbar>
          <IconButton
            size="large"
            edge="start"
            color="inherit"
            aria-label="menu"
            sx={{ mr: 2 }}
          >
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
            News
          </Typography>
          <Button color="inherit">Login</Button>
        </Toolbar>
      </AppBar>
    </Box>
  );
}
RyoRyo

いざ、npm run dev

しかし、ローディングが死ぬほど遅い。

10:20:24 AM [vite] ✨ new dependencies optimized: @mui/material/AppBar/AppBar.js, @mui/material/Box/Box.js, @mui/material/Toolbar/Toolbar.js, @mui/material/Typography/Typography.js, @mui/material/IconButton/IconButton.js, ...and 1 more

と出てる。

何か関係しているのだろうか。

RyoRyo

Development bundles can contain the full library which can lead to slower startup times. This is especially noticeable if you use named imports from @mui/icons-material, which can be up to six times slower than the default import. For example, between the following two imports, the first (named) can be significantly slower than the second (default):

// 🐌 Named
import { Delete } from '@mui/icons-material';
// 🚀 Default
import Delete from '@mui/icons-material/Delete';

開発用バンドルには完全なライブラリが含まれているため、起動時間が遅くなる可能性があります。特に、@mui/icons-material から名前付きでインポートする場合、デフォルトのインポートよりも最大で6倍遅くなることがあります。例えば、次の2つのインポートでは、最初のインポート(名前付き)は2番目のインポート(デフォルト)よりも大幅に遅くなることがあります。

https://mui.com/material-ui/guides/minimizing-bundle-size/#development-environment

って書かれてるし、ツリーシェイキングが利用できてなさそうだな。