idea2020代码el组件红色波浪线_面试三板斧 代码分割(下)

1d7b7cf8c5356dbf34c425a9c4cac284.png

背景

本文接上两篇:

「 面试三板斧 」之 代码分割(上)

「 面试三板斧 」之 代码分割(中)

在上两篇文章中, 我们了解了 splitChunks 三个字段的含义。 

分析了每个字段对应的行为,最后了解了分包的原理

今天是实践篇。

看看如何修改短短几行配置, 就达到了数百毫秒的优化效果。

正文

我的这个项目, 迭代一年多了, 中间打包配置也没没怎么改过, 毕竟也没什么问题, 速度也还可以。

刚好最近要搞优化,就顺带看了看。

不分析不知道, 这一分析, 很快啊!

马上就看出了问题。

看包分析结果:

b243fe2bf0973b2cfbec3c5be03d7e31.png

脑海里瞬间闪过一张图:

960368e4d39e17f83dc77aa14cfb1ae6.png

几乎所有的三方依赖都打在了一起, 写好的页面按路由加载也都打到了一起...

 简直辣眼睛...

于是就去看了一下代码配置:

修正前

原始配置:


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

包分析:

b243fe2bf0973b2cfbec3c5be03d7e31.png

加载时间以及入口文件初始加载的脚本文件:

82930f212bf079e39eceed4762f72fb5.png

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

9395e188f4786904647180ceff3c9b68.png

几乎没有什么变化, 一时间, 开始怀疑是不是受了其他配置的影响。。。

就去仔细去找了一下, 果然:

02bac363ec6956d0491eda3eb35e3042.png

5c151c615872390a35a0ef45a82ddb53.png啊这。。。。 我倒要看看是谁:

4e6a4525044809f31ad71b37f3abdeeb.png

算了算了。。。

‍‍‍然后速度修改了配置。‍‍‍

c2dbc05fc9e9819b72ef5abff58eaaff.png

修正后:

  optimization: {
    runtimeChunk: {
      name: 'manifest',
    },
    splitChunks: {
      chunks: 'all',
      minSize: 30000,
      minChunks: 1,
      maxAsyncRequests: 30,
      maxInitialRequests: 30,
      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,
        },
      },
    },
  },

很快啊!  

马上就有了效果:

012c48592aab28e07ce97193d035ad76.png

c16250e2dddeb9def1c50187ef44937d.png

f8086bf1136b3d4c1f8d7252f2f96c8e.png

chunks: async

入口文件初始加载的脚本:

6ef5d095bd750e2e9c6fe577228828e3.png

8a2467f4e9e18d5a6345349edb437c4d.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 基于组件的分割

打包的情况也会不同, 对比如下两幅图:

2e3b6096d98cbc567530dcbde98fc634.png

和:

1d7b7cf8c5356dbf34c425a9c4cac284.png

实际的场景中, 不会严格的区分这两种, 可以一起用。

比如, 一般情况下, 一个页面就是一个模块, 它的子页面, 也是一个模块, 而这两者是分开的。

也就是更贴近这个模型:

fc06bc903f992d0eb3b97d0ef2a05fb9.png当然一些特殊的场景下, 也可以对某些功能组件去分割。

比如播放器组件, 代码高亮组件等。

这个时候的组件, 会单独成包, 使用的时候才去加载。

当然也有一些别的策略, 比如:

  1. 把一些基础包, 不常变化的, 单独打包, 提高缓存命中率。
  2. 字体等资源拿出去, 走CDN。
  3. 国际化资源做成线加载, 不要一起打包,减少总体积。
  4. 图片自动压缩等。

这其中有很多细节, 本篇就不过多介绍, 后续的文章中会有涉及。

总结

具体, 还是要根据不同的场景,选择不同的打包策略, 来达到最有效果。

webpack 也提供了详细的文档:

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

实际用到的时候可以去看看。

内容就这么多,希望对大家有所启发。

关注我   如果你觉得这篇内容对你挺有启发,可以:
  1. 点个「在看」,让更多的人也能看到这篇内容。

  2. 关注公众号「前端e进阶」,掌握前端面试重难点,公众号后台回复「加群」和小伙伴们畅聊技术。

    e586131816b0dd1f62c07aa4b9668780.png

更多精彩:

聊聊 ESM、Bundleless 、Vite 、Snowpack

记一次 「 无限列表 」滚动优化

「 面试三板斧 」之 代码分割(上)

「 面试三板斧 」之缓存 (上)

「 面试三板斧 」之缓存 (下)

「 面试三板斧 」之 HTTP (上)

「 面试三板斧 」之 HTTP (下)

「 面试三板斧 」之  this

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值