简体   繁体   English

如何防止具有动态导入的 Gulp 任务异步执行?

[英]How can I prevent a Gulp task with a dynamic import from being asynchronous?

I want to use gulp-imagemin to minify images.我想使用 gulp-imagemin 来缩小图像。 The relevant part of my gulpfile.js looks like this:我的 gulpfile.js 的相关部分如下所示:

const gulp = require('gulp');
// a couple more require('')s

function minifyImages(cb) {
    import('gulp-imagemin')
        .then(module => {
            const imagemin = module.default;
            gulp.src('src/img/**/*')
                .pipe(imagemin())
                .pipe(gulp.dest('img'));
            cb();
        })
        .catch(err => {
            console.log(err);
            cb();
        });
}

function buildCSS(cb) { /* ... */ }

exports.build = gulp.series(buildCSS, minifyImages);

The reason I'm using a dynamic import here is because I think I have to - gulp-imagemin doesn't support the require('') syntax, and when I say import imagemin from 'gulp-imagemin I get an error saying "Cannot use import statement outside a module".我在这里使用动态导入的原因是因为我认为我必须 - gulp-imagemin 不支持require('')语法,当我说import imagemin from 'gulp-imagemin ,我收到一条错误消息“不能在模块外使用 import 语句”。

I would expect the build task to only finish after minifyImages has finished.我希望build任务仅在minifyImages完成后完成。 After all, I'm calling cb() only at the very end, at a point where the promise should be resolved.毕竟,我只是在最后才调用cb() ,在应该解析 promise 的位置。

However, build seems to finish early, while minifyImages is still running.但是, build似乎提前完成,而minifyImages仍在运行。 This is the output I get:这是我得到的 output:

[21:54:47] Finished 'buildCSS' after 6.82 ms
[21:54:47] Starting 'minifyImages'...
[21:54:47] Finished 'minifyImages' after 273 ms
[21:54:47] Finished 'build' after 282 ms
<one minute later>
[21:55:49] gulp-imagemin: Minified 46 images (saved 5.91 MB - 22.8%)

How can I make sure the task doesn't finish early, and all tasks are run in sequence?如何确保任务不会提前完成,并且所有任务都按顺序运行?

Let me know if there's something wrong with my assumptions;让我知道我的假设是否有问题; I'm somewhat new to gulp and importing.我对 gulp 和导入有些陌生。

Streams are always asynchronous, so if the cb() callback is called just after creating the gulp stream as in your then handler, it's only obvious that the stream by that time has not finished yet (in fact, it hasn't even started).流始终是异步的,因此如果在创建 gulp stream 之后调用cb()回调,就像在您的then处理程序中一样,很明显到那时 stream 还没有完成(事实上,它甚至还没有开始) .

The simplest solution to call a callback when the gulp.dest stream has finished is using stream.pipeline , ie:gulp.dest stream 完成时调用回调的最简单解决方案是使用stream.pipeline ,即:

function minifyImages(cb) {
    const { pipeline } = require('stream');
    return import('gulp-imagemin')
        .then(module => {
            const imagemin = module.default;
            pipeline(
                gulp.src('src/img/**/*'),
                imagemin(),
                gulp.dest('img'),
                cb
            );
        })
        .catch(cb);
}

Or similarly, with an async function.或者类似地,使用异步 function。

async function minifyImages(cb) {
    const { pipeline } = require('stream');
    const { default: imagemin } = await import('gulp-imagemin');
    return pipeline(
            gulp.src('src/img/**/*'),
            imagemin(),
            gulp.dest('img'),
            cb
    );
}

Another approach I have seen is to split the task in two sequential sub-tasks: the first sub-task imports the plugin module and stores it in a variable, and the second sub-task uses the plugin already loaded by the previous sub-task to create and return the gulp stream in the usual way.我看到的另一种方法是将任务拆分为两个连续的子任务:第一个子任务导入插件模块并将其存储在一个变量中,第二个子任务使用前一个子任务已经加载的插件以通常的方式创建和返回 gulp stream。 Then the two sub-tasks can be combined with gulp.series .然后两个子任务可以结合gulp.series

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM