Přechod na Gulp 4
Publikováno: 28.5.2018
Gulp je populární nástroj pro automatizování vývoje. Typicky se používá např. k buildu CSS souborů za použití preprocesorů ze zdrojových SASS/LESS souborů, automatickému prefixování, spojování souborů, minifikování, správě ikon nebo sestavování JavaScriptů.
Text vyšel původně na autorově webu.
Ve verzi 4 se lehce mění způsob, jak gulpfile.js
(soubor s definovanými tasky) psát.
Proč přecházet na Gulp 4?
Hlavní výhodou je asi přítomnost nativního zpracování paralelních/sériových tasků.
Sériové/paralelní tasky
Při komplikovanějším buildu se může hodit, aby některé tasky běžely zároveň a jiné na sebe čekaly.
V Gulpu 3 k tomu šel použít balíček run-sequence
, jinak tasky běžely asynchronně zároveň.
Nativní zápis v Gulp 4 vypadá následovně:
var build = gulp.series(prvni, gulp.parallel(druhy, druhyDalsi));
Funkce/tasky druhy
a druhyDalsi
se spustí až po doběhnutí funkce/tasku prvni
a obě potom poběží souběžně.
Z toho plyne většina nutných úprav pro přechod.
Přechod
V době psaní článku se Gulp 4 nainstaluje následovně (pro uložení do devDependencies
do package.json
):
npm install gulp@next --save-dev
Pokud se po spuštění příkazu gulp
zobrazí následující chyba:
'gulp' is not recognized as an internal or external command, operable program or batch file.
Je třeba gulp@next
nainstalovat globálně:
npm install gulp@next -g
To je ve Windows vhodné v každém případě, protože jinak se může stát, že se použije starší globální verze Gulpu a použití nového gulpfile.js
může končit chybou, jako např.:
gulpInst.start.apply(gulpInst, toRun);
^
TypeError: Cannot read property 'apply' of undefined
Chyby a problémy k přepsání
Nyní by se již měl gulpfile.js
zpracovávat Gulpem 4, takže zbývá soubor upravit do novější podoby. Po spuštění nějakého z tasků pravděpodobně dojde k některé z následujících chyb:
AssertionError: Task function must be specified
Je způsobené právě jiným zápisem pořadí tasků. Původní konstrukce, která zajišťovala souběžný build stylů a puštění lintu na zdrojové soubory, např.:
gulp.task('styles', ['sass-lint'], function() {
gulp.src('./www/assets/scss/main.scss')
.pipe(…);
…
});
bude nyní vypadat následovně:
gulp.task('styles', gulp.parallel(
function() {
gulp.src('./www/assets/scss/main.scss')
.pipe(…);
…
},
lint
));
Kvůli obalování do gulp.parallel
/gulp.series
je poměrně výhodné anonymní funkce pojmenovávat, aby to bylo přehlednější.
Signal async completion
Po přepsání výše uvedeného může dojít při spouštění tasku k následující chybě:
The following tasks did not complete: styles
Did you forget to signal async completion?
Zde je změna kvůli možnosti sériového a paralelního běhu jednotlivých úloh. Aby toto mohl Gulp vědět, je třeba ho o tom nějak informovat.
Jak na to? Existuje několik způsobů. Nejběžnější jsou:
- Vrátit stream pomocí klíčového slova
return
.return gulp.src('./www/assets/scss/main.scss') .pipe(…); …
- Použít callback
done
:gulp.task('usage', function(done) { console.log('Usage: gulp styles'); done(); });
- Vrátit promisu:
gulp.task('usage', function() { return new Promise(function(resolve, reject) { console.log('Usage: gulp styles'); resolve(); }); });
Po těchto opravách by vše mělo fungovat jako předtím.
Přechod na ES6
Při úpravě gulpfile.js
se může hodit rovnou přejít na ES6 (novější verzi JavaScriptu).
Postup je následující:
- Přejmenovat
gulpfile.js
nagulpfile.babel.js
- Nainstalovat Babel:
npm install --save-dev babel-register babel-preset-env
- Vytvořit soubor
.babelrc
s následujícím obsahem:{ "presets": ["env"] }
Nyní jde využívat vymoženosti ES6:
Připojovat balíčky přes import
Místo:
var gulp = require('gulp');
Můžete použít:
import gulp from 'gulp';
Vytvářet tasky jako export funkce
Pokud daná funkce má být přímo taskem, jde místo:
gulp.task('lint', lint);
přímo exportovat stejnojmennou funkci:
export function lint() {
return gulp.src(paths.scss)
.pipe(sassLint({
configFile: paths.sassLint.config
}))
.pipe(sassLint.format())
.pipe(sassLint.failOnError());
}
Vyexportovanou funkci jde i pojmenovat jinak než task:
function lint() {
…
}
export { lint as cokoliv };
Tím se vytvoří task cokoliv
, který použije funkci lint
. Přičemž původní gulp.task('nazev-tasku', funkce)
jde používat i nadále.
Zdánlivá chyba Failed to load
Při výše uvedeném požití se nejspíš po spuštění tasku zobrazí hláška:
Failed to load external module @babel/register
Requiring external module babel-register
Nejedná se o chybu, ale o vlastnost a na funkci nemá vliv.
Odkazy jinam
- StackOverflow: Gulp error: The following tasks did not complete
- We Are Wizards Blog: Migrating to gulp 4 by example
- StackOverflow: Gulp 4 – Gulpfile.js set up – řešení návratových hodnot funkcí
- Liquid Light: How do I update to Gulp 4?