Gulp 4 выдает ошибку

134
19 июня 2019, 13:40

Исходники: Gulp4.zip

Ошибка:

assert.js:42
  throw new errors.AssertionError({
  ^
AssertionError [ERR_ASSERTION]: Task function must be specified
    at Gulp.set [as _setTask] (E:\Web\test\node_modules\undertaker\lib\set-task.js:10:3)
    at Gulp.task (E:\Web\test\node_modules\undertaker\lib\task.js:13:8)
    at Object.<anonymous> (E:\Web\test\gulpfile.js:224:6)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)

Версия Gulp:

PS E:\Web\test> gulp -v
[06:20:13] CLI version 2.0.1
[06:20:13] Local version 4.0.0

Версия Npm:

PS E:\Web\test> npm -v
6.5.0

package.json

{ 
  "name": "html-ready", 
  "version": "1.0.0", 
  "description": "", 
  "main": "gulpfile.js", 
  "scripts": { 
    "test": "echo \"Error: no test specified\" && exit 1" 
  }, 
  "author": "Devinora", 
  "license": "ISC", 
  "devDependencies": { 
    "@babel/core": "^7.2.0", 
    "@babel/preset-env": "^7.2.0", 
    "babel-cli": "^6.26.0", 
    "babel-core": "^6.26.3", 
    "browser-sync": "^2.26.3", 
    "gulp": "^4.0.0", 
    "gulp-autoprefixer": "^6.0.0", 
    "gulp-babel": "^8.0.0", 
    "gulp-file-include": "^2.0.1", 
    "gulp-imagemin": "^5.0.3", 
    "gulp-minify-css": "^1.2.4", 
    "gulp-plumber": "^1.2.1", 
    "gulp-rename": "^1.4.0", 
    "gulp-sass": "^4.0.2", 
    "gulp-sourcemaps": "^2.6.4", 
    "gulp-terser": "^1.1.6", 
    "gulp-watch": "^5.0.1", 
    "gulp.spritesmith": "^6.9.0", 
    "imagemin-pngquant": "^6.0.0", 
    "rimraf": "^2.6.2" 
  }, 
  "dependencies": { 
    "npm": "^6.5.0" 
  } 
}

gulpfile.js

'use strict'; 
 
var gulp = require('gulp'), 
  watch = require('gulp-watch'), 
  plumber = require('gulp-plumber'), 
  prefixer = require('gulp-autoprefixer'), 
  babel = require('gulp-babel'), 
  terser = require('gulp-terser'), //альтернатива gulp-uglifyes 
  sass = require('gulp-sass'), 
  sourcemaps = require('gulp-sourcemaps'), 
  fileinclude = require('gulp-file-include'), 
  cssmin = require('gulp-minify-css'), 
  imagemin = require('gulp-imagemin'), 
  pngquant = require('imagemin-pngquant'), 
  rimraf = require('rimraf'), 
  browserSync = require("browser-sync"), 
  rename = require('gulp-rename'), 
  spritesmith = require('gulp.spritesmith'), 
  reload = browserSync.stream; 
 
var path = { 
  dist: { 
    html: 'dist/', 
    php: 'dist/', 
    js: 'dist/js/', 
    css: 'dist/css/', 
    img: 'dist/img/', 
    fonts: 'dist/fonts/' 
  }, 
  app: { 
    html: 'app/*.html', 
    php: 'app/*.php', 
    js: 'app/js/main.js', 
    jsInit: 'app/js/init.js', 
    style: 'app/scss/main.scss', 
    sprite: 'app/img/sprite/**/*.*', 
    img: 'app/img/*.*', 
    fonts: 'app/fonts/**/*.*', 
  }, 
  watch: { 
    html: 'app/**/*.html', 
    php: 'app/*.php', 
    js: 'app/js/**/*.js', 
    style: 'app/scss/**/*.scss', 
    img: 'app/img/*.*', 
    sprite: 'app/img/sprite/**/*.*', 
    fonts: 'app/fonts/**/*.*' 
  }, 
  export: { 
    img: 'app/img/', 
    style: 'app/scss/imports/' 
  }, 
  spriteTemplate: 'sass.template.mustache', 
  clean: './dist' 
}; 
 
var config = { 
  server: { 
    baseDir: "dist" // or ./dist 
  }, 
  // tunnel: true, 
  // host: "178.150.110.97", 
  // notify: false, 
  logPrefix: "Frontend_Devil" 
}; 
 
gulp.task('webserver', function() { 
  browserSync(config); 
}); 
 
gulp.task('clean', function(cb) { 
  rimraf(path.clean, cb); 
}); 
 
gulp.task('html:dist', function() { 
  gulp.src(path.app.html) 
    .pipe(plumber()) 
    .pipe(fileinclude({ 
      prefix: '@@', 
      basepath: '@file' 
    })) 
    .pipe(gulp.dest(path.dist.html)) 
    .pipe(reload()); 
}); 
 
gulp.task('php:dist', function() { 
  gulp.src(path.app.php) 
    .pipe(plumber()) 
    .pipe(fileinclude({ 
      prefix: '@@', 
      basepath: '@file' 
    })) 
    .pipe(gulp.dest(path.dist.php)) 
    .pipe(reload()); 
}); 
 
gulp.task('js:dist', function() { 
  //init.js 
  //Файл для инициации 
  // gulp.src(path.app.jsInit) 
  // .pipe(plumber()) 
  // .pipe(sourcemaps.init()) 
  // .pipe(fileinclude({ 
  // 	prefix: '@@', 
  // 	basepath: '@file' 
  // })) 
  // .pipe(babel({ 
  // 	presets: ["@babel/preset-env"] 
  // })) 
  // .pipe(terser()) 
  // .pipe(sourcemaps.write()) 
  // .pipe(rename({suffix: '.babel-min', prefix : ''})) 
  // .pipe(gulp.dest(path.dist.js)) 
 
  //Обычный js файл. 
  gulp.src(path.app.js) 
    .pipe(plumber()) 
    .pipe(sourcemaps.init()) 
    .pipe(fileinclude({ 
      prefix: '@@', 
      basepath: '@file' 
    })) 
    .pipe(sourcemaps.write()) 
    .pipe(gulp.dest(path.dist.js)) 
  //Babel-js файл. 
  gulp.src(path.app.js) 
    .pipe(plumber()) 
    .pipe(sourcemaps.init()) 
    .pipe(fileinclude({ 
      prefix: '@@', 
      basepath: '@file' 
    })) 
    .pipe(babel({ 
      presets: ["@babel/preset-env"] 
    })) 
    .pipe(rename({ 
      suffix: '.babel', 
      prefix: '' 
    })) 
    .pipe(sourcemaps.write()) 
    .pipe(gulp.dest(path.dist.js)) 
  //Mini-js файл. 
  gulp.src(path.app.js) 
    .pipe(plumber()) 
    .pipe(sourcemaps.init()) 
    .pipe(fileinclude({ 
      prefix: '@@', 
      basepath: '@file' 
    })) 
    .pipe(terser()) //альтернатива uglifyes 
    .pipe(sourcemaps.write()) 
    .pipe(rename({ 
      suffix: '.min', 
      prefix: '' 
    })) 
    .pipe(gulp.dest(path.dist.js)); 
  //Babel-mini-js файл. 
  gulp.src(path.app.js) 
    .pipe(plumber()) 
    .pipe(sourcemaps.init()) 
    .pipe(fileinclude({ 
      prefix: '@@', 
      basepath: '@file' 
    })) 
    .pipe(babel({ 
      presets: ["@babel/preset-env"] 
    })) 
    .pipe(terser()) 
    .pipe(sourcemaps.write()) 
    .pipe(rename({ 
      suffix: '.babel-min', 
      prefix: '' 
    })) 
    .pipe(gulp.dest(path.dist.js)) 
    .pipe(reload()); 
}); 
 
gulp.task('style:dist', function() { 
  gulp.src(path.app.style) 
    .pipe(plumber()) 
    .pipe(sourcemaps.init()) 
    .pipe(sass({ 
      sourceMap: true, 
      errLogToConsole: true 
    })) 
    .pipe(prefixer()) 
    .pipe(sourcemaps.write()) 
    .pipe(gulp.dest(path.dist.css)) 
    .pipe(cssmin()) 
    .pipe(sourcemaps.write()) 
    .pipe(rename({ 
      suffix: '.min', 
      prefix: '' 
    })) 
    .pipe(gulp.dest(path.dist.css)) 
    .pipe(reload()); 
}); 
 
gulp.task('image:dist', function() { 
  gulp.src(path.app.img) 
    .pipe(plumber()) 
    .pipe(imagemin({ 
      progressive: true, 
      svgoPlugins: [{ 
        removeViewBox: false 
      }], 
      use: [pngquant()], 
      interlaced: true 
    })) 
    .pipe(gulp.dest(path.dist.img)) 
    .pipe(reload()); 
}); 
 
gulp.task('sprite:dist', function() { 
  var spriteData = 
    gulp.src(path.app.sprite) 
    .pipe(plumber()) 
    .pipe(spritesmith({ 
      imgName: 'sprite.png', 
      cssName: '_sprite.scss', 
      cssFormat: 'scss', 
      algorithm: 'binary-tree', 
      cssTemplate: path.spriteTemplate, 
      cssVarMap: function(sprite) { 
        sprite.name = 's-' + sprite.name 
      } 
    })); 
  spriteData.img.pipe(gulp.dest(path.export.img)); 
  spriteData.css.pipe(gulp.dest(path.export.style)); 
}); 
 
gulp.task('fonts:dist', function() { 
  gulp.src(path.app.fonts) 
    .pipe(plumber()) 
    .pipe(gulp.dest(path.dist.fonts)) 
}); 
 
gulp.task('dist', [ 
  'html:dist', 
  'php:dist', 
  'js:dist', 
  'sprite:dist', 
  'style:dist', 
  'fonts:dist', 
  'image:dist' 
]); 
 
gulp.task('watch', function() { 
  watch(path.watch.html, function(event, cb) { 
    gulp.start('html:dist'); 
  }); 
  watch(path.watch.php, function(event, cb) { 
    gulp.start('php:dist'); 
  }); 
  watch(path.watch.style, function(event, cb) { 
    gulp.start('style:dist'); 
  }); 
  watch(path.watch.js, function(event, cb) { 
    gulp.start('js:dist'); 
  }); 
  watch(path.watch.img, function(event, cb) { 
    gulp.start('image:dist'); 
  }); 
  watch(path.watch.sprite, function(event, cb) { 
    gulp.start('sprite:dist'); 
  }); 
  watch(path.watch.fonts, function(event, cb) { 
    gulp.start('fonts:dist'); 
  }); 
}); 
 
gulp.task('default', ['dist', 'webserver', 'watch']);

Частичное решение

Проблема была в том, что при переходе на новый Gulp 4, не сделали обратной совместимости. Не знаю почему, и оправдано ли это, но ниже я приведу пример, который мне помог.

Они добавили два новых метода: gulp.series, gulp.parallel.

Было:

gulp.task('dist', [ 
	'html:dist', 
	'php:dist', 
	'js:dist', 
	'sprite:dist', 
	'style:dist', 
	'fonts:dist', 
	'image:dist' 
]); 
 
gulp.task('watch', function() { 
	watch(path.watch.html, function(event, cb) { 
		gulp.start('html:dist'); 
	}); 
	watch(path.watch.php, function(event, cb) { 
		gulp.start('php:dist'); 
	}); 
	watch(path.watch.style, function(event, cb) { 
		gulp.start('style:dist'); 
	}); 
	watch(path.watch.js, function(event, cb) { 
		gulp.start('js:dist'); 
	}); 
	watch(path.watch.img, function(event, cb) { 
		gulp.start('image:dist'); 
	}); 
	watch(path.watch.sprite, function(event, cb) { 
		gulp.start('sprite:dist'); 
	}); 
	watch(path.watch.fonts, function(event, cb) { 
		gulp.start('fonts:dist'); 
	}); 
}); 
 
gulp.task('default', ['dist', 'webserver', 'watch']);

Стало:

//Удалил  
 
// gulp.task('dist', [ 
// 	'html:dist', 
// 	'php:dist', 
// 	'js:dist', 
// 	'sprite:dist', 
// 	'style:dist', 
// 	'fonts:dist', 
// 	'image:dist' 
// ]); 
 
gulp.task('watch', function() { 
	gulp.watch(path.watch.html, function(event, cb) { 
		gulp.start('html:dist'); 
	}); 
	gulp.watch(path.watch.php, function(event, cb) { 
		gulp.start('php:dist'); 
	}); 
	gulp.watch(path.watch.style, function(event, cb) { 
		gulp.start('style:dist'); 
	}); 
	gulp.watch(path.watch.js, function(event, cb) { 
		gulp.start('js:dist'); 
	}); 
	gulp.watch(path.watch.img, function(event, cb) { 
		gulp.start('image:dist'); 
	}); 
	gulp.watch(path.watch.sprite, function(event, cb) { 
		gulp.start('sprite:dist'); 
	}); 
	gulp.watch(path.watch.fonts, function(event, cb) { 
		gulp.start('fonts:dist'); 
	}); 
}); 
 
gulp.task('default', gulp.parallel( 
	'html:dist', 
	'php:dist', 
	'js:dist', 
	'sprite:dist', 
	'style:dist', 
	'fonts:dist', 
	'image:dist', 
	'webserver', 
	'watch' 
));

P.S: На счет правильности написания gulp.task('watch') я сомневаюсь, но такое решение мне помогло.

P.S.S: Это малая часть проблем. Буду благодарен, если отредактируете gulpfile.js так как нужно. Если нужны будет исходники, дайте знать.

[07:12:09] Starting '<anonymous>'...
[07:12:09] '<anonymous>' errored after 2.72 ms
[07:12:09] TypeError: gulp.start is not a function
    at E:\Web\test\gulpfile.js:227:8
    at bound (domain.js:301:14)
    at runBound (domain.js:314:12)
    at asyncRunner (E:\Web\test\node_modules\async-done\index.js:55:18)
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickDomainCallback (internal/process/next_tick.js:218:9)
Answer 1

В Gulp 4 изменили способ определения задач, если задача зависит от выполнения другой задачи, другими словами параметр списка [] для указания задач на выполнение - устарел.

У вас описан вотчер следующим образом (обратите внимание на gulp.start, его нужно будет заменить, так как запуск должен производиться иначе):

gulp.task('watch', function() {
  watch(path.watch.js, function(event, cb) {
    gulp.start('js:dist');
  });
  watch(path.watch.html, function(event, cb) {
    gulp.start('html:dist');
  });
  // some code here...
});

Вотчер нужно переделать так (вместо start используй series) :

gulp.task('watch', function() {
  gulp.watch(path.watch.js, gulp.series('js:dist')); 
  gulp.watch(path.watch.html, gulp.series('html:dist'));
  // some code here...
});

Это примера запуска вотчера на JS и HTML (остальные по подобию). Единсвенное замечание - следите за правильностью указания пути к файлам в шаблонах (к примеру 'app/**/*.html').

Также переделайте запуск следующей таски (замените параметра списка []):

gulp.task('dist', [
  'html:dist',
  'php:dist',
  'js:dist',
  'sprite:dist',
  'style:dist',
  'fonts:dist',
  'image:dist'
]);

К примеру на следующий код:

gulp.task('dist', gulp.parallel(
  'html:dist',
  'php:dist',
  'js:dist',
  'sprite:dist',
  'style:dist',
  'fonts:dist',
  'image:dist'
));

Далее, запуск 'default' задачи, у вас он выглядит так (как писал ранее - параметр указания списка задач через [] - устарел):

gulp.task('default', ['dist', 'webserver', 'watch']);

Сделайте запуск 'default' задачи вот так (чтобы они работали параллельно через gulp.parallel, также убрали запуск через параметр списка []):

gulp.task('default', gulp.parallel('dist', 'webserver', 'watch'));

В Gulp 4 принято использовать вместо параметра списка [] следующие функции gulp.series(...tasks) и gulp.parallel(...tasks).

По использованным функциям:

  • gulp.parallel(...tasks) — запускает указанные задачи параллельно, при этом, если возникает ошибка, то выполнение будет завершено
  • gulp.series(...tasks) — запускает задачи последовательно в указанном порядке, при этом, если возникает ошибка, то выполнение будет завершено

Ссылка на документацию по запуску задач внутри gulp.series:

  • Running tasks in series

Сссылка на похожую проблему и ее решение:

  • Everytime I run gulp anything, I get a assertion error. - Task function must be specified

А также ссылка на гайд по переходу на Gulp 4:

  • A quick guide for switching to gulp 4

Также, хочу обратить внимание на то, что все пакеты, которые вы используете в своем gulpfile необходимо обновить, обязательно удостоверьтесь в том, что они поддерживают Gulp 4. Про основные нюансы я рассказал, других проблем не должно возникнуть при переходе на Gulp 4, как правило основной проблемой является параметра списка [], и иногда слишком старые пакеты.

Пример работы вашего приложения. Для начала, версии, которые установлены на моем компьютере (версии node, npm, gulp):

После этого я запустил gulp и в браузере открылась страница:

Я внес правки в html файл и сохранил изменения, при этом вотчер сработал и отобразилось в консоли изменение, также попробовал изменить js файл и в консоли эти изменения тоже отобразились:

В браузере отобразились изменения практически моментально:

Вот, собственно сам gulpfile который я запустил:

'use strict'; 
 
var gulp = require('gulp'), 
		watch = require('gulp-watch'), 
		plumber = require('gulp-plumber'), 
		prefixer = require('gulp-autoprefixer'), 
		babel = require('gulp-babel'), 
		terser = require('gulp-terser'), //альтернатива gulp-uglifyes 
		sass = require('gulp-sass'), 
		sourcemaps = require('gulp-sourcemaps'), 
		fileinclude = require('gulp-file-include'), 
		cssmin = require('gulp-minify-css'), 
		imagemin = require('gulp-imagemin'), 
		pngquant = require('imagemin-pngquant'), 
		rimraf = require('rimraf'), 
		browserSync = require("browser-sync"), 
		rename = require('gulp-rename'), 
		spritesmith  = require('gulp.spritesmith'), 
		reload = browserSync.stream; 
 
var path = { 
	dist: { 
		html: 'dist/', 
		php: 'dist/', 
		js: 'dist/js/', 
		css: 'dist/css/', 
		img: 'dist/img/', 
		fonts: 'dist/fonts/' 
	}, 
	app: { 
		html: 'app/*.html', 
		php: 'app/*.php', 
		js: 'app/js/main.js', 
		jsInit: 'app/js/init.js', 
		style: 'app/scss/main.scss', 
		sprite: 'app/img/sprite/**/*.*', 
		img: 'app/img/*.*', 
		fonts: 'app/fonts/**/*.*', 
	}, 
	watch: { 
		html: 'app/**/*.html', 
		php: 'app/*.php', 
		js: 'app/js/**/*.js', 
		style: 'app/scss/**/*.scss', 
		img: 'app/img/*.*', 
		sprite: 'app/img/sprite/**/*.*', 
		fonts: 'app/fonts/**/*.*' 
	}, 
	export: { 
		img: 'app/img/', 
		style: 'app/scss/imports/' 
	}, 
	spriteTemplate: 'sass.template.mustache', 
	clean: './dist' 
}; 
 
var config = { 
	server: { 
		baseDir: "dist" // or ./dist 
	}, 
	// tunnel: true, 
	// host: "178.150.110.97", 
	// notify: false, 
	logPrefix: "Frontend_Devil" 
}; 
 
gulp.task('webserver', function() { 
	browserSync(config); 
}); 
 
gulp.task('clean', function(cb) { 
	rimraf(path.clean, cb); 
}); 
 
gulp.task('html:dist', function(done) { 
	gulp.src(path.app.html) 
	.pipe(plumber()) 
	.pipe(fileinclude({ 
		prefix: '@@', 
		basepath: '@file' 
	})) 
	.pipe(gulp.dest(path.dist.html)) 
	.pipe(reload()); 
	done(); 
}); 
 
gulp.task('php:dist', function(done) { 
	gulp.src(path.app.php) 
	.pipe(plumber()) 
	.pipe(fileinclude({ 
		prefix: '@@', 
		basepath: '@file' 
	})) 
	.pipe(gulp.dest(path.dist.php)) 
	.pipe(reload()); 
	done(); 
}); 
 
gulp.task('js:dist', function(done) { 
	//init.js 
	//Файл для инициации 
	// gulp.src(path.app.jsInit) 
	// .pipe(plumber()) 
	// .pipe(sourcemaps.init()) 
	// .pipe(fileinclude({ 
	// 	prefix: '@@', 
	// 	basepath: '@file' 
	// })) 
	// .pipe(babel({ 
	// 	presets: ["@babel/preset-env"] 
	// })) 
	// .pipe(terser()) 
	// .pipe(sourcemaps.write()) 
	// .pipe(rename({suffix: '.babel-min', prefix : ''})) 
	// .pipe(gulp.dest(path.dist.js)) 
	 
	//Обычный js файл. 
	gulp.src(path.app.js) 
	.pipe(plumber()) 
	.pipe(sourcemaps.init()) 
	.pipe(fileinclude({ 
		prefix: '@@', 
		basepath: '@file' 
	})) 
	.pipe(sourcemaps.write()) 
	.pipe(gulp.dest(path.dist.js)) 
	//Babel-js файл. 
	gulp.src(path.app.js) 
	.pipe(plumber()) 
	.pipe(sourcemaps.init()) 
	.pipe(fileinclude({ 
		prefix: '@@', 
		basepath: '@file' 
	})) 
	.pipe(babel({ 
		presets: ["@babel/preset-env"] 
	})) 
	.pipe(rename({suffix: '.babel', prefix : ''})) 
	.pipe(sourcemaps.write()) 
	.pipe(gulp.dest(path.dist.js)) 
	//Mini-js файл. 
	gulp.src(path.app.js) 
	.pipe(plumber()) 
	.pipe(sourcemaps.init()) 
	.pipe(fileinclude({ 
		prefix: '@@', 
		basepath: '@file' 
	})) 
	.pipe(terser()) //альтернатива uglifyes 
	.pipe(sourcemaps.write()) 
	.pipe(rename({suffix: '.min', prefix : ''})) 
	.pipe(gulp.dest(path.dist.js)); 
	//Babel-mini-js файл. 
	gulp.src(path.app.js) 
	.pipe(plumber()) 
	.pipe(sourcemaps.init()) 
	.pipe(fileinclude({ 
		prefix: '@@', 
		basepath: '@file' 
	})) 
	.pipe(babel({ 
		presets: ["@babel/preset-env"] 
	})) 
	.pipe(terser()) 
	.pipe(sourcemaps.write()) 
	.pipe(rename({suffix: '.babel-min', prefix : ''})) 
	.pipe(gulp.dest(path.dist.js)) 
	.pipe(reload()); 
	done(); 
}); 
 
gulp.task('style:dist', function(done) { 
	gulp.src(path.app.style)  
	.pipe(plumber()) 
	.pipe(sourcemaps.init()) 
	.pipe(sass({ 
		sourceMap: true, 
		errLogToConsole: true 
	})) 
	.pipe(prefixer()) 
	.pipe(sourcemaps.write()) 
	.pipe(gulp.dest(path.dist.css)) 
	.pipe(cssmin()) 
	.pipe(sourcemaps.write()) 
	.pipe(rename({suffix: '.min', prefix : ''})) 
	.pipe(gulp.dest(path.dist.css)) 
	.pipe(reload()); 
	done(); 
}); 
 
gulp.task('image:dist', function(done) { 
	gulp.src(path.app.img) 
	.pipe(plumber()) 
	.pipe(imagemin({ 
		progressive: true, 
		svgoPlugins: [{removeViewBox: false}], 
		use: [pngquant()], 
		interlaced: true 
	})) 
	.pipe(gulp.dest(path.dist.img)) 
	.pipe(reload()); 
	done(); 
}); 
 
gulp.task('sprite:dist', function(done) { 
	var spriteData = 
		gulp.src(path.app.sprite) 
		.pipe(plumber()) 
		.pipe(spritesmith({ 
			imgName: 'sprite.png', 
			cssName: '_sprite.scss', 
			cssFormat: 'scss', 
			algorithm: 'binary-tree', 
			cssTemplate: path.spriteTemplate, 
			cssVarMap: function(sprite) { 
				sprite.name = 's-' + sprite.name 
			} 
		})); 
		spriteData.img.pipe(gulp.dest(path.export.img)); 
		spriteData.css.pipe(gulp.dest(path.export.style)); 
	done(); 
}); 
 
gulp.task('fonts:dist', function(done) { 
	gulp.src(path.app.fonts) 
	.pipe(plumber()) 
	.pipe(gulp.dest(path.dist.fonts)) 
	done(); 
}); 
 
gulp.task('dist', gulp.parallel( 
	'html:dist', 
	'php:dist', 
	'js:dist', 
	'sprite:dist', 
	'style:dist', 
	'fonts:dist', 
	'image:dist' 
)); 
 
gulp.task('watch', function() { 
	gulp.watch(path.watch.html, gulp.series('html:dist')); 
	gulp.watch(path.watch.php, gulp.series('php:dist')); 
	gulp.watch(path.watch.style, gulp.series('style:dist')); 
	gulp.watch(path.watch.js, gulp.series('js:dist')); 
	gulp.watch(path.watch.sprite, gulp.series('sprite:dist')); 
	gulp.watch(path.watch.fonts, gulp.series('fonts:dist')); 
}); 
 
gulp.task('default', gulp.parallel('dist', 'webserver', 'watch'));

Поскольку некоторые задачи могут содержать асинхронный код, вы должны сигнализировать gulp, когда ваша задача завершит выполнение.

В Gulp 3 версий вы могли не делать этого. Если вы не указали явно асинхронное завершение, gulp просто предположил бы, что ваша задача является синхронной и что она завершена, как только ваша задача завершится.

В Gulp 4 был внедрен более строгий режим в этом отношении. Вы должны явно сигнализировать о завершении задачи. Это можно сделать пятью разными способами, о которых подробно описано в следующем ответе: Gulp error: The following tasks did not complete: Did you forget to signal async completion?

Самый простой способ - это вызвать функцию обратного вызова, которую Gulp автоматически передает вашей задаче в качестве первого аргумента. Нужно просто вызвать эту функцию в конце задачи (внес правку в ответ, в параметрах добавлена колбэк функция done).

Answer 2

При переходе с gulp 3 на gulp 4 есть в принципе 2 проблемы, первая вроде как очевидная при первых попытка поиска решения проблемы: вместо массива с названиями тасков использовать метод gulp.parallel или gulp.series - между ними разница лишь в том, что метод .parallel запускает таски параллельно друг с другом, а вот метод .series не начинает выполнение второго таска указанного в нем до того как закончится первый... итого можно использовать метод .parallel везде если нет строгой зависимости в чередности выполнения тасков переданных данному методу.

было:

gulp.task('default', ['dist', 'webserver', 'watch']);

стало:

`gulp.task('default', gulp.parallel('dist', 'webserver', 'watch'));`

Вторая же проблема не такая очевидная, т.к. всё зависит от того как ранее настраивали gulpfile.

дело в том что таски в gulp представляют из себя поток, и если не "сказать" gulp, что поток завершен, то может вылезть ошибка.

Чтобы сообщить gulp что вызванный таск завершился есть 2 способа:

1) передать в параметры функции некий параметр (назовём его callback) и после выполнения всех действий вызвать этот параметр;

2) воспользоваться return для действий в таске.

на примере

было:

`gulp.task('html:dist', function() {
  gulp.src(path.app.html)
    .pipe(plumber())
    .pipe(fileinclude({
      prefix: '@@',
      basepath: '@file'
    }))
    .pipe(gulp.dest(path.dist.html))
    .pipe(reload());
 });`

закроем поток таска использовав return:

`gulp.task('html:dist', function() {
  return gulp.src(path.app.html)
    .pipe(plumber())
    .pipe(fileinclude({
      prefix: '@@',
      basepath: '@file'
    }))
    .pipe(gulp.dest(path.dist.html))
    .pipe(reload());
 });`

предыдущий способ хорош, НО мы можем наблюдать в данном проекте таск js:dist, где мы не можем использовать return так как в таком случае прервется выполнение таска после выполнения первой задачи (т.к. return возвращает результат выполнения и дальше функция не выполняется):

`gulp.task('js:dist', function() {
   gulp.src(path.app.js)
    .pipe(plumber())
    .pipe(sourcemaps.init())
    .pipe(fileinclude({
      prefix: '@@',
      basepath: '@file'
    }))
    .pipe(sourcemaps.write())
    .pipe(gulp.dest(path.dist.js))
  //Babel-js файл.
  gulp.src(path.app.js)
    .pipe(plumber())
    .pipe(sourcemaps.init())
    .pipe(fileinclude({
      prefix: '@@',
      basepath: '@file'
    }))
    .pipe(babel({
      presets: ["@babel/preset-env"]
    }))
    .pipe(rename({
      suffix: '.babel',
      prefix: ''
    }))
    .pipe(sourcemaps.write())
    .pipe(gulp.dest(path.dist.js))
 //..... и далее другие задачи таска
});`

И вот в этом случае лучшим решением будет передать в параметры функции callback и вызвать его после всех необходимых нам действий:

`gulp.task('js:dist', function(callback) {
   gulp.src(path.app.js)
    .pipe(plumber())
    .pipe(sourcemaps.init())
    .pipe(fileinclude({
      prefix: '@@',
      basepath: '@file'
    }))
    .pipe(sourcemaps.write())
    .pipe(gulp.dest(path.dist.js))
  //Babel-js файл.
  gulp.src(path.app.js)
    .pipe(plumber())
    .pipe(sourcemaps.init())
    .pipe(fileinclude({
      prefix: '@@',
      basepath: '@file'
    }))
    .pipe(babel({
      presets: ["@babel/preset-env"]
    }))
    .pipe(rename({
      suffix: '.babel',
      prefix: ''
    }))
    .pipe(sourcemaps.write())
    .pipe(gulp.dest(path.dist.js))
 //..... и далее другие задачи таска
callback();
});`
Answer 3

Ответ Denis Bubnov актуальный, но я хочу предоставить свой конечный вариант.

Отдельное спасибо Max Manchak, так как он в комментариях предоставил работающий код, и помог довести (до совершенства) конечный ответ.

'use strict'; 
 
var gulp = require('gulp'), 
	watch = require('gulp-watch'), 
	plumber = require('gulp-plumber'), 
	prefixer = require('gulp-autoprefixer'), 
	babel = require('gulp-babel'), 
	terser = require('gulp-terser'), //альтернатива gulp-uglifyes 
	sass = require('gulp-sass'), 
	sourcemaps = require('gulp-sourcemaps'), 
	fileinclude = require('gulp-file-include'), 
	cssmin = require('gulp-minify-css'), 
	imagemin = require('gulp-imagemin'), 
	pngquant = require('imagemin-pngquant'), 
	rimraf = require('rimraf'), 
	browserSync = require("browser-sync"), 
	rename = require('gulp-rename'), 
	spritesmith = require('gulp.spritesmith'), 
	reload = browserSync.stream; 
 
