!!!###!!!title=VChart On-demand Loading Source Code Analysis——VisActor/VChart Contributing Documents!!!###!!!!!!###!!!description=---title: 13.2 VChart On-Demand Loading Source Code Explanation key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM--- Based on the previous articles, we have introduced the composition of VChart and the concept of Tree Shaking. Based on these two preliminary concepts, we will now elaborate on the specific implementation of VChart's on-demand loading. !!!###!!!

Based on the previous articles, we have introduced the composition of VChart and the concept of Tree Shaking. Based on these two preliminary concepts, we will now elaborate on the specific implementation of VChart's on-demand loading.

Core Creation Process of VChart Charts

Factory

The on-demand loading of VChart mainly relies on the Factory class to achieve this. This class plays an important role, responsible for registering and creating various charts, series, components, graphics, Regions, layouts, and plugins. Below, we will conduct an in-depth analysis from the aspects of the registration mechanism, creation mechanism, and on-demand registration of charts.

Registration Mechanism

The Factory class provides a series of static methods for registering different types of modules. Through these methods, modules are registered into the static properties of Factory, thereby forming a registry. The specific code is as follows:

static registerChart(key: string, chart: IChartConstructor) {
  Factory._charts[key] = chart;
}
static registerSeries(key: string, series: ISeriesConstructor) {
  Factory._series[key] = series;
}
static registerComponent(key: string, cmp: IComponentConstructor, alwaysCheck?: boolean) {
  Factory._components[key] = { cmp, alwaysCheck };
}
// 其他注册方法...    

Creation Mechanism

The Factory class also provides a series of static methods for creating module instances as needed. These methods look up the corresponding constructor from the registry based on the type and create an instance. The sample code is as follows:

static createChart(chartType: string, spec: any, options: IChartOption): IChart | null {
  if (!Factory._charts[chartType]) {
    return null;
  }
  const ChartConstructor = Factory._charts[chartType];
  return new ChartConstructor(spec, options);
}
static createSeries(seriesType: string, spec: any, options: ISeriesOption) {
  if (!Factory._series[seriesType]) {
    return null;
  }
  const SeriesConstructor = Factory._series[seriesType];
  return new SeriesConstructor(spec, options);
}
// 其他创建方法...    

On-Demand Registration of Charts

Taking the line chart as an example, let's look at the specific implementation of on-demand registration. In packages/vchart/src/chart/line/line.ts, there is the following code:

export const registerLineChart = () => {
  registerLineSeries();
  Factory.registerChart(LineChart.type, LineChart);
};    

The registerLineSeries is implemented in packages/vchart/src/series/line/line.ts, the code is as follows:

export const registerLineSeries = () => {
  registerSampleTransform();
  registerMarkOverlapTransform();
  registerLineMark();
  registerSymbolMark();
  registerLineAnimation();
  registerScaleInOutAnimation();
  registerCartesianBandAxis();
  registerCartesianLinearAxis();
  Factory.registerSeries(LineSeries.type, LineSeries);
};    

By implementing the above code, when using VChart, if you call registerLineChart to register a line chart, it will automatically register the necessary elements such as the line series, line chart elements, and point chart elements that the line chart depends on. The specific usage is as follows:

import { VChart } from './core';
import { registerLineChart } from './chart/line';
VChart.useRegisters([
  registerLineChart,
  // 其他需要的模块
]);    

In packages/vchart/src/core/vchart.ts, the chart instance is not created by direct path reference, but by using Factory.createChart. In this way, the core class vchart can create instances based on the charts registered by the user without referencing all chart implementations. The relevant code is as follows:

private _initChart(spec: any) {
   // ...
    const chart = Factory.createChart(spec.type, spec, this._getChartOption(spec.type));
   //...
  }    

Core Class VChart On-Demand Loading

Next, let's discuss a question: Is there a difference between the following two ways of referencing VChart?

  • Method One:
import VChart from '@visactor/vchart';    

  • Method Two:
import { VChart } from '@visactor/vchart';    

The answer is yes, the effects produced by these two citation methods are different. Below is an analysis of the reasons for their differences.

First, in the corresponding package.json of the vchart codebase, you can see the following configuration:

{
  "sideEffects": [
    "./*/index-lark.js",
    "./*/index-wx-simple.js",
    "./*/index-wx.js",
    "./*/vchart-all.js",
    "./*/vchart-simple.js"
  ],
}    

The configuration explicitly declares all files with side effects.

In packages/vchart/index.ts, the following exports are present:

import { VChart } from './vchart-all';
export default VChart;
export * from './core';    

In the core/index.ts file, the following exports are present:

import { VChart } from './vchart';
export { VChart, Factory };    

So method one is equivalent to the following reference, where the referenced VChart is the VChart class exported by vchart-all, and method two is equivalent to the VChart class exported from core/vchart.ts.

import { default as VChart } from '@visactor/vchart';    

The main purpose of the file vchart-all.ts is to register and export all functional modules of VChart:

VChart.useRegisters([
  // charts
  registerLineChart,
  registerAreaChart,
  // ...其他图表
  // components
  registerCartesianLinearAxis,
  registerCartesianBandAxis,
  // ...其他组件
  // layout
  registerGridLayout,
  registerLayout3d,
  // mark
  registerAllMarks,
  // plugin
  registerDomTooltipHandler,
  registerCanvasTooltipHandler,
  // ...其他插件
]);
export { VChart };    

Since vchart - all is declared as a file with side effects, when VChart is referenced using method one, all files that vchart-all depends on will be packaged; whereas when VChart is referenced using method two, only core/vchart.ts will be packaged.

This document was revised and organized by the following personnel

玄魂