gulp
gulp copied to clipboard
[Docs] Recipes
We're doing a full rewrite of the docs. We've noticed that recipes is pretty unruly and the quality varies a lot. We need to trim, edit, and add to them.
We'd love to get some feedback on which recipes you use, which you don't touch, and what new ones you'd like to see!
Hi, I just wanted to say that the Delete files and folders recipe helped me when I started with Gulp. Deleting files is a common problem and the fact that you don't need a special plugin but can just use normal libraries is a good thing to know.
I did not use other recipes. Thanks for helping with the documentation.
I loved the handling-the-delete-event-on-watch recipe: it helped me get rid of many of the problems I was facing with my gulp setup previously.
Hello, I would love to see classic documentation with functions signatures, explained inputs/outputs, listed input flags and examples on use :). I believe most of this could be autogenerated (except the examples).
Examples of using a testing tool chain with watch. Jasmine for example is a bit tricky. As gulp stays running, you have to manually clean require.cache when a change is detected.
Here is an example that we finally arrived on - opting to just spawn jasmine on each change and not having to deal with with some of the more subtle require.cache
issues.
'use strict';
var gulp = require('gulp');
var del = require('del');
const path = require('path');
const debug = require('gulp-debug');
const { spawn } = require('child_process');
let server;
const jasmine_spawn = () => {
const jasmine_exec = path.resolve('specs', 'jasmine-runner.js');
const jas = spawn('node', [jasmine_exec], {stdio: 'inherit'});
return jas;
}
const watch_test = () => {
var watcher = gulp.watch([
'src/**/*.js',
'specs/**/*.js',
'config/*.*'
], {'name': 'test', 'read': false, 'delay': 100}, jasmine_spawn);
}
// gulp test:backend
const test = gulp.series(jasmine_spawn, watch_test);
test.description = 'Run tests and start watching if they succeed';
gulp.task('test', test);
// gulp jasmine:test
gulp.task('jasmine:test', jasmine_spawn);
I relied a lot on the server-with-livereload example to get our web project up and running
I would personally love to see a recipe for integrating with webpack. I hacked something together, but I have the feeling it could be a lot better.
What I do most of the time:
- SASS + Source maps
- Pug incremental builds
- ESLINT
Something that I remember took me some time to sort out:
- React / JSX / BABEL
- Being able to use ES6 code in the gulp file itself.
Here is my recipe on how to use Jasmine 3.2 with gulp 4:
const chalk = require('chalk');
const gulp = require('gulp');
const Jasmine = require('jasmine');
const path = require('path');
const gutil = {
log: require('fancy-log'),
};
gulp.task('test:node', (done) => {
const jasmine = new Jasmine();
jasmine.loadConfigFile(path.join(process.cwd(), 'spec', 'support', 'jasmine.json'));
jasmine.configureDefaultReporter({
showColors: true
});
jasmine.onComplete((passed) => {
if (passed) {
gutil.log(chalk`All specs have {green passed}.`);
done();
process.exit(0);
}
else {
process.exit(1);
}
});
jasmine.execute();
});
Unfortunately I had to work with process.exit
. Otherwise the CLI stays open (although the Gulp task already finished).
Today I stumbled over the Reporters documentation from Jasmine 2.1 which helped me to solve my process.exit
problem (only need the process.exit(1)
for now).
I am now defining onComplete
within the default reporter instead of assigning it to my jasmine
instance:
const gulp = require('gulp');
const Jasmine = require('jasmine');
const jasmineConfigFilePath = path.join(process.cwd(), 'spec', 'support', 'jasmine.json')
gulp.task('test', async done => {
const jasmine = new Jasmine({projectBaseDir: process.cwd()});
jasmine.loadConfigFile(jasmineConfigFilePath);
// @see https://github.com/gulpjs/gulp/issues/2164#issuecomment-443540389
jasmine.configureDefaultReporter({
onComplete: passed => {
if (passed) {
exit(0);
} else {
exit(1);
}
},
showColors: true,
});
jasmine.onComplete(passed => {
if (passed) {
done();
} else {
process.exit(-1);
}
});
jasmine.execute();
});
I'd really like to see a recipe for babel, browserify, uglify using the new built in source mapping whilst handling multiple inputs being passed to gulp.src. E.g.
// Dependencies
import concat from 'gulp-concat';
// Task
gulp.src([
'./path/to/entrypoints/entrypoint.js',
'./path/to/entrypoints/anotherentrypoint.js'
], {'sourcemaps': true})
.pipe(concat('bundle.js'))
// Handle babel -> browserify -> uglify
.pipe(gulp.dest('./path/to/dist/', {'sourcemaps': '.'}));
To give some more context I am currently generating multiple output files using this technique, but I'd like to see how I can combine both entries with the new gulp source map feature:
// Dependencies
import babelify from 'babelify';
import browserify from 'browserify';
import buffer from 'vinyl-buffer';
import gulpif from 'gulp-if';
import merge from 'merge-stream';
import rename from 'gulp-rename';
import source from 'vinyl-source-stream';
import sourcemaps from 'gulp-sourcemaps';
import uglify from 'gulp-uglify';
// Task
const entries = [
{
'basePath': './path/to/entrypoints/',
'filename': 'entrypoint.js',
'outputPath': './path/to/dist/',
'rename': 'entrypoint'
},
{
'basePath': '/path/to/entrypoints/',
'filename': 'entrypoint2.js',
'outputPath': './path/to/dist/',
'rename': 'entrypoint2'
}
];
return merge(entries.map(entry => browserify({
'debug': true,
'entries': entry.basePath + entry.filename
})
.transform(babelify)
.bundle()
.pipe(source(entry.filename))
.pipe(rename({
'basename': entry.rename,
'extname': '.js'
}))
.pipe(buffer())
.pipe(sourcemaps.init({'loadMaps': true}))
.pipe(uglify())
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(entry.outputPath))));
Sass + source maps (including loading existing maps)
Maybe I'm dumb but now del cannot be imported with require ? look on its github page
The author went ESM-only with all his modules, so you can try using dynamic import to load del
in tasks where you need them:
async function myTask() {
const del = await import('del');
// use "del" here
}
or if del
is not callable that way try this:
const del = (await import('del')).default
Okay thanks, but I just went ESM only too x)