女王控的博客

Webpack升级优化——记一次产品端升级

接上文 Webpack 配置笔记

分包策略

在分支 feature/optimize_webpack 上启动 yarn analyze 脚本,得到分包策略如下:

分包策略

首屏加载对比

原始首屏加载

原始首屏加载大小

升级后加载

升级后加载大小

分包优化步骤

echarts 只提取需要的包

app\components\ECharts\component.js

js 复制代码
import echarts from 'echarts/lib/echarts';
import 'echarts/lib/chart/bar';
import 'echarts/lib/chart/line';
import 'echarts/lib/chart/pie';

import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/legendScroll';

immutable 指向同一份,避免 draft 与 antd 重复打包

internals/webpack/webpack.base.babel.js

js 复制代码
'immutable': path.resolve(process.cwd(), 'node_modules/immutable'),

分大模块改写法

根据路由来分

这里原来的路由引用模块已经是 import().then() 形式的了,所以我在 webpack 里的 splitChunks 加了如下策略

internals/webpack/webpack.prod.babel.js

js 复制代码
splitChunks: {
  chunks: 'all', // 不管文件是动态还是非动态载入,统一将文件分离。当页面首次载入会引入所有的包
  maxInitialRequests: 10, // 最大初始化请求数
  minSize: 0, // 默认30000,为了不合并 chunk
  cacheGroups: {
    vendor: {
      test: /[\\/]node_modules[\\/]/,
      name(module) {
        const packageName = module.context.match(
          /[\\/]node_modules[\\/](.*?)([\\/]|$)/,
        )[1];
        return `npm.${packageName.replace('@', '')}`; // 提取各个第三方组件,只在需要时提取
      },
    },
  },
},

经实验,可以看到各个页面只加载所需的包

根据组件来分

对其中比较大的组件进行了懒加载处理,react-player/draft/echarts

其中有一个比较大的问题就是懒加载组件引用不到 ref 的问题,经多次实验,更改写法如下

js{16-23} 复制代码
import React from 'react';
import Loadable from 'react-loadable';

const LoaderCache = new Map();
export default function loadComponent(loader, options) {
  let component = LoaderCache.get(loader);
  if (!component) {
    component = Loadable({
      loader,
      loading: (props) => {
        if (props.error) {
          // eslint-disable-line
          console.error('[chunk loader]', props.error); // eslint-disable-line
        }
        return <div />;
      },      render: (loaded, props) => {        const Component = loaded.default;        const { withRef, ...rest } = props; // eslint-disable-line        return (          <Component            ref={(r) => {              withRef && withRef(r);            }}
            {...rest}
          />
        );
      },
      ...options
    });
    LoaderCache.set(loader, component);
    // component.preload();
  }
  return component;
}

用法:

app\components\GraphHintTextArea\index.js

js 复制代码
import loadComponent from 'utils/loader';

export default loadComponent(() => import(/* webpackChunkName: "c-graph-hint-text-area" */ './component'), null);
jsx 复制代码
<GraphHintTextArea
  withRef={(r) => {
    this.graphHintTextArea = r;
  }}
/>

antd 只加载需要的 icon

internals/webpack/webpack.base.babel.js

js 复制代码
'@ant-design/icons/lib/dist$': path.resolve('app/icons'),

app/icons/index.js

js 复制代码
// fill
export { default as ExclamationCircleFill } from '@ant-design/icons/lib/fill/ExclamationCircleFill';
// outline
export { default as QuestionCircleOutline } from '@ant-design/icons/lib/outline/QuestionCircleOutline';
// twotone
export { default as ProfileTwoTone } from '@ant-design/icons/lib/twotone/ProfileTwoTone';

评论

阅读上一篇

React生命周期入门学习
2019-09-19 15:29:20

阅读下一篇

正则表达式入门学习
2019-08-02 10:36:31
0%