var path = { 
	dist: { 
		html: 'dist/', 
		php: 'dist/', 
		js: 'dist/js/', 
		css: 'dist/css/', 
		img: 'dist/img/', 
		fonts: 'dist/fonts/', 
		videos: 'dist/videos/', 
		files: 'dist/files/' 
	}, 
	app: { 
		html: 'app/*.html', 
		php: 'app/*.php', 
		js: 'app/js/main.js', 
		jsInit: 'app/js/init.js', 
		style: 'app/scss/main.scss', 
		img: 'app/img/*.*', 
		sprite: 'app/img/sprite/**/*.*', 
		fonts: 'app/fonts/**/*.*', 
		videos: 'app/videos/*.*', 
		files: 'app/files/*.*' 
	}, 
	watch: { 
		html: 'app/**/*.html', 
		php: 'app/*.php', 
		js: 'app/js/**/*.js', 
		style: 'app/scss/**/*.scss', 
		img: 'app/img/*.*', 
		sprite: 'app/img/sprite/**/*.*', 
		fonts: 'app/fonts/**/*.*', 
		videos: 'app/videos/*.*', 
		files: 'app/files/*.*' 
	}, 
	export: { 
		img: 'app/img/', 
		style: 'app/scss/imports/' 
	}, 
	spriteTemplate: 'sass.template.mustache', 
	clean: './dist' 
}; 
 
