How to automate image compression with Git Hooks
Tags: javascript, automation, webdev, git
Published: 2020-09-12 17:06:07

This story is a kind of story and tutorial mix. It consists of the following parts:

* **Why do we need to compress images?**
* **What leads to me this?**
* **How I did it?**



So without delay let’s get started. **WHY WHAT AND HOW :-)**

### Why do we need to compress images?

This tutorial is not about why we need to compress images. There are already a ton of good resources over the internet of this. In summary: 

* **Large images** slow down your web pages which creates a bad user experience. (no one wants to wait)

* **Large image** files slow down your site and search engine hates slow sites(it leads to bad SEO)

* **Large images** required high bandwidth
* **Uncompressed** images bloat your pages with unnecessary bytes



That’s it there is a lot more information about this. But there is no point in explaining here. You can find all this information on this internet.



### What leads to me this?

Whenever I am doing my personal project or in my organization. I need to organize my images and have to go to manually some compressing site and then convert it into a compressed one and replaced. My lead asked me one day why don’t we automate this stuff. I don’t find any good source or anything to automate this. So I thought It’s worth sharing also.


**Note: There are already 3<sup>rd</sup> party services that done this for you. But again you have to buy that service. This tutorial is all about automating compression using hooks and for smaller project you dont want your project to blot another 3<sup>rd</sup> party service.**


### How I did it?

This is the interesting part. Let’s start it. Initially the images size is this:

![Before compress](https://dev-to-uploads.s3.amazonaws.com/i/d639kbd2o6y0wu8swmb7.png)

**Note:** I took this image for demo purpose only


So for automating this stuff I use [husky](https://www.npmjs.com/package/husky)(for git hooks) and lint-staged.
* Husky is a good npm package for using git hooks in a better way.
* lint-staged is a linter that runs for your staging file (it's like a code you want to run for staging file like beautifying your code, check unused code or malicious code, etc.)

For compression of images I use [sharp](https://www.npmjs.com/package/sharp) (it’s open-source). If you have this question why this package why not other packages there are so many good packages. I totally agree with this. But all this question is already answered sharp. 
 
You can check its [performance guide](https://sharp.pixelplumbing.com/performance). It’s already giving the answer to those questions.

### Code time:

So logic is that before committing to the code check of images and if images find then compress them before committing. 
You can do other things (like post commit, pre build etc).

Here is complete code:




```json
{
  "hooks": {
    "pre-commit": "lint-staged"
  }
}
```

---

```javascript
/**
  A precommit script to compress image before commiting file
  Q: Why Sharp package used?
  A: https://sharp.pixelplumbing.com/performance

 */

const fs = require("fs");
const sharp = require("sharp");//https://sharp.pixelplumbing.com/

/*
Function: Update existing file to new compress file
 */
const minifyFile = filename => {
  new Promise((resolve, reject) => {
    /*Read upcomimg file*/
    fs.readFile(filename, function(err, sourceData) {
      if (err) throw err;
      /*If file buffer data is present convert it into new compressed file*/
      sharp(sourceData).toFile(filename, (err, info) => {
        err ? reject(err) : resolve();
      });
    });
  });
};

/*
Fetch images maps from args and compress all.
Compressing is asynchronuous process.
So wait for all image to compress and return.
*/
Promise.resolve(process.argv)/*Find more. here: https://nodejs.org/en/knowledge/command-line/how-to-parse-command-line-arguments/*/
  .then(x => x.slice(2))
  .then(x => x.map(minifyFile))
  .then(x => Promise.all(x))
  .catch(e => {
    process.exit(1);
  });
```

---

```json
{
  "name": "image-compression",
  "version": "1.0.0",
  "description": "Pre commit script to compress images",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": {
    "name": "Shubham Verma"
  },
  "license": "ISC",
  "devDependencies": {
    "husky": "^4.2.5",
    "lint-staged": "^10.2.7",
    "sharp": "^0.25.3"
  },
  "lint-staged": {
    "*.{png,jpeg,jpg,gif,svg}": [
      "node ./compress-image.js"
    ]
  }
}
```

I already explained everything in code. Feel free to reach me out.

### Last but not least proof ;-)

![After compression](https://dev-to-uploads.s3.amazonaws.com/i/z5ibu3x31cvuwrluqxj1.png)


That’s all folks. Feel free to ask a question if you find any doubt. The complete code is available on Github. Feel free to [checkout](https://github.com/shubhamV123/compress-image-script)

You can reach me at twitter [@shubham2133](https://twitter.com/shubham2133)