Tree Shaking not reducing the overall package size of an Angular application
msbasanth opened this issue ยท 9 comments
Hi,
We compared using ngx-echarts with full echarts against echarts tree shakable API's. For experimenting we used the demo sample given @https://github.com/xieziyu/ngx-echarts-starter
Option 1: Full ECharts imported
@NgModule({
imports: [
NgxEchartsModule.forRoot({
/**
* This will import all modules from echarts.
* If you only need custom modules,
* please refer to [Custom Build] section.
*/
echarts: () => import('echarts'), // or import('./path-to-my-custom-echarts')
}),
],
})
Total Main.js Size: 1.1 MB; Total Network transfer: 1.2MB
Option 2: Using tree shakable API's from ECharts
import * as echarts from 'echarts/core';
import { LineChart } from 'echarts/charts';
import {
TitleComponent,
TooltipComponent,
GridComponent
} from 'echarts/components';
// Import the Canvas renderer, note that introducing the CanvasRenderer or SVGRenderer is a required step
import {
CanvasRenderer
} from 'echarts/renderers';
import 'echarts/theme/macarons.js';
echarts.use(
[TitleComponent, TooltipComponent, GridComponent, LineChart, CanvasRenderer]
);
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
NgxEchartsModule.forRoot({ echarts }),
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
Our observation is,
Total Main.js Size: 1.2 MB; Total Network transfer: 1.2MB
So as you could see total size of main.js increased with tree shakable API usage. What could be the reason for the increase in package size after using tree shakable API?
Please let us know in case the approach we followed is not correct.
Thanks
Basanth
Having this same problem on Angular 12. Copy-pasted the documentation, and looking at the webpack analysis shows every echarts module is included.
Yes it looks like when we add theme (downloaded from theme builder) we have echarts included inside that.
Here is the comment from echarts apache/echarts#15138
I will keep you updated with the package size.
I tried the suggestion from echarts contributor and looks like tree shaking is working in echarts. ๐
apache/echarts#15138
But the same approach of registering the theme ourselves by passing json (basically avoiding require('echarts')) didn't work here with ngx-echarts.
This is what I tried, instead of importing style directly I registered theme manually.
import * as echarts from 'echarts/core';
echarts.registerTheme('dark', { <<Entire theme as json>>});
Even with this network transfer shows same size 1.2MB for the application.
@msbasanth
Sorry for the late reply and thanks for your issue report.
I double checked the codes in https://github.com/xieziyu/ngx-echarts-starter and found the duplicated echarts/theme/macarons.js
importing in main.ts
. If we remove all the codes importing the theme files directly, the tree shaking should be working as expected.
@xieziyu from this issue I didn't really get how to tree shake echarts in Angular. Could you provide some examples and/or explanations other than in linked issues?
This issue still seems to be prevailing, any update on this?
@Alphapredator01
Here's the solution I used so that I got both tree-shaking and lazy loading of modules:
- I split out the components of interest into
charts.ts
:
import * as echarts from 'echarts/core';
import {DataZoomComponent, GridComponent, LegendComponent, MarkLineComponent, TitleComponent, ToolboxComponent, TooltipComponent} from 'echarts/components';
import {BarChart, LineChart, SankeyChart} from 'echarts/charts';
import {CanvasRenderer} from 'echarts/renderers';
echarts.use([
BarChart, LineChart, SankeyChart,
DataZoomComponent, GridComponent, LegendComponent, MarkLineComponent, TitleComponent, ToolboxComponent, TooltipComponent,
CanvasRenderer,
]);
export default echarts;
- Add an import for this in my
app.module.ts
:
@NgModule({
declarations: [AppComponent],
imports: [
NgxEchartsModule.forRoot({
echarts: () => import(
/* webpackChunkName: "charts" */
/* webpackMode: "lazy" */
'./path/to/charts').then(m => m.default)
}),
.
.
.
bootstrap: [AppComponent]
})
export class AppModule {
}
With my current imports, this gets my gzip'd webpack analysis down to ~204 KB. That used to be closer to 1 MB:
For testing, I had to make a separate test module file so that it could be imported in unit tests. Created charts-testing.module.spec.ts
right next to my charts.ts
in step 1:
import echarts from './charts';
import {NgxEchartsModule} from 'ngx-echarts';
/** Simple export to simplify charts import when testing, but allow AppModule to continue to use lazy-loading process */
export const ChartsTestingModuleSpec = NgxEchartsModule.forRoot({echarts});
and then import it like I would any other module in a unittest:
beforeEach( async () => {
await TestBed.configureTestingModule({
imports: [
ChartsTestingModuleSpec,
NoopAnimationsModule,
.
.
.
],
});
.
.
.
});
How would this look for a standalone component?