当前位置: 首页 > ops >正文

【ECharts】2. ECharts 性能优化

动态(按需)加载异步子组件

之前说过 ECharts 如何封装,今天来讲一讲 ECharts 如何做性能优化。

对于之前 ECharts 的封装子组件,我们可以使用 component 动态组件的方式进行渲染,并传参。

并且使用 import 动态导入搭配 defineAsyncComponent 实现打包代码分割,import 实现组件按需加载, defineAsyncComponent 实现将这些异步组件单独打包,减小主包的体积。

而且统一封装图表组件,统一管理图表配置 options,可以实现业务数据与图表样式配置分离。

在这里插入图片描述

以下代码均只保留核心代码,已脱敏。

index.vue 中去实现动态渲染:

 <componentclass="w-full":is="echartsComponent"v-if="echartsComponent"v-bind="echartsProps"/>
  // 接收参数const props = defineProps({confgData: {type: Object,required: true,default: () => ({}),},boardData: {type: Object,required: true,default: () => ({}),},// componentKey: {//   type: String,//   required: true,// },});// ...// 所有的图表按需加载const allEcharts = [{type: 'bar',component: defineAsyncComponent(() => import('./BarEcharts/index.vue')),},{type: 'pie',component: defineAsyncComponent(() => import('./PieCharts/index.vue')),},{type: 'line',component: defineAsyncComponent(() => import('./LineCharts/index.vue')),},{type: 'progress',component: defineAsyncComponent(() => import('./Progress/index.vue')),},];// 抛出一个父组件使用该组件修改内部配置的方式const emit = defineEmits(['updates']);// 针对不同图表做不同的参数传递const echartsProps = computed(() => {if (confgData.value?.type === 'bar') {return {xAxisLabels: props.boardData.x_axis_labels,yAxisLabels: props.boardData.y_axis_labels,seriesData: props.boardData.series_data,isHorizontal: props.boardData?.y_axis_labels?.length >= 1,};} else if (confgData.value?.type === 'pie') {return {data: props.boardData.data,title: props.boardData?.title,};} else if (confgData.value?.type === 'progress') {return {percent: props.boardData.percent,title: props.boardData?.title,};} else {// 折线图// obj 特殊化配置return {xAxisLabels: props.boardData.x_axis_labels,yAxisLabels: props.boardData.y_axis_labels,seriesData: props.boardData.series_data,isHorizontal: props.boardData?.y_axis_labels?.length > 1,...obj,};}});// 计算得到所需组件const echartsComponent = computed(() => {return allEcharts.find((item) => item.type === confgData.value?.type)?.component;});

按需导入 ECharts 包

按需引入 ECharts,而非全量引入,减小打包体积大小。

在全局入口文件中引用。

lib/echarts.ts

import * as echarts from 'echarts/core';import {BarChart,LineChart,// ...
} from 'echarts/charts';import {TitleComponent,TooltipComponent,// ... 
} from 'echarts/components';import { SVGRenderer } from 'echarts/renderers';echarts.use([LegendComponent,TitleComponent,// ...
]);export default echarts;

依赖预构建

依赖预构建 (Dependency Pre-Bundling)

vite.config.ts 文件中,相关的配置是 optimizeDeps.include

// vite.config.ts
export default defineApplicationConfig({overrides: {optimizeDeps: {include: ['echarts/core','echarts/charts','echarts/components','echarts/renderers',// ... other dependencies],},// ...},
});

这个配置是如何优化 ECharts 的?

  1. 优化对象:此优化主要针对 开发环境 (dev server),旨在提升开发时的页面加载速度和热更新性能。

  2. 工作原理

    • 问题背景
      1. ECharts 库本身是由大量的小模块组成的(例如,core 是核心,charts 目录下有各种图表类型,components 目录下有提示框、图例等组件)。
      2. 当我们在代码中按需引入时(如 import { BarChart } from 'echarts/charts'),在开发模式下,浏览器需要根据 import 语句逐个去请求这些零散的模块文件。
      3. 如果一个复杂的图表需要几十个模块,就会导致浏览器发起大量的网络请求,形成“请求瀑布流”,严重拖慢页面首次加载速度。
    • Vite 的解决方案:Vite 在启动开发服务器时,会先扫描项目代码,找出所有依赖。对于 optimizeDeps.include 中明确列出的依赖,Vite 会使用速度极快的 esbuild 工具,提前将这些零散的模块 “预构建” 成一个或少数几个大的 JavaScript 文件。
      • 具体到 ECharts:配置中的 'echarts/core', 'echarts/charts', 'echarts/components', 'echarts/renderers' 告诉 Vite:“请提前把这几个路径下的所有 ECharts 模块都找到,并将它们打包成一个整体。”
  3. 带来的好处

    • 减少网络请求:经过预构建,当浏览器需要加载 ECharts 时,不再是请求几十个零散的小文件,而是只请求一个或几个已经打包好的大文件。这极大地减少了 HTTP 请求开销。
    • 模块格式转换esbuild 会将可能存在的 CommonJS 或 UMD 格式的模块(一些旧的库可能还在使用)统一转换为浏览器原生支持的 ESM (ES Modules) 格式,避免了在浏览器端进行复杂的模块解析。
    • 更快的页面加载:最终结果就是,在开发环境中,包含 ECharts 图表的页面加载速度会得到显著提升,让开发体验更加流畅。

注意:这个优化主要作用于 开发环境。在 生产环境打包 (build) 时,Vite 会利用 Rollup 和 Tree Shaking 机制,确保最终打包出的代码只包含实际用到的 ECharts 模块,以实现生产环境包体积的最小化。这里的 optimizeDeps 配置与最终的打包体积没有直接关系。

图表的屏幕适配

统一解决了窗口缩放时图表的适应问题,避免因窗口缩放导致的 ECharts 图表变形。(主要针对大屏)

  1. 使用 scale,缩放比例比较小,那么左右留白比较大。
  2. 推荐使用 vw/vh,动态计算宽高比例,字体等,比较灵活,避免大片留白。缺点:每个图表都需要单独做字体、间距、位移的适配,比较麻烦。
http://www.xdnf.cn/news/18455.html

相关文章:

  • kafka的rebalance机制是什么
  • CentOS 10安装Ollama
  • 12-Linux系统用户管理及基础权限
  • 机试备考笔记 18/31
  • Nginx(一)认识Nginx
  • Eino 开源框架全景解析 - 以“大模型应用的搭积木指南”方式理解(一)
  • Azure TTS Importer:一键导入,将微软TTS语音接入你的阅读软件!
  • LeetCode 3195.包含所有 1 的最小矩形面积 I:简单题-求长方形四个范围
  • 【ElasticSearch】IK分词器安装,配置修改,支持新增词组,中文常用mapping使用案例
  • 微前端qiankun框架,子页面图标样式错乱问题,显示为X
  • 人脸识别驱动的工厂人体属性检测与预警机制
  • Conmi的正确答案——Ubuntu24.04禁用任何休眠
  • huggingface离线下载模型使用方法
  • CAN总线工具学习:DBC解析、设备扫描与报文监控
  • Logstash——性能、可靠性与扩展性架构
  • JAVA后端开发——API状态字段设计规范与实践
  • Claude Code接入Serena mcp
  • Elasticsearch Rails 集成(elasticsearch-model / ActiveRecord)
  • [激光原理与应用-317]:光学设计 - Solidworks - 零件、装配体、工程图
  • 浅拷贝,深拷贝
  • 【生成树+环】题解:P3907 环的异或_图论_环_异或_搜索_算法竞赛_C++
  • 【C++】多态(详解)
  • 单片机---------WIFI模块
  • 智能二维码QR\刷IC卡\人脸AI识别梯控系统功能设计需基于模块化架构,整合物联网、生物识别、权限控制等技术,以下是多奥分层次的系统设计框架
  • openEuler系统中home文件夹下huawei、HwHiAiUser、lost+found 文件夹的区别和作用
  • Linux:网络层IP协议
  • Spring Web MVC
  • 36v转5v峰值电流7A同步DC/DC降压芯片AH8655
  • C#开源库ACadSharp读取dwg图元的示例
  • Springboot项目的各层级详细总结