Compression reduces up to 70% of the size of text-based files ( HTML, JS, CSS, etc..) and some compression algorithms can reduce the size even more, this will result in a much faster loading time for your clients and less bytes going over the wire.
Gzip compression is probably the most common algorithm in use today and is supported by all major browsers.
Integrate compression with Express
We can easily compress our serverās responses with a simple Node.js compression middleware, Lets start with a simple server as our playground:
const express = require("express");const port = process.env.PORT || 3000;// Init expressconst app = express();// Server routesapp.get("/compress", (req, res) => {res.send("Hello World!");});// Start serverapp.listen(port, () => {console.log(`Listening on port: ${port}`);});
Install the middleware:
npm install compression
After itās installed lets import it inside our server:
const compression = require("compression");
Now lets bind our compression middleware to the application:
......// Init expressconst app = express();app.use(compression())......
Here we did not supply any options to the compression middleware, this means any response the server returns will be automatically compressed.
Control the level of compression
To control the compression level we need the pass a number between 0 ā 9 to the level property.
0 ā no compression at all.
ā¦
9 ā the best compression available.
The higher the level of compression you use the more time it will take to compress your response.
We can set the default compression by not passing any parameters to the level property or by passing the value -1, this value will currently equal the value of 6 and it means it is the best compromise between compression and speed.
Example of setting a compression level:
app.use(compression({ level: 9 }));
Controlling the compression middleware
We can decide which responses we would like to compress or not by supplying a filtering function to the middleware:
const shouldCompress = (req, res) => {if (req.headers["x-no-compression"]) {// don't compress responses with this request headerreturn false;}// fallback to standard filter functionreturn compression.filter(req, res);};// Usage:app.use(compression({ filter: shouldCompress }));
When you send a request with the header āx-no-compressionā the compression middleware will not compress your response, for example using the fetch API:
// npm install node-fetch...const fetch = require("node-fetch");fetch("http://localhost:3000/compress", {method: "GET",headers: {"x-no-compression": "Any true value",},}).catch((e) => console.log(e));
Iām sending the request using Node.js, Node.js does not support fetch out of the box so Iāve installed node-fetch.
As you can see Iām sending a simple GET request to our server and Iāve supplied the āx-no-compressionā header, by doing so our filtering function will decide whether to compress the response or not.
You can pass any value you want inside āx-no-compressionā header, just make sure its not a falsy value.
Before and After
Now that its all set up lets test our compression middleware by seeing how the response size changes.
The easiest way I could think of to increase the response size was to create a variable that will hold a really long text, by doing so the response size will increase.
app.get("/compress", (req, res) => {// I've shortend the actual text sizeconst text = `Lorem Ipsum is simply dummy text of the ...`;res.send(text.repeat(10));});
The function repeat will return a new concatenated string which contains a specified number of copies of the string which we called it on.
While repeat is used to increase the size of the response it will make the response time much higher until the processing is done. For a more accurate response you can store a large text in a database and retrieve it, or for the purpose of testing the compression hard code the text like I did in the example, just remove the repeat function and add a large text.
THE RESULTS
Before compression the response size is 23.3KB
After compression the response size is 1.6KB
I think the response size difference is truly impressive, the usual compression rate for the gzip algorithm is around 70%. We have here around 93% compression size difference but its mostly because we used the repeat function and the text is not diverse enough.
While I have not looked up the implementation of the gzip algorithm, the most basic compression algorithms usually finds repeating patterns in a given text and replaces them with a representing value instead, by doing so you can compress the text with values that later decompresses to the pattern found.
I hope you enjoyed this article and that it brought you VALUE.
Documentation about the compression plugin:
http://expressjs.com/en/resources/middleware/compression.html