Use imagemin to compress and optimize a large number of images at once!

We use imagemin as a way to optimize a number of images by compressing to show web pages. Then the lighthouse won't complaint of insufficient compression. However, other issues, such as image scaling, need to be resolved separately.

Image compression

Background

If you're building a blog or web application, you inevitably need to use images. If you don't do this, downloading images becomes a bottleneck when displaying a web page, and It would be nice if the age of 5G would come, but it's not. Not all users can benefit from 5G, so for the time being, image optimization is a necessary task and be.

Find the image, then cut and scale it down to the appropriate size, and finally compress it. Various tools are available as software and online tools for compression, but there are pros and cons.

  • Photoshop

    When it comes to working with images in a comprehensive way, Photoshop is unbeatable, but the paid tool Therefore, it is necessary to make a big decision for personal use, and even if you use it in a company, you have to know how to make a request for approval. You will be wondering if you should go through with it. But once you use it, it will be difficult to get out of it because of its convenience and efficiency.

  • GIMP

    Photoshop has always been an expensive tool. So, as a free Photoshop-like product, GIMP has been available for more than 20 years. It exists. The feel is much improved compared to the original, but compared to Photoshop, it's inevitably It's not as good as it could be. I don't need to do any advanced work on my images, but I will only compress them. However, when I compress them in GIMP, I can't help but notice that I can't get the image to meet the Lighthouse score. I couldn't make the file easy. This is the reason why I decided to create the content for this article.

  • Optimizilla

  • TinyPng
  • I love IMG

    If you search, this area comes up at the top of Google. There are many other sites. You can even resize some sites. The compression ratio is up to the site. One of the main concerns with online tools is the handling of uploaded images, and you'll need to be careful about how you handle them. You don't need to be aware of this. You don't need to be aware of free images, but you can use images that you own the copyright to or Consideration must be given to special images, such as images that have been purchased and images that are confidential to the company. The Terms of Service will give you some idea of what to expect, but it's important to note that it's not always easy to comply with the Whether they are or not is a different matter. Most sites are not audited like the big companies are, so it's up to the user to decide which ones to believe. The situation is left to the

  • imagemin

    There are many programs that you can run in your own environment (local environment). Of course, it would be fun to write a program to handle images from scratch, but there is a lot of learning It is preferable to have a ready-to-use tool other than imagemin has been in use for a long time, is stable, and is in continuous development, so you can be assured that it will be a library that you will be able to use.

    The advantages of imagemin are that the images will not be leaked, the parameters can be changed and manipulated freely, and it can be automated in combination with other programs.

Install imagemin

  1. Install NodeJS

    Please download the installer at nodejs.org and install it。I could recommend you to use version 12.18.0 LTS.

  2. Decide your working directory.

    Here, it is C:/home/test/compression.

  3. Open the command prompt and move the above directory.

    cd C:/home/test/compression
  4. Create a project.

    Don't mind the detail. You can change the content whenever you want.

    npm init -y
  5. Install imagemin

    npm install -D imagemin imagemin-jpegtran imagemin-pngquant
    • imagemin is a main library
    • imagemin-jpegtran is a plugin to treat JPEG files.
    • imagemin-pngquant is a plugin to treat PNG files.
    • There are various plugins such as treating svg, gif, webp etc.You can find plugins at this page
  6. Make the starter program.

    Create a file called demo01.js directly under the project and copy and paste the following contents. In this case, the absolute path of the file would be C:/home/test/compression/demo01.js.

    const fs = require("fs");
    const path = require("path");
    const imagemin = require("imagemin");
    const imageminJpegtran = require("imagemin-jpegtran");
    const imageminPngquant = require("imagemin-pngquant");
    
    (async () => {
      const files = await imagemin(["demo/*.{jpg,png,JPG,PNG}"], {
        destination: "dest",
        plugins: [
          imageminJpegtran(),
          imageminPngquant({
            quality: [0.6, 0.8],
          }),
        ],
      });
    
      console.log(files);
    })();
  7. Prepare images.

    1. Create a demo folder and put a JPEG or PNG image in it directly under the project. Any number is possible.
    2. If there is no output destination, it will be generated automatically.
  8. Run the program.

    node demo01.js

    When executed, the following characters will be output.

    [{data: <Buffer 89 50 4e …>, destinationPath: 'build/images/foo.jpg'}, …]

    In addition, there is a compressed file in the dest folder with the same name as the original file.

    If you set the destination to the same folder as the input file (demo), the source images will be overwritten.

Up to this point, the basic contents are over.