var config = { 
	server: { 
		baseDir: "dist" // or ./dist 
	}, 
	// tunnel: true, 
	// host: "178.150.110.97", 
	// notify: false, 
	logPrefix: "Frontend_Devil" 
}; 
 
gulp.task('webserver', function(cb) { 
	browserSync(config); 
	cb(); 
}); 
 
gulp.task('clean', function(cb) { 
	rimraf(path.clean, cb); 
}); 
 
gulp.task('html:dist', function(cb) { 
	gulp.src(path.app.html) 
	.pipe(plumber()) 
	.pipe(fileinclude({ 
		prefix: '@@', 
		basepath: '@file' 
	})) 
	.pipe(gulp.dest(path.dist.html)) 
	.pipe(reload()); 
	cb(); 
}); 
 
gulp.task('php:dist', function(cb) { 
	gulp.src(path.app.php) 
	.pipe(plumber()) 
	.pipe(fileinclude({ 
		prefix: '@@', 
		basepath: '@file' 
	})) 
	.pipe(gulp.dest(path.dist.php)) 
	.pipe(reload()); 
	cb(); 
}); 
 
 
gulp.task('js:dist', function(cb) { 
	//init.js 
	//Файл для инициации 
	// gulp.src(path.app.jsInit) 
	// .pipe(plumber()) 
	// .pipe(sourcemaps.init()) 
	// .pipe(fileinclude({ 
	// 	prefix: '@@', 
	// 	basepath: '@file' 
	// })) 
	// .pipe(babel({ 
	// 	presets: ["@babel/preset-env"] 
	// })) 
	// .pipe(terser()) 
	// .pipe(sourcemaps.write()) 
	// .pipe(rename({suffix: '.babel-min', prefix : ''})) 
	// .pipe(gulp.dest(path.dist.js)) 
 
	//Обычный js файл. 
	gulp.src(path.app.js) 
	.pipe(plumber()) 
	.pipe(sourcemaps.init()) 
	.pipe(fileinclude({ 
		prefix: '@@', 
		basepath: '@file' 
	})) 
	.pipe(sourcemaps.write()) 
	.pipe(gulp.dest(path.dist.js)); 
 
	gulp.src(path.app.js) 
	.pipe(plumber()) 
	.pipe(sourcemaps.init()) 
	.pipe(fileinclude({ 
		prefix: '@@', 
		basepath: '@file' 
	})) 
	.pipe(babel({ 
		presets: ["@babel/preset-env"] 
	})) 
	.pipe(rename({ 
		suffix: '.babel', 
		prefix: '' 
	})) 
	.pipe(sourcemaps.write()) 
	.pipe(gulp.dest(path.dist.js)) 
	//Mini-js файл. 
	gulp.src(path.app.js) 
	.pipe(plumber()) 
	.pipe(sourcemaps.init()) 
	.pipe(fileinclude({ 
		prefix: '@@', 
		basepath: '@file' 
	})) 
	.pipe(terser()) //альтернатива uglifyes 
	.pipe(sourcemaps.write()) 
	.pipe(rename({ 
		suffix: '.min', 
		prefix: '' 
	})) 
	.pipe(gulp.dest(path.dist.js)); 
	//Babel-mini-js файл. 
	gulp.src(path.app.js) 
	.pipe(plumber()) 
	.pipe(sourcemaps.init()) 
	.pipe(fileinclude({ 
		prefix: '@@', 
		basepath: '@file' 
	})) 
	.pipe(babel({ 
		presets: ["@babel/preset-env"] 
	})) 
	.pipe(terser()) 
	.pipe(sourcemaps.write()) 
	.pipe(rename({ 
		suffix: '.babel-min', 
		prefix: '' 
	})) 
	.pipe(gulp.dest(path.dist.js)) 
	.pipe(reload()); 
	cb(); 
}); 
 
