Why compress images

Images are a very important part of a website and can be compressed automatically through scripts. And a wave of performance. It’s a treat.

Image loading speed has a great impact on user experience, and image compression is the most effective way to improve the loading speed. Today I recommend a lossless compression tool: Tinify (panda).

Tinify use

Just drag the image in and download the compressed image.Existing problems:

  1. Many people are not in the habit of pre-development compression.
  2. How to deal with the pictures that the project has accumulated. (The project had accumulated thousands of images while I was doing it)

Automated compression (Tinify inherited into the project)

Goal: To compress images in the project by executing NPM Run Tinify in the root directory.

1. Install Tinify and MD5

npm i tinify md5
Copy the code

2. Preparation

  1. Create a new tinify.js file
  2. Tinify is introduced for compression, FS reads files and Glob obtains all image paths.
  3. You can apply for KEYS from the official website. Details can be found at the end of this article.
  4. KeyIndex determines the number of keys to be used, total records the total number of files to be compressed, and handleCount records how many files are currently compressed.
const tinify = require('tinify');
const fs = require('fs');
const glob = require('glob');

const KEYS = [
  "4HMC1HrQjWcvg1TTd5q7l47BhZmc8GBV"."R4QKQm0mnBSyb28jpRpzTtRrbGMxMGQZ"."z4ZPxWYGX6t5cxfR2g7T7j9JZ1M5l5V1",];let keyIndex = 0;
let total = 0;
let handleCount = 0; // Number of files processed
Copy the code

3. Determine the amount of key

  1. Inject keys (each key is 500);
  2. How much is left to obtain the current key compressionCount;
  3. When compressionCount is greater than 400, keyIndex++ uses the next key, keyIndex > keys. length, error “Tinify is insufficient, please add key!” ;
  4. When compressionCount is less than 400, checkFile is executed.
// Start the task
const startTask = () = > {
  const key = KEYS[keyIndex];
  tinify.key = key;
  tinify.validate(err= > {
    const { compressionCount = 500 } = tinify;

    // The maximum amount is 500, 100 is reserved before processing
    if (compressionCount < 400) {
      checkFile();
    } else {
      keyIndex++;
      if (keyIndex < KEYS.length) {
        startTask();
      } else {
        throw new Error('Tinify quota is insufficient, please add KEY! '); }}}); };Copy the code

4. Read all images

  1. Glob. sync reads all images in the directory
  2. List. filter filters out images that are too small to compress
  3. DoTinify compression is performed to read files based on the path
const checkFile = () = > {
  let list = glob.sync('./src/**/*.@(png|jpg|jpeg)');
  // Files larger than 4K are not compressed
  list = list.filter((i) = >fs.statSync(i)? .size >10000)
  // Number of files to be processed
  total = list.length;
  list.forEach(path= > {
    const key = path.replace('./src/'.' ');
    fs.readFile(path, (err, buf) = > {
        doTinify(key, path, buf);
    });
  });
};
Copy the code

5. Perform compression

  1. Tinify. FromBuffer (buf) performs compression
  2. ToBuffer returns a compressed file stream
  3. Fs. writeFile overwrites the file stream to the original file
const doTinify = (key, path, buf) = > {
  tinify.fromBuffer(buf).toBuffer((err, result) = > {
    handleCount++;
    // Overwrite the source file
    fs.writeFile(path, result);
  });
};
Copy the code

6. Add the script to package.json

Don’t write path wrong, you can compress the code. But we still have to optimize.

 "tinify": "node ./scripts/tinify.ts"
Copy the code

7. Use MD5 to optimize

  1. The introduction of the md5
  2. Create a tinifymd5.json file and mark the compressed file according to the directory to avoid repeated compression

Specific use can see all the code:

All the code

const tinify = require('tinify');
const fs = require('fs');
const glob = require('glob');
const md5 = require('md5');
const configPath = './scripts/tinifymd5.json';

// Read the compressed file MD5
const tinifyMd5 = JSON.parse(fs.readFileSync(configPath).toString());

const KEYS = [
  "4HMB1HrQjWcvg1TTd5q7l47BhZmc8GBV"."R4QGQm0mnBSyb28jpRpzTtRrbGMxMGQZ"."z4ZRxWYGX6t5cxfR2g7T7j9JZ1M5l5V1",];let keyIndex = 0;
let total = 0;
let handleCount = 0; // Number of files processed

// Start the task
const startTask = () = > {
  const key = KEYS[keyIndex];
  tinify.key = key;
  tinify.validate(err= > {
    const { compressionCount = 500 } = tinify;

    if (err) {
      console.log(`[error] ${key}`.String(err));
    } else {
      console.log(`[compressionCount] ${key}`, compressionCount);
    }

    // The maximum amount is 500, 100 is reserved before processing
    if (compressionCount < 400) {
      checkFile();
    } else {
      keyIndex++;
      if (keyIndex < KEYS.length) {
        startTask();
      } else {
        console.log("Encountered an error to see documentation: http://wiki.duxiaoman-int.com/pages/viewpage.action?pageId=168130093")
        throw new Error('Tinify quota is insufficient, please add KEY! '); }}}); };// Check whether compression is required
const checkFile = () = > {
  let list = glob.sync('./src/**/*.@(png|jpg|jpeg)');
  // Files larger than 4K are not compressed
  list = list.filter((i) = >fs.statSync(i)? .size >10000)
  // Number of files to be processed
  total = list.length;
  list.forEach(path= > {
    const key = path.replace('./src/'.' ');
    fs.readFile(path, (err, buf) = > {
      if(tinifyMd5[key] ! == md5(buf) && ! err) { doTinify(key, path, buf); }else {
        console.log(`${err ? 'Error' : 'Ignore'}: ${key} ${err || ' '}`);
        handleCount++;
        updateTinifyMd5()
      }
    });
  });
};

const doTinify = (key, path, buf) = > {
  tinify.fromBuffer(buf).toBuffer((err, result) = > {
    handleCount++;
    if (err) {
      console.log(`Error: ${err} ${key}`);
      updateTinifyMd5()
    } else {
      // Overwrite the source file
      fs.writeFile(path, result, () = > {
        / / update md5
        tinifyMd5[key] = md5(result);
        console.log('Tinified: '+ key); updateTinifyMd5() }); }}); };function updateTinifyMd5() {
  if (handleCount === total) {
    console.log("Encountered an error to see documentation: http://wiki.duxiaoman-int.com/pages/viewpage.action?pageId=168130093")
    fs.writeFileSync(configPath, JSON.stringify(tinifyMd5, null.2));
  }
}

startTask();
Copy the code

Key Usage Rules

Apply for an account by email

  1. Each account has a monthly quota of 500
  2. Each account can apply for more than one key, and each key will be invalid after being used 500 times.
  3. The total number of keys used cannot exceed 500 per month

To get the key

Search dashboard in the “I enter” page and click to enter the management background. You can apply for a key.