本文接上篇: javascript
上文中, 咱們瞭解了 chunks 三個字段的含義, 以及每一個字段對應的行爲。css
今天是實踐篇。html
修改短短几行配置, 就達到了數百毫秒的優化效果。java
個人這個項目, 迭代一年多了, 中間打包配置也沒沒怎麼改過, 畢竟也沒什麼問題, 速度也還能夠。node
恰好最近老闆要搞指標, 讓每一個項目組分析性能數據, 給優化方案,作性能優化。react
不分析不知道, 一分析, 很快啊, 立刻就看出了問題, 看包分析結果:webpack
腦海裏瞬間閃過一張圖:web
幾乎全部的三方依賴都打在了一塊兒, 寫好的頁面按路由加載也都打到了一塊兒, 簡直辣眼睛...性能優化
因而就去看了一下代碼配置:antd
原始配置:
const OnBoard = React.lazy(() => import('@/pages/onboard')); const menuData = MenuItemTypes[] = [ { title: 'onboard', path: '/onboard', meta: { showInMenu: false }, children: [ { component: OnBoard, // ... }, // ... ] }, // ... ];
const AppRouter = () => { // ... const { el, routes } = getRoutes(menuData); // ... return ( <BasicLayout {...matchedRoute.meta}> <Suspense fallback={<Spin />}> <Route path="/" exact component={MyDashboard} /> {el} </Suspense> // ... </BasicLayout> ); };
const App: React.FC<> = () => { // ... return <AppRouter />; }; const AppContainer = () => ( <Router history={history}> <Provider store={store}> <Locale> <App /> </Locale> </Provider> </Router> );
看起來沒什麼問題。
看了一下 webpack 配置:
optimization: { splitChunks: { chunks: 'all', minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, cacheGroups: { vendor: { test: /[\\/]node_modules/, enforce: true, priority: 5, }, antd: { test: /[\\/]node_modules[\\/]antd[\\/]/, priority: 10, }, antdIcons: { test: /[\\/]node_modules[\\/]@ant-design[\\/]/, priority: 15, }, styles: { test: /\.(scss|css)$/, minChunks: 1, reuseExistingChunk: true, enforce: true, priority: 20, }, }, }, },
看起來貌似也沒什麼問題。。。
build 以後 html 中的腳本, 乍一看好像也沒毛病...
<script type="text/javascript" src="/main.75a8d9f8.js"></script> <script type="text/javascript" src="/chunk.styles~main.eaa8f358.js"></script> <script type="text/javascript" src="/chunk.antdIcons~main.6ee35491.js"></script> <script type="text/javascript" src="/chunk.vendor~main.aa82abbc.js"></script> <script type="text/javascript" src="/chunk.main.db1b67a1.js"></script>
這種狀況下, 修改 chunks
配置的對比:
chunks: all
包分析:
加載時間以及入口文件初始加載的腳本文件:
chunks: async
:<script type="text/javascript" src="/main.64245819.js"></script> <script type="text/javascript" src="/chunk.main.d6a
幾乎沒有什麼變化, 一時間, 開始懷疑是否是受了其餘配置的影響,就去仔細去找了一下, 果真:
速度修改了配置。
chunks:all
optimization: { runtimeChunk: { name: 'manifest', }, splitChunks: { chunks: 'all', minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, cacheGroups: { vendor: { test: /[\\/]node_modules/, enforce: true, priority: 5, }, antd: { test: /[\\/]node_modules[\\/]antd[\\/]/, priority: 15, enforce: true, }, antdIcons: { test: /[\\/]node_modules[\\/]@ant-design[\\/]/, priority: 15, enforce: true, }, antdV: { test: /[\\/]node_modules[\\/]@antv[\\/]/, priority: 30, enforce: true, }, bizcharts: { test: /[\\/]node_modules[\\/]bizcharts[\\/]/, priority: 20, enforce: true, }, dplayer: { test: /[\\/]node_modules[\\/]dplayer[\\/]/, priority: 25, enforce: true, }, styles: { test: /\.(scss|css|less})$/, minChunks: 1, reuseExistingChunk: true, enforce: true, priority: 20, }, 'react-dom': { test: /[\\/]node_modules[\\/]react-dom[\\/]/, priority: 25, enforce: true, }, 'rc-components': { test: /([\\/]node_modules[\\/]rc-[a-zA-Z-]+[\\/])/, priority: 25, enforce: true, }, }, }, },
很快啊, 立刻就有了變化:
chunks: async
入口文件初始加載的腳本:
<script type="text/javascript" src="/main.572fc9fe.js"></script> <script type="text/javascript" src="/chunk.main.8c0dcc22.js"></script>
除了入口腳本數量的變化, 整體積, 加載時長, 幾乎沒有變化。
腳本數量的不一樣:
all
: 8async
: 4區別就是, 大文件的體積不一樣, 對這個大文件的加載時間有影響。
回頭看, 這是一個 maxChunks
配置錯誤引起的血案。
修正配置以後, 立竿見影。
根據你的狀況, 能夠選擇更適合的打包策略。
all
的優點在於, 能共享代碼。
Providing
all
can be particularly powerful, because it means that chunks can be shared even between async and non-async chunks.
選擇這個模式, 若是你用的協議是h2, 並行下載,可能有比較好的效果。
async
會幫你合併一些包,但產生的請求也會減小。
須要根據實際狀況作測試, 選擇最適合的打包策略。
還有一種分割策略:
基於路由的分割 vs 基於組件的分割
打包的狀況也會不一樣, 對好比下兩幅圖:
和:
實際的場景中, 不會嚴格的區分這兩種, 能夠一塊兒用。
好比, 通常狀況下, 一個頁面就是一個模塊, 它的子頁面, 也是一個模塊, 而這二者是分開的。
也就是更貼近這個模型:
固然一些特殊的場景下, 也能夠對某些功能組件去分割, 好比播放器組件, 代碼塊組件等。
這個時候的組件, 會單獨成包, 使用的時候纔去加載。
這是另外一個話題了, 也有不少細節在裏面, 本篇就不過多介紹。
具體, 仍是要根據不一樣的場景,選擇不一樣的打包策略, 來達到最有效果。
webpack 也提供了詳細的文檔:
https://webpack.docschina.org...
實際用到的時候能夠去看看。
內容就這麼多,但願對你們有所啓發。
謝謝。