Reduce your bundle size through this component styling technique
Believe me struggle to reduce the bundle size is something we all struggle with, it is the same with us, and I am crazy about optimizing things, and want my bundle to be as small as possible once my application is stable and in running state.

Reduce your bundle size through this component styling technique
Believe me struggle to reduce the bundle size is something we all struggle with, it is the same with us, and I am crazy about optimizing things, and want my bundle to be as small as possible once my application is stable and in running state.


Few months ago, I started working on a new project, the biggest problem for us, is the application is very big, so the bundle size.
NOTE: We were using partial _scss-variable
everywhere. The partial scss will never be added to generated css.
The StruggleLink to this section
Believe me struggle to reduce the bundle size is something we all struggle with, it is the same with us, and I am crazy about optimizing things, and want my bundle to be as small as possible once my application is stable and in running state. This project was new as I started in Feb 20, and it takes sometime to adjust into a new project and team, so I don't wanted to directly jump into optimizing things. I did implemented lazy loading and upgraded to Angular 9 to reduce our bundle size upto some extent, but still the idle bundle size for was a dream.
Ray of Hope Link to this section
One thing you need to succeed is hope that you can do it, This is what I got while working on one of the issues, and thanks to Igor who introduced me to source-map-explorer for which I created an builder to use with angular.
If you add and run this builder in your application, it will give you size of each and every chunks, including services, components, directives, the angular framework all third party library size which is adding into your final bundle size.
The output of the analyzer looks like below:


The above statistics is for entire application, you can zoom out to see more details as they will be hidden.


