「 面試三板斧 」代碼分割(下)

背景

image.png

本文接上篇: javascript

上文中, 咱們瞭解了 chunks 三個字段的含義, 以及每一個字段對應的行爲。css

今天是實踐篇。html

修改短短几行配置, 就達到了數百毫秒的優化效果。java

正文

個人這個項目, 迭代一年多了, 中間打包配置也沒沒怎麼改過, 畢竟也沒什麼問題, 速度也還能夠。node

恰好最近老闆要搞指標, 讓每一個項目組分析性能數據, 給優化方案,作性能優化。react

不分析不知道, 一分析, 很快啊, 立刻就看出了問題, 看包分析結果:webpack

image.png

腦海裏瞬間閃過一張圖: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

包分析:
image.png

加載時間以及入口文件初始加載的腳本文件:

image.png

chunks: async:

<script type="text/javascript" src="/main.64245819.js"></script>
  <script type="text/javascript" src="/chunk.main.d6a

image.png

幾乎沒有什麼變化, 一時間, 開始懷疑是否是受了其餘配置的影響,就去仔細去找了一下, 果真:

image.png

image.png

速度修改了配置。

image.png

修正後:

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,
        },
      },
    },
  },

很快啊, 立刻就有了變化:

image.png

image.png

image.png

chunks: async

入口文件初始加載的腳本:

image.png

<script type="text/javascript" src="/main.572fc9fe.js"></script>
  <script type="text/javascript" src="/chunk.main.8c0dcc22.js"></script>

image.png

image.png

除了入口腳本數量的變化, 整體積, 加載時長, 幾乎沒有變化。

腳本數量的不一樣:

  • all: 8
  • async: 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 基於組件的分割

打包的狀況也會不一樣, 對好比下兩幅圖:

image.png

和:

image.png

實際的場景中, 不會嚴格的區分這兩種, 能夠一塊兒用。

好比, 通常狀況下, 一個頁面就是一個模塊, 它的子頁面, 也是一個模塊, 而這二者是分開的。

也就是更貼近這個模型:

image.png

固然一些特殊的場景下, 也能夠對某些功能組件去分割, 好比播放器組件, 代碼塊組件等。
這個時候的組件, 會單獨成包, 使用的時候纔去加載。

這是另外一個話題了, 也有不少細節在裏面, 本篇就不過多介紹。

總結

具體, 仍是要根據不一樣的場景,選擇不一樣的打包策略, 來達到最有效果。

webpack 也提供了詳細的文檔:

https://webpack.docschina.org...

實際用到的時候能夠去看看。

內容就這麼多,但願對你們有所啓發。

謝謝。

相關文章
相關標籤/搜索