运行`gulp`命令时出现`错误[ERR_REQUIRE_ESM]`。

16

我是Gulp的新手,正在尝试自动化一些任务。这是我的环境设置:npm版本:8.1.0node版本:17.0.1gulp CLI版本:2.3.0gulp版本:4.0.2

这是我的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
);

当我在终端中尝试运行gulp命令时,出现了以下错误: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.

enter image description here

我尝试了一些解决方案,比如在package.json中添加type:"module"并使用import代替require(),但是我无法让它正常工作。那么我该怎么解决这个问题呢?谢谢!

5个回答

29

是的,我已经得到了解决方案,但还是谢谢你的回答。 - Bipul Roy
11
npm install --save-dev gulp-imagemin@7.1.0 - Bipul Roy
1
锁定依赖版本只是一个勉强的解决方法。解决方案应该是展示如何将GULP文件转换为ESM。 - noraj
1
@BipulRoy,您能分享一下您的解决方案吗?我也遇到了同样的问题。 - Shiplu
7.1.0存在漏洞。 - Takeshi Tokugawa YD

11
转移到类似这样的东西可能会起作用:
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';

我已经写了一份指南:将gulpfile从CommonJS(CJS)迁移到ECMAScript模块(ESM)


我相信这个链接可能应该替换掉这个答案的文本,以避免链接失效。 - bric3

1
根据Node.js文档,Node.js有两个模块系统:CommonJS模块和ECMAScript模块。
您可以通过文件扩展名.mjs、package.json的"type"字段或--input-type标志告诉Node.js使用ECMAScript模块加载器。在这些情况之外,Node.js将使用CommonJS模块加载器。了解更多详情请参见确定模块系统。
因此,基本上使用ES6语法并将文件扩展名改为.mjs,这样Node.js会将该文件视为ECMA文件。
import gulp from 'gulp';
import imagemin from 'gulp-imagemin';

export default () =>
  gulp
    .src('public/media/**/*')
    .pipe(imagemin())
    .pipe(gulp.dest('dist/public/media'));

0

虽然我已经添加了上述作为潜在解决方案,但我的个人偏好是从CommonJS到ESM(require => import)进行完整的迁移。这可能并不总是完全简单,也因为Node.js LTS刚刚改变为18,可能会产生一些破坏性的变化,但如果您迁移到ESM,您将拥有更长时间的可支持性。 - MikeMcC399

0
另一个选项: 您需要切换到使用动态import()语法而不是require()。但是,在gulpfile中,这可能有点棘手,因为动态导入返回一个promise,而Gulp通常希望立即可用的东西。
以下是如何在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;

这种方式可以在加载gulpfile时异步导入gulp-imagemin,然后在任何任务运行时都可用。但请注意,如果您在启动脚本后立即运行gulp images,则gulp-imagemin可能尚未加载。您应确保在启动Gulp任务之前加载所有导入项。

如果您发现这种方法过于复杂或容易出错,另一种解决方案是坚持使用您的依赖项的CommonJS模块版本,而不是ES模块,就像其他答案中描述的那样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接