One of the most impactful techniques to reduce the bundle size of a React application is compression. compression is a process in which the size of a file is reduced by re-encoding the file data to use fewer bits of storage than the original file.
Reduce your bundle size by code-splitting Instead of keeping all your code in the one bundle, you can split it up into multiple bundles to be loaded separately. This is known as code-splitting. If your app has multiple pages, an easy candidate for code-splitting is to split up the code by each page.
Update February 2020
Since this answer got a lot of traction, I thought it would be best to update it with newer Angular optimizations:
ng build --prod --build-optimizer
is a good option for people using less than Angular v5. For newer versions, this is done by default with ng build --prod
Some claims that using AOT compilation can reduce the vendor bundle size to 250kb. However, in BlackHoleGalaxy's example, he uses AOT compilation and is still left with a vendor bundle size of 2.75MB with ng build --prod --aot
, 10x larger than the supposed 250kb. This is not out of the norm for angular2 applications, even if you are using v4.0. 2.75MB is still too large for anyone who really cares about performance, especially on a mobile device.
There are a few things you can do to help the performance of your application:
1) AOT & Tree Shaking (angular-cli does this out of the box). With Angular 9 AOT is by default on prod and dev environment.
2) Using Angular Universal A.K.A. server-side rendering (not in cli)
3) Web Workers (again, not in cli, but a very requested feature)
see: https://github.com/angular/angular-cli/issues/2305
4) Service Workers
see: https://github.com/angular/angular-cli/issues/4006
You may not need all of these in a single application, but these are some of the options that are currently present for optimizing Angular performance. I believe/hope Google is aware of the out of the box shortcomings in terms of performance and plans to improve this in the future.
Here is a reference that talks more in depth about some of the concepts i mentioned above:
https://medium.com/@areai51/the-4-stages-of-perf-tuning-for-your-angular2-app-922ce5c1b294
Use latest angular cli version and use command ng build --prod --build-optimizer It will definitely reduce the build size for prod env.
This is what the build optimizer does under the hood:
The build optimizer has two main jobs. First, we are able to mark parts of your application as pure,this improves the tree shaking provided by the existing tools, removing additional parts of your application that aren’t needed.
The second thing the build optimizer does is to remove Angular decorators from your application’s runtime code. Decorators are used by the compiler, and aren’t needed at runtime and can be removed. Each of these jobs decrease the size of your JavaScript bundles, and increase the boot speed of your application for your users.
Note : One update for Angular 5 and up, the ng build --prod
automatically take care of above process :)
Lodash can contribute a bug chunk of code to your bundle depending on how you import from it. For example:
// includes the entire package (very large)
import * as _ from 'lodash';
// depending on your buildchain, may still include the entire package
import { flatten } from 'lodash';
// imports only the code needed for `flatten`
import flatten from 'lodash-es/flatten'
Personally I still wanted smaller footprints from my utility functions. E.g. flatten
can contribute up to 1.2K
to your bundle, after minimization. So I've been building up a collection of simplified lodash functions. My implementation of flatten
contributes around 50 bytes
. You can check it out here to see if it works for you: https://github.com/simontonsoftware/micro-dash
Firstly, vendor bundles are huge simply because Angular 2 relies on a lot of libraries. Minimum size for Angular 2 app is around 500KB (250KB in some cases, see bottom post).
Tree shaking is properly used by angular-cli
.
Do not include .map
files, because used only for debugging. Moreover, if you use hot replacement module, remove it to lighten vendor.
To pack for production, I personnaly use Webpack (and angular-cli relies on it too), because you can really configure everything
for optimization or debugging.
If you want to use Webpack
, I agree it is a bit tricky a first view, but see tutorials on the net, you won't be disappointed.
Else, use angular-cli
, which get the job done really well.
Using Ahead-of-time compilation is mandatory to optimize apps, and shrink Angular 2 app to 250KB.
Here is a repo I created (github.com/JCornat/min-angular) to test minimal Angular bundle size, and I obtain 384kB. I am sure there is easy way to optimize it.
Talking about big apps, using the AngularClass/angular-starter configuration, the same as in the repo above, my bundle size for big apps (150+ components) went from 8MB (4MB without map files) to 580kB.
The following solution assumes you are serving your dist/ folder using nodejs. Please use the following app.js in root level
const express = require('express'),http = require('http'),path = require('path'),compression = require('compression');
const app = express();
app.use(express.static(path.join(__dirname, 'dist')));
app.use(compression()) //compressing dist folder
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
})
const port = process.env.PORT || '4201';
app.set('port', port);
const server = http.createServer(app);
server.listen(port, () => console.log('Running at port ' + port))
Make sure you install dependencies;
npm install compression --save
npm install express --save;
Now build the app
ng build --prod --build-optimizer
If you want to further compress the build say reduce 300kb(approx) from , then follow the below process;
Create a folder called vendor
inside the src
folder and inside vendor folder create a file rxjs.ts
and paste the below code in it;
export {Subject} from 'rxjs/Subject';
export {Observable} from 'rxjs/Observable';
export {Subscription} from 'rxjs/Subscription';
And then add the follwing in the tsconfig.json
file in your angular-cli application. Then in the compilerOptions
, add the following json;
"paths": {
"rxjs": [
"./vendor/rxjs.ts"
]
}
This will make your build size way too smaller. In my project I reduced the size from 11mb to 1mb. Hope it helps
One thing I wish to share is how imported libraries increase the size of the dist. I had angular2-moment package imported, whereas I could do all the date time formatting I required using the standard DatePipe exported from @angular/common.
With Angular2-Moment "angular2-moment": "^1.6.0",
chunk {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 kB {4} [initial] [rendered] chunk {1} main.e7496551a26816427b68.bundle.js (main) 2.2 MB {3} [initial] [rendered] chunk {2} styles.056656ed596d26ba0192.bundle.css (styles) 69 bytes {4} [initial] [rendered] chunk {3} vendor.62c2cfe0ca794a5006d1.bundle.js (vendor) 3.84 MB [initial] [rendered] chunk {4} inline.0b9c3de53405d705e757.bundle.js (inline) 0 bytes [entry] [rendered]
After removing Angular2-moment and using DatePipe instead
chunk {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 kB {4} [initial] [rendered] chunk {1} main.f2b62721788695a4655c.bundle.js (main) 2.2 MB {3} [initial] [rendered] chunk {2} styles.056656ed596d26ba0192.bundle.css (styles) 69 bytes {4} [initial] [rendered] chunk {3} vendor.e1de06303258c58c9d01.bundle.js (vendor) 3.35 MB [initial] [rendered] chunk {4} inline.3ae24861b3637391ba70.bundle.js (inline) 0 bytes [entry] [rendered]
Note the vendor bundle has reduced half a Megabyte!
Point is it is worth checking what angular standard packages can do even if you are already familiar with an external lib.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With