The above image is what i got after a zoomed out and clicked on src folder, now i can see the size of each and every component in my main bundle, the builder gives you an option to analyze the lazy loaded chunks as well.
After I saw the same report for my application, I was surprised a bit, most fo the component was minimum of 90KB ?. Huge right, considering we had around 160 components, you can consider the pain, specially when we add a new component. Considering now i know the size of components, I tried to analyze more, why they are so big.
Finding the culpritLink to this section
Now as I knew the size, next thing I had to figure out was who is the culprit?
While working on one issue, suddenly i found below code, you can notice there is nothing being used from scss-variables
still it is imported.I decided to remove it, and i decided to analyze the bundle again, the size got reduced by 20KB, and this is one of the component, there were few more like this.
<>Copy@import '../../../themes/scss-variables'; :host { .image, .placeholder, .spinner { display: none; width: 100%; position: relative; }
So I figured out somehow, we are not using scss properly which is causing this bundle size to increase.
Baby Steps for solutionLink to this section
One thing which I have learned over the years is, take baby steps when you are working on a new project. I decided to take one step at a time, removing unused scss imports was the first step.
Remove Unused importsLink to this section
To give you an idea about our app, we are using material custom theme,so we have lots of scss files. We had custom-material-theme.scss where we had our custom colors, in few components I found we are importing custom-material-theme too.
<>Copy@import '../../../../themes/custom-material-theme'; @import '../../../../themes/scss-variables'; :host { .documents-list { } }
I realized this is totally unnecessary, but as it is imported, its responsible for increasing the bundle size, next step remove all imports for custom-material-theme.scss
This exercise helped us to decrease the bundle size by 250KB in main bundle and around 250-300KB from lazy loaded module.


Setting Budget SizeLink to this section
One good thing about Angular is it knows what you can do wrong, so it actually offers budgets to keep your bundle size in check. If you are not using it, please use it. When i joined the team, i added the anyComponentStyle
check and build failed, to my surprise most of the components had styling of more than 65kb.
<>Copy"budgets": [ { "type": "initial", "maximumWarning": "2mb", "maximumError": "5mb" }, { "type": "anyComponentStyle", "maximumWarning": "6kb", "maximumError": "10kb" } ]
Using ViewEncapsulation for ComponentsLink to this section
I had used ViewEncapsulation in past while working on a component library with my previous employer. We had used ViewEncapsulation.None
because we wanted the developers to override the component styling. Most of the component library use the encapsulation to ViewEncapsulation.None
so it can be overwritten, what it does is, it writes the styling in global css file generated.
Let's write some code to Reproduce the issue, I am not going to talk about how to setup the custom theme in material, you can download the code from: https://github.com/santoshyadav198613/scssdemo
After downloading go ahead and run the below command.
<>Copynpm run analyze
You can see the size of employee
and department
component, they are more than 90KB, same issue which we are facing.
Now let's get it fixed:
Open the employee.component.ts
and add the below code, you can see we are using encapsulation: ViewEncapsulation.None
and add the same property to department.component.ts
<>Copyimport { ViewEncapsulation } from '@angular/core'; @Component({ selector: 'app-employee', templateUrl: './employee.component.html', styleUrls: ['./employee.component.scss'], encapsulation: ViewEncapsulation.None })
run the below command again to analyze the bundle.
<>Copynpm run analyze


You can see the size of employee
and department
component is already reduced by around 25-30KB. This is for one component, consider the large code base with many components, it will reduce the bundle size in MB's.
But wait, we are still not done, using ViewEncapsulation.None
adds the styling to global file, lets add <h1> in both the component.
<>Copy// In employee component <h1> Employee </h1> // In department component <h1> Department </h1>
Next add the below styling in employee.component.scss
<>Copyh1 { background-color: $color-nordic-blue; color: $color-white; }
and add the below styling in department.component.scss
<>Copyh1 { background-color: $color-green; color: $color-white; }
Run the application using ng serve
you will notice the employee and department both having same styling, this is due to encapsulation set to None.
Now rather than fixing and optimizing our application we introduced another issue. Don't worry let's fix this next.
NOTE: I have seen many projects using :host
to wrap styling, see the below code and check if you can remove it.
Using HostBinding to wrap stylingLink to this section
HostBinding let's you use DOM property as a host-binding property this is what we are going to do next.
Open employee.component.ts
and add the below code:
<>Copy@HostBinding('class') class = 'app-employee';
and in department.component.ts
add the below code:
<>Copy@HostBinding('class') class = 'app-department';
The above code will add class app-employee
to EmployeeComponent
and app-department
class to DepartmentComponent
let's inspect the element to see it.




NOTE: You can use the class name property to be anything, I prefer naming it to same as selector name so it is easy to remember if I want to override it.
Next let's wrap your classes into the newly added css property.
Open department.component.scss
and add the below code to wrap all css inside app-department
class.
<>Copy.app-department { h1 { background-color: $color-green; color: $color-white; } .full-width-table { width: $full-width; } }
Do the same for employee.component.scss
and run the application now everything works. If you inspect and select the h1
tags and view the Styles
tab you will notice something like below:




You can run the analyze command again to see the bundle size, there should not be any change.
When not to use this approachLink to this section
This approach adds the styling to global stylesheet, so if you don't want anyone to override the component styling, this approach is not for you.
Stats from my applicationLink to this section
Wondering what it did to my application, below is the stat, and let me tell you its still not completed.


ConclusionLink to this section
The Bundle size of our application is big, and when i joined the team, it was also a concern for me, but initially i tried some optimization techniques like lazy loading, which helped, but it was not clear why still chunk size is big, understanding the size for each component helped me figure out, where to look for the issue.
We had used :host
everywhere we replaced it with @HostBinding('class')
and adding it with ViewEncapsulation.None
helped us reduce the bundle size.
Also be strict while doing code reviews, check for the imports properly if they are correct of being used properly.
The optimized code is available in https://github.com/santoshyadav198613/scssdemo/tree/feat--add-encapuslation
So if you are also struggling with such issue, do the similar exercise and share your stats with community.
Comments (0)
Be the first to leave a comment
About the author

Santosh is a GDE for Angular, he is an open-source contributor for Angular, NgRx, and Writer at AngularInDepth and DotNetTricks.

About the author
Santosh Yadav
Santosh is a GDE for Angular, he is an open-source contributor for Angular, NgRx, and Writer at AngularInDepth and DotNetTricks.
About the author

Santosh is a GDE for Angular, he is an open-source contributor for Angular, NgRx, and Writer at AngularInDepth and DotNetTricks.