sindresorhus / gulp-imagemin

Minify PNG, JPEG, GIF and SVG images

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Custom plugin settings: TypeError: imagemin.<plugin name> is not a function

replete opened this issue · comments

Error

[18:25:48] TypeError: imagemin.optipng is not a function

Doesn't seem to detect any of the plugins and fails on whatever it hits first, in the above error imagemin.optipng. I've tried adding imagemin and imagemin-* packages to my repository, but this does not help.

My implementation appears to match the package expectations. Am I missing something here?

Environment

node v16.10.0
npm 7.24.0
macOS Catalina 10.15.7

gulpfile.js

// gulpfile.js
import gulp from 'gulp';
import gulpSass from 'gulp-sass';
import dartSass from 'sass';
import del from 'del';
import browserSync from 'browser-sync';
import imagemin from 'gulp-imagemin';
import fancyLog from 'fancy-log';

const sass = gulpSass(dartSass);
const browserSyncServer = browserSync.create('LocalDevServer');

const paths = {
    distributables: 'dist',
    documents: {
        source: 'src/**/*.html',
        destination: 'dist'
    },
    styles: {
        source: 'src/styles/**/*.scss',
        destination: 'dist/styles/'
    },
    scripts: {
        source: 'src/scripts/**/*.js',
        destination: 'dist/scripts'
    },
    images: {
        source: 'src/images/**/*.{png,jpg,jpeg,webp,gif}',
        destination: 'dist/images'
    }
}

fancyLog(typeof imagemin);

function clean() { 
    return del([paths.distributables]);
}

function documents() {
    return gulp.src(paths.documents.source,{since: gulp.lastRun(documents)})
        .pipe(gulp.dest(paths.documents.destination));
}

function styles() {
    return gulp.src(paths.styles.source)
        .pipe(sass.sync().on('error', sass.logError))
        // sass.sync() is faster than sass(): https://github.com/dlmanning/gulp-sass
        .pipe(gulp.dest(paths.styles.destination))
        .pipe(browserSyncServer.stream());
}

function scripts() {
    return gulp.src(paths.scripts.source)
        .pipe(gulp.dest(paths.scripts.destination));
}

function images() {
    return gulp.src(paths.images.source, {since: gulp.lastRun(images)})
        .pipe(imagemin([
            imagemin.optipng({ optimizationLevel: 5 }), 
            imagemin.svgo({
                plugins: [
                    { removeViewBox: true },
                    { cleanupIDs: false }
                ]
            }),
            imagemin.mozjpeg({ quality: 75, progressive: false })
        ]))
        .pipe(gulp.dest(paths.images.destination));
}

function watchFiles(done) {
    gulp.watch(paths.documents.source, gulp.series(documents, browserSyncReload));
    gulp.watch(paths.styles.source, styles);
    gulp.watch(paths.scripts.source, gulp.series(scripts, browserSyncReload));
    gulp.watch(paths.images.source, images);
    done();
}

function serve(done) {
    browserSyncServer.init({
        server: {
            baseDir: `${paths.distributables}`,
        },
        open: false
    });
    done();
}

function browserSyncReload(done) {
    browserSyncServer.reload();
    done();
}

const build = gulp.series(
    clean, 
    gulp.parallel(
        documents,
        styles, 
        scripts, 
        images
    )
);

const dev = gulp.series(
    clean, 
    build, 
    gulp.parallel(
        watchFiles, 
        serve
    )
);

export { 
    clean, 
    documents,
    styles, 
    scripts,
    images,
    watchFiles as watch,
    serve,
    build,
    dev
}
export default build;

package.json

// package.json
{
  "name": "frontend-boilerplate",
  "version": "1.0.0",
  "description": "Frontend boilerplate 2021",
  "main": "gulpfile.js",
  "type": "module",
  "scripts": {
    "start": "gulp dev"
  },
  "keywords": [
    "frontend",
    "javascript",
    "gulp"
  ],
  "author": "Phil Ricketts",
  "license": "UNLICENSED",
  "homepage": "https://github.com/replete/frontend-boilerplate#readme",
  "devDependencies": {
    "browser-sync": "^2.27.5",
    "del": "^6.0.0",
    "fancy-log": "^1.3.3",
    "gulp": "^4.0.2",
    "gulp-imagemin": "^8.0.0",
    "gulp-sass": "^5.0.0",
    "sass": "^1.42.1"
  }
}

Workaround solution

The problem is resolved by importing the imagemin modules directly after adding the packages to the local project.

I guess the fix is to either update the docs, or move the imagemin from optionalDependencies into devDependencies?

package.json

  "devDependencies": {
    "browser-sync": "^2.27.5",
    "del": "^6.0.0",
    "fancy-log": "^1.3.3",
    "gulp": "^4.0.2",
    "gulp-imagemin": "^8.0.0",
    "gulp-sass": "^5.0.0",
+  "imagemin": "^8.0.1",
+  "imagemin-mozjpeg": "^9.0.0",
+  "imagemin-optipng": "^8.0.0",
+  "imagemin-svgo": "^10.0.0",
    "sass": "^1.42.1"
  }

gulpfile.js diff

 import gulpSass from 'gulp-sass';
 import dartSass from 'sass';
 import del from 'del';
 import browserSync from 'browser-sync';
 import imagemin from 'gulp-imagemin';
+import imageminOptipng from 'imagemin-optipng';
+import imageminSvgo from 'imagemin-svgo';
+import imageminMozjpeg from 'imagemin-svgo';
 import fancyLog from 'fancy-log';


 function images() {
     return gulp.src(paths.images.source, {since: gulp.lastRun(images)})
+        .pipe(imagemin([
+            imageminOptipng({ optimizationLevel: 5 }),
+            imageminSvgo({
+                plugins: [
+                    { removeViewBox: true },
+                    { cleanupIDs: false }
+                ]
+            }),
+            imageminMozjpeg({ quality: 75, progressive: false })
+        ]))
         .pipe(gulp.dest(paths.images.destination));
 }

Although this workaround introduces this deprecation warning from imagemin-svgo. I will raise an issue there and link to this issue.

(node:28326) [DEP0151] DeprecationWarning: No "main" or "exports" field defined in the package.json for /Users/user/dev/frontend-boilerplate/node_modules/imagemin-svgo/ resolving the main entry point "index.js", imported from /Users/user/dev/frontend-boilerplate/gulpfile.js.