xieziyu / ngx-echarts

An angular (ver >= 2.x) directive for ECharts (ver >= 3.x)
https://xieziyu.github.io/ngx-echarts/
MIT License
1.11k stars 197 forks source link

Tree-shaking Not Working as Expected in ngx-echarts v18 with Angular v18 #426

Open achraf-codemaster opened 4 months ago

achraf-codemaster commented 4 months ago

Description

I have noticed that tree-shaking is not working as expected in the latest version of ngx-echarts (v18) with Angular v18. The bundle size remains the same whether I use the full build or a custom build of ngx-echarts.

Steps to Reproduce

Custom build

// app.component.ts

import { Component } from '@angular/core';  
import { RouterOutlet } from '@angular/router';  

import {NgxEchartsDirective, provideEchartsCore} from "ngx-echarts";  
import {EChartsOption} from "echarts";  
import * as echarts from "echarts/core";  
import {BarChart} from "echarts/charts";  
import {  
  DatasetComponent,  
  GridComponent,  
  TitleComponent,  
  TooltipComponent,  
  TransformComponent  
} from "echarts/components";  
import {LabelLayout, UniversalTransition} from "echarts/features";  
import {CanvasRenderer} from "echarts/renderers";  

echarts.use([  
  BarChart,  
  TitleComponent,  
  TooltipComponent,  
  GridComponent,  
  DatasetComponent,  
  TransformComponent,  
  LabelLayout,  
  UniversalTransition,  
  CanvasRenderer  
]);  

@Component({  
  selector: 'app-root',  
  standalone: true,  
  imports: [RouterOutlet, NgxEchartsDirective],  
  templateUrl: './app.component.html',  
  styleUrl: './app.component.css',  
  providers: [  
    provideEchartsCore({ echarts })  // Importing the custom build
  ]  
})  
export class AppComponent {  
  chartOptions: EChartsOption | null = {  
    xAxis: {  
      type: 'category',  
  data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']  
    },  
  yAxis: {  
      type: 'value'  
  },  
  series: [  
      {  
        data: [120, 200, 150, 80, 70, 110, 130],  
  type: 'bar'  
  }  
    ]  
  };  
}

Full build

// app.component.ts

import { Component } from '@angular/core';  
import { RouterOutlet } from '@angular/router';  

import {NgxEchartsDirective, provideEcharts} from "ngx-echarts";  
import {EChartsOption} from "echarts";  

@Component({  
  selector: 'app-root',  
  standalone: true,  
  imports: [RouterOutlet, NgxEchartsDirective],  
  templateUrl: './app.component.html',  
  styleUrl: './app.component.css',  
  providers: [  
    provideEcharts() // Importing the full build
  ]  
})  
export class AppComponent {  
  chartOptions: EChartsOption | null = {  
    xAxis: {  
      type: 'category',  
  data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']  
    },  
  yAxis: {  
      type: 'value'  
  },  
  series: [  
      {  
        data: [120, 200, 150, 80, 70, 110, 130],  
  type: 'bar'  
  }  
    ]  
  };  
}
  1. Build the project:
ng build --configuration production
  1. Compare the bundle sizes when using the full build versus the custom build.

Expected Behavior

The bundle size should be smaller when using a custom build compared to the full build, due to tree-shaking removing unused parts of the library.

Actual Behavior

The bundle size remains the same regardless of whether the full build or a custom build is used.

Results

Bundle size with full build

full full-2

Bundle size with custom build

custom custom-2

Versions

Conclusion

It appears that tree-shaking is not reducing the bundle size as expected. I would appreciate any guidance or fixes to resolve this issue. Thank you!

stefanlange commented 2 months ago

Try adding "statsJson": true under "architect" -> "build" -> "options" in your angular.json file. After building, you should find a file called stats.json in your dist folder.

Call https://esbuild.github.io/analyze/ and upload this file into the analyzer. You can traverse through the tree view of your packages and identify why the whole ECharts library has been bundled.

In my case, it all seems to depend on an entry point in node_modules? Please correct me, if I'm wrong.

Example for an ECharts component I don't use at all:

image

How can this be solved?