trying to convert images to webp with imagemin-webp but not working

1.9k Views Asked by At

I found a code in a website for converting png, jpg to webp but it doesnt work for me. I have two jpg files in /images/ folder

const imagemin = require("imagemin"),
  webp = require("imagemin-webp");
const outputFolder = "./images/webp";
const produceWebP = async () => {
  await imagemin(["images/*.png"], {
    destination: outputFolder,
    plugins: [
      webp({
        lossless: true,
      }),
    ],
  });
  console.log("PNGs processed");
  await imagemin(["images/*.{jpg,jpeg}"], {
    destination: outputFolder,
    plugins: [
      webp({
        quality: 65,
      }),
    ],
  });
  console.log("JPGs and JPEGs processed");
};
produceWebP();

When i run node index.js i take the message you see in the photo

enter image description here

1

There are 1 best solutions below

2
On BEST ANSWER

The issue here is in Error [ERR_REQUIRE_ESM]: Must use import to load ES Module.

There are two types of modules in NodeJS: CommonJS and ECMAScript modules (ESM).

CommonJS uses const webp = require("imagemin-webp") syntax.

While ESM uses import webp from "imagemin-webp" syntax to achieve the same result.

Your index.js is CommonJS and the imagemin npm module is ESM and the error ocures when you try to use require() call to import ESM module.

There are two possible solutions for this:

  • convert your index.js from CommonJS to ESM (preferred)
  • use asynchronous import() call instead of require() to import ESM module from CommonJS

First (and preferred) option is to convert your code to ESM:

  • rename index.js to index.mjs (.mjs extension indicates ESM syntax)
  • change all require() calls to import something from 'library' calls
  • run it as node index.mjs

index.mjs:

// using ES import syntax here
import imagemin from "imagemin";
import webp from "imagemin-webp";
// the rest of the file is unchanged
const outputFolder = "./images/webp";
const produceWebP = async () => {
    await imagemin(["images/*.png"], {
        destination: outputFolder,
        plugins: [
            webp({
                lossless: true,
            }),
        ],
    });
    console.log("PNGs processed");
    await imagemin(["images/*.{jpg,jpeg}"], {
        destination: outputFolder,
        plugins: [
            webp({
                quality: 65,
            }),
        ],
    });
    console.log("JPGs and JPEGs processed");
};
produceWebP();

Second option is to use asynchronous import() call to import ESM modules from CommonJS module as indicated in NodeJS docs.

It is not preferred because import() is asynchronous, I'd like to use await to get the result like await import() but this in-turn requires to be called inside another async function.

index.js:

const outputFolder = "./images/webp";
const produceWebP = async () => {
    // Load ESM modules using import(),
    // it returns a Promise which resolves to
    // default export as 'default' and other named exports.
    // In this case we need default export.
    const imagemin = (await import("imagemin")).default;
    const webp = (await import("imagemin-webp")).default;
    await imagemin(["images/*.png"], {
        destination: outputFolder,
        plugins: [
            webp({
                lossless: true,
            }),
        ],
    });
    console.log("PNGs processed");
    await imagemin(["images/*.{jpg,jpeg}"], {
        destination: outputFolder,
        plugins: [
            webp({
                quality: 65,
            }),
        ],
    });
    console.log("JPGs and JPEGs processed");
};
produceWebP();

P.S. Please note that ESM can export more than one entry (default and named exports) while CommonJS can only export one entry.