gulp.task('style:dist', function(cb) { 
	gulp.src(path.app.style) 
	.pipe(plumber()) 
	.pipe(sourcemaps.init()) 
	.pipe(sass({ 
		sourceMap: true, 
		errLogToConsole: true 
	})) 
	.pipe(prefixer()) 
	.pipe(sourcemaps.write()) 
	.pipe(gulp.dest(path.dist.css)) 
	.pipe(cssmin()) 
	.pipe(sourcemaps.write()) 
	.pipe(rename({ 
		suffix: '.min', 
		prefix: '' 
	})) 
	.pipe(gulp.dest(path.dist.css)) 
	.pipe(reload()); 
	cb(); 
}); 
 
gulp.task('image:dist', function(cb) { 
	gulp.src(path.app.img) 
	.pipe(plumber()) 
	.pipe(imagemin({ 
		progressive: true, 
		svgoPlugins: [{ 
			removeViewBox: false 
		}], 
		use: [pngquant()], 
		interlaced: true 
	})) 
	.pipe(gulp.dest(path.dist.img)) 
	.pipe(reload()); 
	cb(); 
}); 
 
gulp.task('sprite:dist', function(cb) { 
	var spriteData = 
	gulp.src(path.app.sprite) 
	.pipe(plumber()) 
	.pipe(spritesmith({ 
		imgName: 'sprite.png', 
		cssName: '_sprite.scss', 
		cssFormat: 'scss', 
		algorithm: 'binary-tree', 
		cssTemplate: path.spriteTemplate, 
		cssVarMap: function (sprite) { 
			sprite.name = 's-' + sprite.name 
		} 
	})); 
	spriteData.img.pipe(gulp.dest(path.export.img)); 
	spriteData.css.pipe(gulp.dest(path.export.style)); 
	reload(); 
	cb(); 
}); 
 
