Angular: Optimization Bundle Size with Brotli
Problem: The bundle size is too large and makes website slower
Hi everyone, in this section I want to share my experience about optimization bundle size, especially in Angular using Brotli. The main problem why am I using Brotli rather than Gzip is because the bundle size is too large to serve to the client. So, I need to do more research about how to optimize the application, and walaaa, I got the Brotli.
So, what is Brotli? In short, the main task of Brotli is to compress bundle size, which has an algorithm itself. The advantage of using Brotli (br) is to make the website load faster. If you have ever heard about Gzip, the Brotli is the same thing as that, and Brotli was developed by Google. For more information, you can visit this link down below.
Actually, I have a lot of questions about Brotli but one question that I want to highlight is, “is it Brotli does support a lot of versions of the browser?” Then I got the information and it was great.
The next is you should know the comparison of some methods with Brotli. The image below is a summary to compare Brotli with gzip, bzip2, and xz.
We know that the compression time of Brotli is higher than Gzip, but for decompression time Brotli is smaller than Gzip. This is the reason why the bundle size can be smaller and can improve the performance of applications.
I also recommended a blog about Brotli with more detailed information.
Practice
I think enough for the explanation, Let’s practice together. In this section, I’m using projects from previous blogs. You can clone or maybe create your own project.
Make sure you are in the branch communication-data-input-output and then create a new branch with run this command
git checkout -b optimization-brotli
Just try to run the project with this command
npm run start
If the project running well, that’s good
Next, we need to install an additional library to support the Brotli in Angular.
npm install -D @angular-builders/custom-webpack compression-webpack-plugin brotli-webpack-plugin
Then, update angular.json
Before updating angular.json
After updating angular.json
Just updated the build lib and add customWebpackConfig on the options of build config.
Next, create the file webpack.config.js
const CompressionPlugin = require(`compression-webpack-plugin`);
const BrotliPlugin = require(`brotli-webpack-plugin`);
module.exports = {
plugins:[
new BrotliPlugin({
asset: '[fileWithoutExt].[ext].br',
test: /\.(js|css|html|svg|txt|eot|otf|ttf|gif)$/
}),
new CompressionPlugin({
test: /\.(js|css|html|svg|txt|eot|otf|ttf|gif)$/,
filename(info){
let opFile= info?.filename?.split('.'),
opFileType = opFile?.pop(),
opFileName = opFile?.join('.');
return `${opFileName}.${opFileType}.gzip`;
}
})
],
}
The above script is to add plugin compression from Webpack (Gzip) and Brotli. For Brotli config we only apply on file js|css|html|svg|txt|eot|otf|ttf|gif .
After that, create a file brotli-compress.js
const brotli = require('brotli')
const fs = require('fs')
const brotliSettings = {
extension: 'br',
mode: 0, // 0 = generic, 1 = text, 2 = font (WOFF2)
quality: 11, // 0 - 11
lgwin: 22 // window size
}
const path = 'dist/angular-tutorial-blogs';
fs.readdirSync(path).forEach(file => {
if (file.endsWith('.js') || file.endsWith('.css') || file.endsWith('.html')) {
const result = brotli.compress(fs.readFileSync(path + '/' + file), brotliSettings)
if (result) {
fs.writeFileSync(path + '/' + file + '.br', result)
}
}
})
The function file of brotli-compress is to compress the file with Brotli and write a file with extension .br
For the Brotli settings, you can check this link below
Then, we need a little adjustment on package.json
{
"name": "angular-tutorial-blogs",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build && npm run postbuild",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"postbuild": "node brotli-compress.js"
},
...
}
After that, try to build the project
npm run build
Finally, if your build is successful, there are files with extensions .js , .gzip, and .br
Look at the size! That awesome.
After that just try to serve the project.
But, we have a problem, the content that serves it is still .js
Although we have several types files like .js , .gzip and .br . It’s still served in js if we serve the client side, the possible way to try the compression files is with server-side rendering or we create a server with express js.
To create a server, run this command.
npm i express express-static-gzip
After that, create a file server.js
const path = require('path');
const express = require('express');
const expressStaticGzip = require('express-static-gzip');
const serverPort = 7000;
const server = express();
server.use("/", expressStaticGzip(path.join(__dirname + '/dist/angular-tutorial-blogs'), {
enableBrotli: true
}));
server.get(/.*/, function (req, res, next) {
if (req.headers['x-forwarded-proto'] !== 'https' && process.env.NODE_ENV === 'production')
res.redirect('https://' + req.hostname + req.url);
else
res.sendFile(__dirname + '/dist/angular-tutorial-blogs/index.html');
});
server.listen(process.env.PORT || serverPort, function () {
console.log('Server. Port:%d', process.env.PORT || serverPort);
});
Then, just run node server.js to run angular from server.
node server.js
To make it easier, just update the package.json
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build && npm run postbuild",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"postbuild": "node brotli-compress.js",
"ssr":"npm run build && npm run server",
"server": "node server.js"
},
This is an awesome result.
Conclusion
Finally, we have implemented Brotli compression in the angular project. There are several advantages to using brotli
- Reduce bundle size
- Easy to implement
- Improve web performance
Last but not least, the image below is the compare load file with Brotli and without Brotli.
Compress with Brotli
Compress without Brotli
Thank you for your attention to reading this blog. You can check the repository for this project.
References:
#Angular #Express #Brotli #Optimization #BundleSize #Compression