最小化套件大小
了解更多關於您可以利用哪些工具來減少套件大小。
套件大小很重要
Material UI 的維護者非常重視套件大小。每次提交都會針對每個套件和這些套件的關鍵部分進行大小快照。結合 dangerJS,我們可以檢查每個 Pull Request 上的詳細套件大小變更。
何時以及如何使用 tree shaking?
Tree shaking Material UI 在現代框架中開箱即用。Material UI 在頂層 @mui
引入中公開其完整的 API。如果您使用 ES6 模組和支援 tree shaking 的打包工具 (webpack
>= 2.x、帶有 flag 的 parcel
),您可以安全地使用具名引入,並且仍然可以自動獲得最佳化的套件大小
import { Button, TextField } from '@mui/material';
開發環境
開發套件可能包含完整的程式庫,這可能會導致啟動時間變慢。如果您從 @mui/icons-material
使用具名引入,這會特別明顯,這可能會比預設引入慢達六倍。例如,在以下兩個引入之間,第一個(具名)可能比第二個(預設)慢得多
// 🐌 Named
import { Delete } from '@mui/icons-material';
// 🚀 Default
import Delete from '@mui/icons-material/Delete';
如果這對您來說是個問題,您有兩個選項
選項一:使用路徑引入
您可以使用路徑引入來避免拉入未使用的模組。例如,使用
// 🚀 Fast
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
而不是頂層引入(沒有 Babel 外掛程式)
import { Button, TextField } from '@mui/material';
這是我們在所有範例中記錄的選項,因為它不需要任何設定。建議正在擴展組件的程式庫作者使用此選項。前往選項 2 以了解產生最佳 DX 和 UX 的方法。
雖然以這種方式直接引入不會使用 @mui/material
的主檔案中的導出,但此檔案可以作為方便的參考,了解哪些模組是公開的。
請注意,我們僅支援第一層和第二層引入。任何更深層次的引入都被視為私有,並可能導致問題,例如套件中的模組重複。
// ✅ OK
import { Add as AddIcon } from '@mui/icons-material';
import { Tabs } from '@mui/material';
// ^^^^^^^^ 1st or top-level
// ✅ OK
import AddIcon from '@mui/icons-material/Add';
import Tabs from '@mui/material/Tabs';
// ^^^^ 2nd level
// ❌ NOT OK
import TabIndicator from '@mui/material/Tabs/TabIndicator';
// ^^^^^^^^^^^^ 3rd level
如果您使用 ESLint,您可以使用 no-restricted-imports
規則捕獲有問題的引入。以下 .eslintrc
設定將突出顯示來自 @mui
套件的有問題引入
{
"rules": {
"no-restricted-imports": [
"error",
{
"patterns": ["@mui/*/*/*"]
}
]
}
}
選項二:使用 Babel 外掛程式
此選項提供最佳的使用者體驗和開發者體驗,除非您使用Next.js 13.5 或更高版本,在這些版本中,此最佳化會透過 Next.js 中的 optimizePackageImports
選項自動應用。在這種情況下,使用 Babel 外掛程式是不必要的。
- 使用者體驗 (UX):即使您的打包工具不支援,Babel 外掛程式也能啟用頂層 tree shaking。
- 開發者體驗 (DX):Babel 外掛程式使開發模式下的啟動時間與選項 1 一樣快。
- 開發者體驗 (DX):此語法減少了程式碼的重複,僅需要單次引入即可引入多個模組。總體而言,程式碼更易於閱讀,並且在引入新模組時,您不太可能犯錯。
import { Button, TextField } from '@mui/material';
但是,您需要正確應用以下步驟。
1. 設定 Babel
使用 babel-plugin-import 以及以下設定
yarn add -D babel-plugin-import
在您的專案根目錄中建立一個 .babelrc.js
檔案
const plugins = [
[
'babel-plugin-import',
{
libraryName: '@mui/material',
libraryDirectory: '',
camel2DashComponentName: false,
},
'core',
],
[
'babel-plugin-import',
{
libraryName: '@mui/icons-material',
libraryDirectory: '',
camel2DashComponentName: false,
},
'icons',
],
];
module.exports = { plugins };
如果您使用 Create React App,您將需要使用幾個專案,讓您可以使用 .babelrc
設定,而無需 eject。
yarn add -D react-app-rewired customize-cra
在根目錄中建立一個 config-overrides.js
檔案
/* config-overrides.js */
/* eslint-disable react-hooks/rules-of-hooks */
const { useBabelRc, override } = require('customize-cra');
module.exports = override(useBabelRc());
如果您願意,可以使用此設定,透過 config-overrides.js
而不是 .babelrc
來設定 babel-plugin-import
。
修改您的 package.json
命令
"scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test",
+ "start": "react-app-rewired start",
+ "build": "react-app-rewired build",
+ "test": "react-app-rewired test",
"eject": "react-scripts eject"
}
享受顯著更快的啟動時間。
2. 轉換您的所有引入
最後,您可以使用此 top-level-imports codemod 將您現有的程式碼庫轉換為此選項。它將執行以下差異
-import Button from '@mui/material/Button';
-import TextField from '@mui/material/TextField';
+import { Button, TextField } from '@mui/material';
可用的套件
預設套件
在 npm 上發布的套件使用 Babel 進行轉譯,並針對支援的平台進行效能最佳化。
現代化套件也可用。
如何使用自訂套件?
使用這些套件的好方法是設定打包工具導出條件,例如使用 webpack 的 resolve.conditionNames
或 vite 的 resolve.conditions
// webpack.config.js
{
resolve: {
conditionNames: ['mui-modern', '...'],
}
}
// vite.config.js
{
resolve: {
conditions: ['mui-modern', 'module', 'browser', 'development|production']
}
}