Reputation: 566
I'm new to Gulp
and trying to automate some tasks. Here's my environment setup: npm version: 8.1.0
, node version 17.0.1
, gulp CLI version 2.3.0
and gulp version 4.0.2
And here's my gulpfile.js
:
// list of dependencies ( things require to run the below funcitions)
const { src, dest, watch, series } = require('gulp');
const sass = require('gulp-sass');
const prefix = require('gulp-autoprefixer');
const minify = require('gulp-clean-css');
const terser = require('gulp-terser');
const imagemin = require('gulp-imagemin');
const imagewebp = require('gulp-webp');
// create functions
// SCSS
function compilescss() {
return src('src/scss/*.scss')
.pipe(sass())
.pipe(prefix('last 2 versions'))
.pipe(minify())
.pipe(dest('/dist/css'))
}
// JS
function jsmin(){
return src('src/js/*.js')
.pipe(terser())
.pipe(dest('dist/js'))
}
// images
function optimizeimg() {
return src('src/img/*.{jpg,png}')
.pipe(imagemin([
imagemin.mozjpeg({quality: 80, progressive: true}),
imagemin.optipng({optiminzationLevel: 2})
]))
.pipe(dest('dist/img'))
}
// webp images
function webpImage() {
return src('dist/img/*.{jpg, png}')
.pipe(imagewebp())
.pipe('dist/img')
}
// create watchlist
function watchTask(){
watch('src/scss/*.scss', compilescss);
watch('src/js/*.js', jsmin);
watch('src/img/*.{jpg,png}', optimizeimg);
watch('dist/img/*.{jpg,png}', webpImage);
}
// default gulp
exports.default = series(
compilescss,
jsmin,
optimizeimg,
webpImage,
watchTask
);
When I'm trying to run gulp
command in the terminal. I'm getting errors like - Error [ERR_REQUIRE_ESM]: require() of ES Module E:\Projects\portfolio\node_modules\gulp-imagemin\index.js from E:\Projects\portfolio\gulpfile.js not supported.
I've tried solutions like - adding type:"module"
in package.json and instead of require()
used import
but I couldn't make it work. So how can I fix this??? Thanks!
Upvotes: 19
Views: 28963
Reputation: 9
I was getting the same error so first go through the npm doc of the gulp plugin and see if there is an addition change. Also for now try this
const sass = require('gulp-sass')(require('sass'));
instead of
const sass = require('gulp-sass');
Upvotes: 0
Reputation: 736
Another option: You'll need to switch to using dynamic import() syntax instead of require(). However, in a gulpfile, this can be a bit tricky because dynamic imports return a promise, and Gulp is generally expecting things to be available immediately.
Here's how you can use dynamic imports with gulp-imagemin:
let imagemin;
import('gulp-imagemin').then((gulpImagemin) => {
imagemin = gulpImagemin;
});
const images = () => {
if (!imagemin) {
throw new Error('gulp-imagemin not loaded');
}
return gulp.src('src/images/**/*')
.pipe(imagemin())
.pipe(gulp.dest('dist/images'));
};
exports.images = images;
This way, gulp-imagemin is imported asynchronously when the gulpfile is loaded, and then it's available by the time any tasks run. But note that if you run gulp images immediately after starting your script, gulp-imagemin might not have loaded yet. You should ensure all your imports are loaded before starting your Gulp tasks.
If you find this approach to be too complex or error-prone, another solution is to stick with versions of your dependencies that are CommonJS modules, not ES modules, as some other answers described above.
Upvotes: 0
Reputation: 355
The (currently) latest gulp-imagemin (v8.0.0) version is a pure ESM package according to the v8.0.0 release notes. A solution to this issue using dynamic import has been posted to How to import a Javascript file that is ESM from a CommonJS module? Gulp. Error: [ERR_REQUIRE_ESM].
Upvotes: 1
Reputation: 3271
According to node docs Node.js has two module systems: CommonJS modules and ECMAScript modules.
You can tell Node.js to use the ECMAScript modules loader via the .mjs file extension, the package.json "type" field, or the --input-type flag. Outside those cases, Node.js will use the CommonJS module loader. See Determining module system for more details.
So basically use es6 syntax and rename the file extension to .mjs this way node treats this file as ECMA
import gulp from 'gulp';
import imagemin from 'gulp-imagemin';
export default () =>
gulp
.src('public/media/**/*')
.pipe(imagemin())
.pipe(gulp.dest('dist/public/media'));
Upvotes: 2
Reputation: 4662
Moving to something like that would probably work:
import gulp from 'gulp';
const { src, dest, watch, series } = gulp;
import dartSass from 'sass';
import gulpSass from 'gulp-sass';
const sass = gulpSass(dartSass);
import prefix from 'gulp-autoprefixer';
import minify from 'gulp-clean-css';
import terser from 'gulp-terser';
import imagemin from 'gulp-imagemin';
import imagewebp from 'gulp-webp';
I have made a guide: Moving gulpfile from CommonJS (CJS) to ECMAScript Modules (ESM)
Upvotes: 13
Reputation: 786
gulp-imagemin 8.0.0 and above are now ESM only. You can downgrade gulp-imagemin to 7.1.0 which is commonjs and it should work fine.
This package is now pure ESM. Please read this.
https://github.com/sindresorhus/gulp-imagemin/releases/tag/v8.0.0
Upvotes: 30