项目体积优化
原始: parsed JS 体积 42M.
dist文件夹体积 56.5M
删除无用包
工具: npm install -g depcheck
命令: depcheck
删除
红色字体表示不可删除。
灰色字体表示暂时保留
划线字体表示已经删除。
dependencies
npm uninstall @antv/l7-react @re-editor/core @re-editor/toolbar-antd @types/lodash.debounce lodash.debounce braft-editor @types/numeral bizcharts-plugin-slider gg-editor lodash-decorators mockjs numeral nzh re-editor react-fittext
@antv/data-set@0.11.0
@antv/l7-react@2.1.9
@re-editor/core@0.5.8
@re-editor/toolbar-antd@0.5.8
@types/lodash.debounce@4.0.6
@types/lodash.isequal@4.5.5
@types/numeral@0.0.28
bizcharts-plugin-slider@2.1.1-beta.1
braft-editor@2.3.9
dva@2.4.0
gg-editor@2.0.2
lodash-decorators@6.0.0
lodash.debounce@4.0.8
lodash.isequal@4.5.0
mockjs@1.0.1-beta3
numeral@2.0.6
nzh@1.0.3
re-editor@0.5.8
react-fittext@1.0.0
devDependencies
npm uninstall @types/history @types/jest @types/react-helmet chalk enzyme husky jsdom-global pro-download
@types/history@4.7.2
@types/jest@26.0.0
@types/react-helmet@5.0.13
@umijs/plugin-blocks@2.0.5
@umijs/preset-ant-design-pro@1.2.0
@umijs/preset-react@1.4.8
@umijs/preset-ui@2.0.9
chalk@4.0.0
enzyme@3.11.0
husky@4.0.7
jsdom-global@3.0.2
pro-download@1.0.1
暂时保留
@types/history@4.7.2
@types/jest@26.0.0
@types/react-helmet@5.0.13
优化打包方式
提取公共模块、多核心打包、抽离css等
提取公共模块可以通过使用SplitChunksPlugin来实现。这个插件可以将公共的依赖模块提取出来,形成单独的文件,以便于浏览器进行缓存和复用。
// https://umijs.org/config/
import { defineConfig } from 'umi';
import defaultSettings from './defaultSettings';
import pageRoutes from './router.config';
import proxy from './proxy';
const { REACT_APP_ENV, HIDEHTTPS, NODE_ENV } = process.env;
const HappyPack = require('happypack');
const happyThreadPool = HappyPack.ThreadPool({
size: require('os').cpus().length,
});
export default defineConfig({
nodeModulesTransform: { // 加速打包
type: 'none',
exclude: [],
},
hash: true,
antd: {},
dva: {
hmr: true,
},
define: {
showHttps: HIDEHTTPS ? false : true,
},
mock: false,
locale: {
default: 'zh-CN',
antd: true,
baseNavigator: false,
},
dynamicImport: {
loading: '@/components/PageLoading/index',
},
targets: {
ie: 11,
},
routes: pageRoutes,
theme: {
'primary-color': defaultSettings.primaryColor,
},
// @ts-ignore
title: false,
ignoreMomentLocale: true,
proxy: proxy[REACT_APP_ENV || 'dev'],
manifest: {
basePath: '/',
},
chunks: NODE_ENV === 'production' ? ['vendors', 'umi'] : undefined,
chainWebpack: function (config, { webpack, env }) {
// 加快编译
config.cache({
type: 'filesystem',
allowCollectingMemory: true,
buildDependencies: {
config: [__filename],
},
});
// 利用多线程,加快js打包
config.plugin('HappyPack').use(HappyPack, [{ // 使用 HappyPack 插件
id: 'js',
loaders: ['babel-loader'], // 使用 babel-loader 来处理 JavaScript 文件
threadPool: happyThreadPool, // 指定使用一个名为 happyThreadPool 的线程池来处理多线程任务
}]);
// 提取公共模块,减小体积
config.merge({
optimization: {
minimize: env === 'production',
splitChunks: {
chunks: 'all', // async异步代码分割 initial同步代码分割 all同步异步分割都开启
minSize: 20000, // 表示当模块的大小超过20,000字节时,才会考虑将其拆分为公共模块
minChunks: 2, // 指定一个模块至少被引用两次才会被提取为公共模块
automaticNameDelimiter: '.',
cacheGroups: {
vendor: {
name: 'vendors',
test({ resource }) {
return /[\/]node_modules[\/]/.test(resource);
},
priority: 10,
},
// 将css打包到一个css文件里
styles: {
name: 'styles',
test: /.(css|less)$/,
chunks: 'async',
minChunks: 1,
minSize: 0,
}
},
},
}
});
},
// 加快编译速度
devtool: NODE_ENV !== 'production' ? 'eval' : false,
// 暂时还不能用,有bug
// mfsu: {
// production: { output: '.mfsu-production' }
// },
esbuild: {}, // 增加压缩速度,可能有bug
// webpack5: {}
});
打包时间根据当时机器可用硬件资源不同而不同,只做参考。
esbuild压缩:
同样 npm run analyze, 时间从 280s -> (150s - 100s)
打包时间 290s -> (150s - 70s) 提速50%以上。
打包后js 体积(parsed) 从 42M -> 5.6M,减少87%。
打包后 css文件体积 减少 9.92M -> 0.62M, 减少94%。
dist总体体积: 56.5 M -> 8.7M , 减少85%。
压缩器选择
esbuild vs terserOptions vs mfsu
初始采用了mfsu,但是有bug,无法获取正确文件,项目无法启动。具体原因还没细查。
使用esbuild时,项目js打包体积 5.6M。
使用 terser 时, js打包体积进一步压缩。 5.6M -> 4.8M。
Terser压缩
打包的js,42M -> 4.8M,减少89%
dist总体积, 56.5M -> 7.8M,减少87%
如果打包结果有问题,且无法解决,尝试切换esbuild压缩。
经测试发现,Terser压缩后有点问题,build后react会报错。
EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, TB.
可能是配置项设置设置的原因。目前使用esbuild打包。
{
// esbuild: {}, // 增加压缩速度,可能有bug.如遇bug无法解决。尝试使用terserOptions压缩
terserOptions: {
parse: {
// parse options
},
compress: {
// compress options
},
mangle: {
// mangle options
properties: {
// mangle property options
}
},
format: {
// format options (can also use `output` for backwards compatibility)
},
sourceMap: {
// source map options
},
ecma: 5, // specify one of: 5, 2015, 2016, etc.
enclose: false, // or specify true, or "args:values"
keep_classnames: false,
keep_fnames: false,
ie8: false,
module: false,
nameCache: null, // or specify a name cache object
safari10: false,
toplevel: false
},
}
大体积包按需加载?
bizcharts 这个打包体积看起来很多,尝试按需加载
bizcharts parsed 体积从 757.3k -> 40.5K, 体积减小95%。
// 过去
// import { Axis, Chart, Geom, Tooltip, AxisProps } from 'bizcharts';
// 现在
import Chart from 'bizcharts/lib/components/Chart';
import Axis from 'bizcharts/lib/components/Axis';
import Geom from 'bizcharts/lib/components/Geom';
import Tooltip from 'bizcharts/lib/components/Tooltip';
import type AxisProps from 'bizcharts/typings'
替换
todo:
用dayjs 替换掉 moment ?
externals
设置哪些模块可以不被打包,通过
export default {
// 配置 external
externals: {
'react': 'window.React',
'react-dom': 'window.ReactDOM',
},
// 引入被 external 库的 scripts
// 区分 development 和 production,使用不同的产物
scripts: process.env.NODE_ENV === 'development' ? [
'https://gw.alipayobjects.com/os/lib/react/16.13.1/umd/react.development.js',
'https://gw.alipayobjects.com/os/lib/react-dom/16.13.1/umd/react-dom.development.js',
] : [
'https://gw.alipayobjects.com/os/lib/react/16.13.1/umd/react.production.min.js',
'https://gw.alipayobjects.com/os/lib/react-dom/16.13.1/umd/react-dom.production.min.js',
],
};
todo:
react、antd、biecharts 这些比较大的包,是否可以使用 externals的方式进行加载?
这个要根据业务具体、部署方式、用户的网络情况来判断。
启动优化
启动速度很慢,需要优化。
wait~