To ensure a good user experience in web development, prioritize web application performance. File compression is a powerful optimization tool that reduces data size and leads to faster page loading times. Gzip and Brotli are effective compression tools that can be used with Webpack Compression Plugin to achieve fast loading speeds on all devices and network conditions.
Here's a little about me: I am skilled in improving performance and enjoy enhancing applications to save time and resources. I always strive to optimize everything I work on.
I organized my approach by topics. Here are some suggestions:
Optimize Your Web Experience: Master the Art of Lazy Loading Imports
Boost Your JavaScript Dockerfile for Top-Notch Production Deployments
Today, you will get an in-depth understanding of webpack and some valuable tips. By going deeper, you will understand what you are doing, with answers to questions like "Why?" and "How does it work?" Let's analyze the events that we will influence when building the application.
Before we start, let us quickly remind you what comes next after your code passes the PR.
A bundle file(-s) is a collection of resources such as JavaScript code, CSS styles, and images combined and optimized to make loading and running on the client side more convenient.
Thus browsers have tools for demodulating the code into digestible user form. The browser understands what needs to be done to turn the code into a website or application.
The speed of demodulation and the construction of the DOM depends on the computing power of the user's device.
As a developer, you may not be able to control the performance of the browser or the power of the user’s device. However, there is a crucial aspect where you and/or the DevOps engineer can significantly impact the bundle size. This is the focus of our analysis, and the solution lies in compression.
Compression of bundle files during Webpack build is the process of using compression algorithms, such as Gzip and Brotli, to reduce the size of the final bundle files containing all the code and resources of your web application. This improves website loading performance, reduces network traffic, and allows your application to run faster on the client side.
Compression algorithms identify repeating data and replace it with shorter symbols, reducing the amount of transmitted information and file size. Gzip and Brotl are safe for compressing text and code but may cause a quality loss in images and videos. To use the compression algorithm when building a project, or a web application, you have to support it:
The good news is that most browsers support “under the hood” for decompressing Data from the server and do decompression “on the fly.”
If you have specific browser support, please, check compatibility here on this link.
So, now we need to comprehend how to Compress data.
I am using my well-known Angular pet application from a previous topic about lazy imports and will now focus on applying the gzip algorithm.
I will break down the steps into smaller subtopics to make them easier to follow.
The process of building the app is outlined in the angular.json
configuration file. Within the build
configuration, a package offers a standard build setup for most Angular applications.
"projects": {
...
"[project]": {
...
"architect": {
"builder": "@angular-devkit/build-angular:browser",
We require something else. We aim to adjust the settings and enhance the functionality of the standard build. We need greater flexibility in managing the build process and Webpack configuration. We strive for excellence in our standards.
The good news is that a custom-webpack package already exists for non-standard developers. Install and change the builder string.
npm i @angular-builders/custom-webpack
"architect": {
...
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./custom-webpack.config.js",
"replaceDuplicatePlugins": true
},
...
}
},
The place where we change the webpack configuration is a particular JavaScript file. Here, we have the options and customWebpackConfig
sections. To specify the path to the new webpack configuration file, you should create a new file with the same name or a different one and link it to the path.
For React developers, you can make the same things without a custom builder and use this command to configure your build.
{
"scripts": {
"build": "webpack --config webpack.config.ts"
}
}
We need to install the special CompressionPlugin (the main star of our topic) before we can proceed with configuring the custom-webpack.config
file.
npm install compression-webpack-plugin --save-dev
Add configuration to custom-webpack.config.js is:
const CompressionPlugin = require("compression-webpack-plugin");
module.exports = {
mode: "production",
plugins: [
new CompressionPlugin({
// Be very carefully with 'true', sometimes bug happens
deleteOriginalAssets: false,
algorithm: 'gzip',
test: /\.(js|css|html)$/,
}),
]
};
“deleteOriginalAssets: true.” We will address this further in a later discussion.
We have installed the CompressionPlugin dependency and set it up. We aim to use the gzip algorithm for compression, and we have specified the file extensions we want to compress in the Regular Expression format.
This library supports algorithms such as Gzip and Google’s Brotli.
Brotli provides better compression than Gzip, especially for text-based files such as HTML, CSS, and JavaScript. It can achieve compression rates 20-30% higher than Gzip. For instance, JavaScript and CSS files are typically compressed to 30-40% of their original size with Gzip, whereas Brotli can achieve 50% or more compression.
Our upcoming project will be built using custom-webpack and its new configuration file, custom-webpack.config.js. Let’s build:
ng build
Let's take a look at the dist/lazy-import folder. Here, you will find both the original and … the compressed gzip files.
An inquiry that DevOps engineers may have is whether keeping both clean and compressed application files will increase the server's application size. The answer is yes- the size will be 🔼X plus (compression ratio multiplied by X). Prior to this, only clean application files with X megabytes were retained. 💾
Can I only save compressed files and securely use the application? Yes, the answer is affirmative.
Overall, there are libraries available to remove non-compressed files automatically.
The CompressionPlugin has a setting called deleteOriginalAssets set to true, which you may want to check. However, some forums report that this feature can accidentally delete important files, causing the application to fail.
However, in this tutorial, we will create a script for this purpose and integrate it into the process. This will help you better understand how these libraries function behind the scenes.
To begin, create a new JavaScript file in the project's root, like remove-non-compressed-files.js
, and add the script.
const fs = require('fs');
const path = require('path');
const directoryPath = './dist/lazy-import';
fs.readdir(directoryPath, (err, files) => {
if (err) {
console.error('Error reading directory contents:', err);
return;
}
// Filter files to keep only those with the .js extension
const jsFiles = files.filter((file) => path.extname(file) === '.js');
// Delete each file
jsFiles.forEach((file) => {
const filePath = path.join(directoryPath, file);
fs.unlinkSync(filePath);
console.log(`Deleted file: ${filePath}`);
});
console.log('File deletion completed!');
});
If we add this script to the build process after the build, this script will delete all files with the given condition.
ng build && node remove-non-compressed-files.js
The result is more respectable now.
Fantastic! But storing only compressed files can be helpful but requires a careful approach and proper integration with your actual server and build process.
Our upcoming article will discuss Docker Example and cover essential topics such as server Dynamic Compression, Gzip Support, and Caching. A comprehensive understanding of these aspects is crucial; we'll provide the necessary information.
It is time to make sure that our approach is correct and efficient.
Let's set up a local server to handle isolated and built applications using only gzip files. Do the command and read my notes.
npm install express compression express-static-gzip
express:
A popular web framework for Node.js used to build web applications. It provides features to handle routes, requests, and responses.
compression
: An express middleware that enables HTTP response compression on the server side using methods like Gzip and Brotli. It reduces the size of data sent to the client, improving application performance.
expressStaticGzip
— is a middleware express
that provides static file serving with built-in gzip compression support. It enables express
to serve static files, such as JavaScript, CSS, and images, while automatically compressing them using gzip or Brotli, if available. This helps to reduce the size of transferred files, leading to faster loading times and improved performance for web applications.
Let's create a server configuration file called. server.js.
const express = require('express');
const expressStaticGzip = require('express-static-gzip');
const path = require('path');
const app = express();
// Enable gzip compression for server responses
app.use(expressStaticGzip(path.join(__dirname, 'dist', 'lazy-import'), {
enableBrotli: true, // Enable Brotli compression
orderPreference: ['br', 'gz'], // Compression preference order (Brotli will be preferred if available)
setHeaders: (res) => {
// Set correct Content-Encoding and Content-Type headers
res.setHeader('Cache-Control', 'public, max-age=31536000');
},
}));
// Start the server on port 8080
const PORT = 8080;
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}/`);
});
Let’s run the server and open the application.
node server.js
After each test, kindly delete the dist/[app-name] folder, restart the server following the build, and clear the cache in your browser.
This feature only works in browsers that support gzip compression - all modern browsers. IE bye. The initial picture represents the uncompressed version of the application. It resulted in a transfer of 106 kB.
The second picture is intended for the compressed application, resulting in a transfer of 284 kB.
The results show that around 50% of the 📊 transfer wins and occurs during the ⌛️ DOMContentLoaded event.
Scale the application and see more fascinating results.
Last look on headers. Our compressed application has Content-Encoding: gzip instead of standard application/javascript.
The browser decompresses the data and uses the resulting JavaScript to process and render the page.
We see that our full-time uploading included a decompression process.
The legitimate question is - "How long does the decompression process take, and could it potentially affect the user's experience?".
Gzip and Brotli decompression usually happens very quickly in modern browsers and computers. Compression algorithms are designed to provide high-speed decompression with minimal computational overhead.
The speed of decompression depends on several factors:
new CompressionPlugin({
...
//for gzip max compression level is 9.
compressionOptions: { level: 9 },
...
}),
Overall, gzip decompression is a relatively fast operation and is usually not a performance bottleneck when working with web applications. However, like any performance optimization, monitoring file sizes and ensuring proper caching is essential to maximize the user experience.
In summary, by harnessing the full potential of compression technologies and staying dedicated to continuous improvement, web developers can pave the way toward a faster, more sustainable, and more engaging web experience for users worldwide.
Please, follow me: