前言
一个umijs项目,打包后发现体积过大,想优化, 看到各种博客上的优化手段是基于webpack的,于是我花了几天把项目转成webpack5的, 优化打包后比原来还大.... 最终还是在原来的umijs基础上进行了优化.
打包分析
umi项目在package.json加一个脚本语句 "analyze": "cross-env ANALYZE=1 umi build", 执行yarn analyze 即可在ANALYZE server上得到依赖包分析图
"scripts": {
"start": "cross-env UMI_ENV=dev umi dev",
"build": "cross-env UMI_ENV=prod umi build",
"analyze": "cross-env ANALYZE=1 umi build",
"postinstall": "umi generate tmp",
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
"test": "umi-test",
"test:coverage": "umi-test --coverage"
},
webpack需要安装 webpack-bundle-analyzer 插件 并在配置文件中配置 new BundleAnalyzerPlugin().
针对性优化(antd echart lodash momentjs)
经过分析发现, antd echart lodash momentjs四个依赖包占的体积最大
antd
umijs对antd组件库有良好支持, 使用插件集@umijs/preset-react或@umijs/plugin-antd整合antds组件库就自动是按需引入, 在webpack下需要使用bebel插件 babel-plugin-import 并在webpack.config.js(这个更靠谱)或babelrc配置
echart
echartc5的按需引入在官网有示例 实例
// 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。
import * as echarts from 'echarts/core';
// 引入柱状图图表,图表后缀都为 Chart
import { BarChart } from 'echarts/charts';
// 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component
import {
TitleComponent,
TooltipComponent,
GridComponent,
DatasetComponent,
DatasetComponentOption,
TransformComponent
} from 'echarts/components';
// 标签自动布局,全局过渡动画等特性
import { LabelLayout, UniversalTransition } from 'echarts/features';
// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
import { CanvasRenderer } from 'echarts/renderers';
// 注册必须的组件
echarts.use([
TitleComponent,
TooltipComponent,
GridComponent,
DatasetComponent,
TransformComponent,
BarChart,
LabelLayout,
UniversalTransition,
CanvasRenderer
]);
// 接下来的使用就跟之前一样,初始化图表,设置配置项
var myChart = echarts.init(document.getElementById('main'));
myChart.setOption({
// ...
});
实测对项目整体打包体积的优化用处不大, 采取了定制echarts.min.js的方式 定制地址
echarts4的体积比echart5小, 页面生成echarts.min.js加入到项目的public文件夹
在document.ejs引入
<script src="<%= context.config.publicPath +'echarts.min.js'%>" > </script>
在.umirc.js添加配置
externals: {
echarts: 'echarts'
},
使用示例: echart组件封装
import React, { useEffect, useState, useRef } from 'react'
import echarts from 'echarts'
const Echarts = (props) => {
const { option } = props
const [chart, setChart] = useState()
const domRef = useRef()
useEffect(() => {
const instance = echarts.init(domRef.current)
const chartResize = () => {
instance.resize()
}
setChart(instance)
window.addEventListener('resize', chartResize)
return () => {
window.removeEventListener('resize', chartResize)
}
}, [])
useEffect(() => {
if (chart) {
chart.setOption(option)
}
}, [option])
return <div ref={domRef} style={{ height: '100%', width: '100%' }} />
}
export default Echarts
lodash
代码中的全部引入改为部分引入
```
import _ from 'lodash'
改为
import { extend, omit, difference } from 'lodash'
```
devDependencies中安装两个插件 babel-plugin-lodash 和 lodash-webpack-plugin
.umirc.js中配置
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin')
export default defineConfig({
...
extraBabelPlugins: ['lodash'],
chainWebpack: (config, { webpack }) => {
if (process.env.NODE_ENV === 'production') { // 生产模式开启
config.plugin('LodashModuleReplacementPlugin').use(
new LodashModuleReplacementPlugin()
); // 压缩lodash
}
},
})
momentjs
moment的体积也是很大,使用webpack.IngorePlugin插件忽略其locale能很好的压缩体积
.umirc.js中配置
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin')
export default defineConfig({
...
extraBabelPlugins: ['lodash'],
chainWebpack: (config, { webpack }) => {
if (process.env.NODE_ENV === 'production') { // 生产模式开启
config.plugin('igncore').use(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/))
config.plugin('LodashModuleReplacementPlugin').use(
new LodashModuleReplacementPlugin()
); // 压缩lodash
}
},
})
也可以使用dayjs替换moment, dayjs体积非常小. antd组件库有使用到moment,也需要进行替换 官方文档操作说明