Skip to content

Commit 3369eef

Browse files
committed
fix(shared-media-utils): use dynamic imports for ESM-only imagemin packages
imagemin-mozjpeg, imagemin-webp, imagemin-pngquant, and imagemin v8+ are ESM-only packages that cannot be require()'d from CJS output. The shared-media-utils package builds to CJS format, causing ERR_REQUIRE_ESM at runtime. Replace static imports with dynamic import() calls which work in both CJS and ESM contexts. Closes #1700
1 parent 239b654 commit 3369eef

1 file changed

Lines changed: 29 additions & 13 deletions

File tree

multimodal/tarko/shared-media-utils/src/ImageCompressor.ts

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,19 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
import imagemin from 'imagemin';
8-
import imageminPngquant from 'imagemin-pngquant';
9-
// @ts-expect-error
10-
import imageminMozjpeg from 'imagemin-mozjpeg';
11-
// @ts-expect-error
12-
import imageminWebp from 'imagemin-webp';
7+
// Use dynamic imports for ESM-only packages to ensure CJS compatibility
8+
async function loadImagemin() {
9+
return (await import('imagemin')).default;
10+
}
11+
async function loadPngquant() {
12+
return (await import('imagemin-pngquant')).default;
13+
}
14+
async function loadMozjpeg() {
15+
return (await import('imagemin-mozjpeg')).default;
16+
}
17+
async function loadWebp() {
18+
return (await import('imagemin-webp')).default;
19+
}
1320

1421
export interface ImageCompressionOptions {
1522
quality: number; // Compression quality (1-100)
@@ -48,8 +55,9 @@ export class ImageCompressor {
4855
* @param imageBuffer Image Buffer
4956
*/
5057
async compressToBuffer(imageBuffer: Buffer): Promise<Buffer> {
58+
const imagemin = await loadImagemin();
5159
// Choose appropriate compression plugin
52-
const plugins = this.getPluginsForFormat();
60+
const plugins = await this.getPluginsForFormat();
5361

5462
// Compress image
5563
return await imagemin.buffer(imageBuffer, {
@@ -60,22 +68,30 @@ export class ImageCompressor {
6068
/**
6169
* Select plugins based on target format
6270
*/
63-
private getPluginsForFormat() {
71+
private async getPluginsForFormat() {
6472
const quality = this.options.quality / 100; // Convert to 0-1 range (required by some plugins)
6573

6674
switch (this.options.format) {
67-
case 'jpeg':
75+
case 'jpeg': {
76+
const imageminMozjpeg = await loadMozjpeg();
6877
return [imageminMozjpeg({ quality: this.options.quality })];
69-
case 'png':
78+
}
79+
case 'png': {
80+
const imageminPngquant = await loadPngquant();
7081
return [
7182
imageminPngquant({
7283
quality: [quality, Math.min(quality + 0.2, 1)],
7384
}),
7485
];
75-
case 'webp':
76-
return [imageminWebp({ quality: this.options.quality })];
77-
default:
86+
}
87+
case 'webp': {
88+
const imageminWebp = await loadWebp();
7889
return [imageminWebp({ quality: this.options.quality })];
90+
}
91+
default: {
92+
const imageminWebpDefault = await loadWebp();
93+
return [imageminWebpDefault({ quality: this.options.quality })];
94+
}
7995
}
8096
}
8197

0 commit comments

Comments
 (0)