Chakra UI のバンドルサイズを削る方法 2023/01版
Chakra UI のバンドルサイズが大きくて大変なので、現時点(v2.4.9)での削減方法を紹介します。
必要なコンポーネントのみを宣言する
@chakra-ui/react
がエクスポートする ChakraProvider
は、全てのコンポーネントのテーマを含んでしまっています。逆に、コンポーネントのテーマを全く含まない ChakraBaseProvider
が用意されているため、これを使います。
まず、extendBaseTheme
を用いて必要なコンポーネントのみを含めたテーマを作ります。
それを ChakraBaseProvider
に渡すことで、テーマを適用します。
import { FC } from "react";
import { ChakraBaseProvider, extendBaseTheme, Box, Button, Checkbox, Tag } from "@chakra-ui/react";
import { Button as ButtonTheme, Checkbox as CheckboxTheme } from "@chakra-ui/theme/components";
const theme = extendBaseTheme({
components: {
Button: ButtonTheme,
Checkbox: CheckboxTheme,
},
});
const App: FC = () => {
return (
<ChakraBaseProvider theme={theme}>
<Box>
<Button>This is styled!</Button>
<Checkbox>This is also styled!</Checkbox>
<Tag>This is NOT styled</Tag>
</Box>
</ChakraBaseProvider>
);
};
extendBaseTheme
に渡していないコンポーネントはスタイルがつかないので注意してください。
Framer Motion に依存するコンポーネントを使わない
アニメーションライブラリである Framer Motion は、めちゃめちゃサイズがでかいので出来るだけバンドルしたくありません。v2.4.9 時点では、以下のコンポーネントが Framer Motion に依存しているため、これらを1つでも使うと一気にバンドルサイズが膨らみます。
- Transition
- Tooltip
- Popover
- Modal
- Menu
- Toast
Toast だけが特殊で、グローバルステートを持つため、ChakraProvider
や ChakraBaseProvider
が依存してしまっています。
これは @chakra-ui/react
で実装されているため、よりプリミティブな @chakra-ui/provider
からエクスポートされる ChakraProvider
を使うことで回避できます。
import { FC } from "react";
-import { ChakraBaseProvider, extendBaseTheme, Box, Button, Checkbox, Tag } from "@chakra-ui/react";
+import { extendBaseTheme, Box, Button, Checkbox, Tag } from "@chakra-ui/react";
+import { ChakraProvider as ChakraBaseProvider } from "@chakra-ui/provider";
import { Button as ButtonTheme, Checkbox as CheckboxTheme } from "@chakra-ui/theme/components";
const theme = extendBaseTheme({
components: {
Button: ButtonTheme,
Checkbox: CheckboxTheme,
},
});
const App: FC = () => {
return (
<ChakraBaseProvider theme={theme}>
<Box>
<Button>This is styled!</Button>
<Checkbox>This is also styled!</Checkbox>
<Tag>This is NOT styled</Tag>
</Box>
</ChakraBaseProvider>
);
};
Rollup や Vite を使わない
Chakra UI の内部コードでは再エクスポートを多用しています。
そして Rollup や Vite では再エクスポートにおける副作用判定にバグがあるらしく、うまく Tree Shaking が効かない場合があります。
これが治るまでは webpack を使うのが無難でしょう。他のバンドラは試してないのでわかりません。
おわりに
前述のバグのように、様々な外部要因で結果が変わりうるので、webpack-bundle-analyzer などで逐一チェックしながら最適化してください。
また、v3 で Breaking Change を伴う大きな改善を予定しているらしいので、ひとまずはこれで凌ぎましょう。
Discussion