Advanced

Compress images by searching folders recursively

In the case of the above program, only files in the same folder were targeted. Instead, what if you want to target all files under that folder? I guess.

One way is to change the point where you specify the input file to "demo/**/*. {jpg,png,jpg,jpg,png}".

const files = await imagemin(["demo/**/*.{jpg,png,JPG,PNG}"], {
  destination: "dest",
  plugins: [
    // ...
  ],
});

All JPEG and PNG files in the current folder will be processed . This specification is in glob format.

The problem with this approach is that all the compressed files go into the demo folder. The original folder structure is not preserved.

So, we specify each destination by running the process one folder at a time.

  1. Recursively get the paths under a certain folder. The result is an array called ["demo", "demo/001", "demo/002"].

    const getDirRecursively = (dir) => {
      const getChildrenRecursively = (dir) => {
        // Get child directories under the dir.
        const readdir = fs
          .readdirSync(dir, { withFileTypes: true })
          .filter((d) => d.isDirectory());
    
        if (readdir.length === 0) {
          // There're no directories under the dir.
          return dir;
        } else {
          // Get directories recursively. Require >=Node11
          return readdir
            .map((p) => getChildrenRecursively(`${dir}/${p.name}`))
            .flat();
        }
      };
      return [dir, ...getChildrenRecursively(dir)];
    };
  2. Perform compression for each folder. In addition, make the files hold the compressed result as an array for later renaming. It is important to note that we are creating a destDir.

    (async () => {
      const files = [];
      const sourceDirs = getDirRecursively("demo");
      for (let inDir of sourceDirs) {
        // Make output path: demo/001 => dest/demo/001
        const destDir = "dest/" + inDir;
        const filesInDir = await imagemin([`${inDir}/*.{jpg,png,JPG,PNG}`], {
          destination: destDir,
          plugins: [
            imageminJpegtran(),
            // @ts-ignore
            imageminPngquant({
              quality: [0.6, 0.8],
            }),
          ],
        });
        files.push(...filesInDir);
      }
    })();
  3. Rename the last compressed file. Here, xxx.jpg is referred to as xxx.min.jpg.

    files.map((file) => {
      const ext = path.extname(file.destinationPath);
      const filename = path.basename(file.destinationPath, ext);
      const newPath = path.join(
        path.dirname(file.destinationPath),
        `${filename}.min${ext}`
      );
      fs.renameSync(file.destinationPath, newPath);
    });
  4. It's a long story, but overall it looks like this Compresses an image by looking under the demo folder recursively. The compressed files are outputted under the dest/demo folder.

    const fs = require("fs");
    const path = require("path");
    const imagemin = require("imagemin");
    const imageminJpegtran = require("imagemin-jpegtran");
    const imageminPngquant = require("imagemin-pngquant");
    
    const getDirRecursively = (dir) => {
      const getChildrenRecursively = (dir) => {
        // Get child directories under the dir.
        const readdir = fs
          .readdirSync(dir, { withFileTypes: true })
          .filter((d) => d.isDirectory());
    
        if (readdir.length === 0) {
          // There're no directories under the dir.
          return dir;
        } else {
          // Get directories recursively. Require >=Node11
          return readdir
            .map((p) => getChildrenRecursively(`${dir}/${p.name}`))
            .flat();
        }
      };
      return [dir, ...getChildrenRecursively(dir)];
    };
    
    (async () => {
      const files = [];
      const sourceDirs = getDirRecursively("demo");
      console.log("sourceDirs", sourceDirs);
      for (let inDir of sourceDirs) {
        // Make output path: demo/001 => dest/demo/001
        const destDir = "dest/" + inDir;
        const filesInDir = await imagemin([`${inDir}/*.{jpg,png,JPG,PNG}`], {
          destination: destDir,
          plugins: [
            imageminJpegtran(),
            // @ts-ignore
            imageminPngquant({
              quality: [0.6, 0.8],
            }),
          ],
        });
        files.push(...filesInDir);
      }
    
      // Rename file
      files.map((file) => {
        const ext = path.extname(file.destinationPath);
        const filename = path.basename(file.destinationPath, ext);
        const newPath = path.join(
          path.dirname(file.destinationPath),
          `${filename}.min${ext}`
        );
        fs.renameSync(file.destinationPath, newPath);
      });
    })();

Finally

You can do a lot of things with this one. There are issues with IE and Safari, but converting to Webp is also easy.

See you!

Updated at: Thu Jun 25 2020

© 2020-presentTerms|Privacy