Node.js: how to recursively compress all images on the site


31-08-2018
Денис Л.
Разное
Node.js: how to recursively compress all images on the site

Not so long ago I started working with Node.js. Great thing, I tell you! For example, having mastered some of its basic functions and connecting the necessary modules, you can automatically compress styles on your site, javascript, images and so on. Today I will talk about how in 1 hour I optimized all images of the site, namely 1215 pieces. All images were in the folder /upload/medialibrary/, Each one was in a separate folder. This situation is familiar to users of Wordpress and some other CMS. Control systems place each picture of each new post in a separate folder. In my case, there were 1200 folders with images. Doing all this by hand is simply irrational in terms of effort.

Looking ahead, I will say that before the optimization of the weight of the folder medialibrary was 121 Mb, after optimizing the folder's weight became 78 Mb. The difference is 43 Mb. Each image was on average 35% less and all this (!) absolutely without loss of quality!

About all this, I'll tell in order.

So, how to use Node.js to optimize all images on the site

First of all, we will need Node.js. Install it on the server. If you do not own a dedicated server, you will have to install it to your operating system and work with local files. I did everything through the console, directly on our dedicated server. Here is the site from which you can download and install Node.js: nodejs.org

For Windows users, I recommend downloading the most stable version: LTS. Next for Windows users, the instruction will be the same, with a slight difference: in advance you will need to download the folder with images to your computer. If you have root rights and you work directly on the server, then, of course, you do not need to download anything :)

We connect to the server through the console, using SSH.

Then install Node.js on the server:

If you have Linux based on Debian and Ubuntu, then the command in the console will be the next:

sudo apt-get install -y nodejs  

If you have other versions of Linux, then instead of apt-get use another installation command corresponding to the package manager of your server.

After installation, go one level above the root of our site and run the command:

npm init -y

With this command we create a configuration file package.json. This file will store information about installed packages, and you can fill in lines with a description of your project, the author and others. It's up to you, to do this, you do not need to do this.

Next we are interested in the service tinypng.com - one of the best services for image compression, without loss of quality. We are setting up an account on this service. This is necessary to obtain API key, which we will use a little later.

Now we need to install the tinify module for our Node. For this we execute in the console:

npm install --save tinify

After a successful installation, if you look at the file package.json, then in the section "dependencies" you will have a line: "tinify" and version number.

After that, in the same folder we are in, create a file, name it, for example: tinifyRecurse.js

Below I quote the contents of the file and a few comments.


var fs = require('fs');
var tinify = require("tinify");

// Below, instead of ... insert your tinify.key. You will see it on the Account page of the tinypng service. 
// To get to this page, click on the name of your account in the upper right corner of the screen
tinify.key = "..."; 

function getFiles(dir, files_) {
    files_ = files_ || [];
    var files = fs.readdirSync(dir); // read the entire contents of the file system, starting with the folder in which we will be at the time the script is executed
    for(var i in files) {
        var name = dir + '/' + files[i];
        if(fs.statSync(name).isDirectory()) { // if the loop element to be looped is a folder, then recursively call the same function
            getFiles(name, files_);
        } 
        else { // if the loop element being traversed is a file and if the file extension by pattern is lower
            if(~name.indexOf('.png') || ~name.indexOf('.jpg') || ~name.indexOf('.jpeg') || ~name.indexOf('.JPG')) {
                files_.push(name); // in the files_ array, we insert the name of this file
            }
        }
    }
    return files_;
}

var imgArr = getFiles('.'); // we call the function, in the form of a parameter, we pass the folder in which we will be at the time the script is executed

var imgArrLimit = []; // create an empty array to retrieve the file limit
// The fact is that on a free account tinify you can optimize not more than 500 images within a month
// so if you need to optimize more than 500 images, then you need to register several accounts for different mailboxes

for(let j in imgArr) { // sorting out all the images of our site
    if(j>=0 && j<500) { // set a limit of 500 at a time and make a selection of images from 0 to 499
        imgArrLimit.push(imgArr[j]); // insert them into the array imgArrLimit
    }
}

for(var i in imgArrLimit) { // We sort through all the files from the imgArrLimit array and optimize them
    source = tinify.fromFile(imgArrLimit[i]);
    source.toFile(imgArrLimit[i]);
}

// To find out the number of images on your site, uncomment the line below:
// console.log(imgArr.length);

Once we have created and saved the file, go to the console. We go to the folder of our site. Either in the root, or immediately in the folder in which you know that there are all the images of your site. And execute the command below, after specifying the correct path to the file tinifyRecurse.js, based on the root of your server. (To find out the path, in the folder with the tinifyRecurse.js file, run the following command in the console: pwd).

After the path is known, execute the command below, replacing the path to the file with the correct one:

node /home/bitrix/tinifyRecurse.js   

If the images on our site are more than 500, then after optimizing the first batch of images, register a second account на tinify.

Further:

  • In file tinifyRecurse.js change the key tinify.key to a new one;
  • Further in the code where we run a loop for(let j in imgArr) put instead of 0 and 500 digits 500 and 1000

Repeat the two operations above as many times as necessary in your case: a new API key -> a loop with a passage through five hundred new files.

As a result, all images of your site will be perfectly compressed, absolutely without loss of quality.

I will be happy if you succeed and you can optimize the images of your site!