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.