gulp.task('fonts:dist', function(cb) { 
	gulp.src(path.app.fonts) 
	.pipe(plumber()) 
	.pipe(gulp.dest(path.dist.fonts)) 
	.pipe(reload()); 
	cb(); 
}); 
 
gulp.task('videos:dist', function(cb) { 
	gulp.src(path.app.videos) 
	.pipe(plumber()) 
	.pipe(gulp.dest(path.dist.videos)) 
	.pipe(reload()); 
	cb(); 
}); 
 
gulp.task('files:dist', function(cb) { 
	gulp.src(path.app.files) 
	.pipe(plumber()) 
	.pipe(gulp.dest(path.dist.files)) 
	.pipe(reload()); 
	cb(); 
}); 
 
gulp.task('dist', gulp.parallel( 
	'html:dist', 
	'php:dist', 
	'js:dist', 
	'style:dist', 
	'image:dist', 
	'sprite:dist', 
	'fonts:dist', 
	'videos:dist', 
	'files:dist' 
)); 
 
gulp.task('watch', function() { 
	gulp.watch(path.watch.html, gulp.series('html:dist')); 
	gulp.watch(path.watch.php, gulp.series('php:dist')); 
	gulp.watch(path.watch.js, gulp.series('js:dist')); 
	gulp.watch(path.watch.style, gulp.series('style:dist')); 
	gulp.watch(path.watch.img, gulp.series('image:dist')); 
	gulp.watch(path.watch.sprite, gulp.series('sprite:dist')); 
	gulp.watch(path.watch.fonts, gulp.series('fonts:dist')); 
	gulp.watch(path.watch.videos, gulp.series('videos:dist')); 
	gulp.watch(path.watch.files, gulp.series('files:dist')); 
}); 
 
gulp.task('default', gulp.parallel('dist', 'webserver', 'watch'));

READ ALSO
Получить статус запроса ReactJS

Получить статус запроса ReactJS

Получаю ответ от API OpenWeatherMapКаким образом можно было бы получить код ответа и в зависимости от него отобразить контент? К примеру, если статус...

138
Изображение в массиве

Изображение в массиве

Как мне передать картинку через массив? Имеется массив Const LocalStorage = [ { Id: 1, Name: "one" … } … ]

110
Перейти к следующему фото в альбоме вконтакте с помощью javascript

Перейти к следующему фото в альбоме вконтакте с помощью javascript

Нашел селектор, который отвечает за переход к следующему фото из альбома вконтакте: #pv_nav_btn_right хотел перейти таким образом:

106
Как правильно использовать React-router в моем случаи?

Как правильно использовать React-router в моем случаи?

Такая ситуация: Есть главная страница indexhtml, на ней вообще не используется React, на главной странице есть ссылка на страницу на которой используется...

120