Gulp: Invoking the Gulp tool programmatically

Created on 14 Nov 2014  路  34Comments  路  Source: gulpjs/gulp

I am trying to invoke Gulp within another Node.js script. Is there any non-hackish way to do this? e.g. by not manually requiring bin/gulp.js or setting up a new Liftoff({ ... }), or running the command in the shell as is done at the moment in this plugin I'm currently working on?

To be more general I'm asking if there's an official way to run Gulp as a part of another tool, without the extra overhead of spawning a new child process. A meta-API, if you like.

I think this is somewhat related to issue #755, except that no gulpfile has been loaded yet.

Most helpful comment

nah heres how you really do it

var gulp = require('gulp');
require('./gulpfile');

if (gulp.tasks.test) { 
    console.log('gulpfile contains task!');
    gulp.start('test');
}

a gulpfile is just a node script, so you can require it in like any other.

As they said though, .start will be gone in 4.0 and replaced with series and parallel

All 34 comments

Try this:

var gulp = require('gulp');

function myFunc(done) {
  // eg: copy *.js files into `./dist`
  gulp.src('./src/**/*.js')
    .pipe(gulp.dest('./dist')
    .on('end', function () {
      if (done) { 
        done(); // callback to signal end of build
      }
    });
}

// run our custom build
myFunc(function () {
  console.log('Done!');
});

Nothing special I think, but I think this is what you're looking for?

yep, there is repl and more, feel free to go to the chat and ask me anything you would want to do. I say that mainly because the documentation has to be expanded

Hmm no, that was not exactly what I was trying achieve ... the gulpfile.js is already there, I'm just looking for a way to analyse and/or execute its contents dynamically rather than using a shell and/or REPL, e.g.

var gulp = require('gulp').parse('/my/project/.gulpfile.js');

if (gulp.hasTask('test')) { 
    console.log('gulpfile contains task!');
    gulp.runTask('test');
}

It's a bit rough but it might clarify what I am trying to get at.

Ok, vanilla gulp

var gulp = require('gulp');
process.nextTick(function(){
 var tasks = gulp.tasks;
 if( gulp.myTask ){ gulp.start('myTask'); }
});

in [email protected] gulp.start will be removed in favor of gulp.series and gulp.parallel, which are really cool by the way. So beware of changing that in the future.

Using the plugin I wrote

var runtime = require('gulp-runtime');
process.nextTick(function(){ 
 runtime.input.write('myTask\n');
})

which is the same as you wrote in the shell the task and pressed enter. The repl is something more of a feature. It can work without stdin and stdout, but I have yet to document it better.

Anyhow the first option will serve you good if your aim is simpler.

sorry there was a typo,

gulp.myTask; /* -> to */ gulp.tasks.myTasks

on that if

nah heres how you really do it

var gulp = require('gulp');
require('./gulpfile');

if (gulp.tasks.test) { 
    console.log('gulpfile contains task!');
    gulp.start('test');
}

a gulpfile is just a node script, so you can require it in like any other.

As they said though, .start will be gone in 4.0 and replaced with series and parallel

Why this then?

@stringparser Why what? Theres a lot of stuff going on in those lines, specifically what thing?

The problem with the sample solution you posted was you never required the gulpfile - requiring the gulp module doesn't load the gulpfile

haha, sorry about that @contra just the part of gulp.start being called on process.nextTick. That is: why sometimes nextTick is necessary and others don't after requiring the gulpfile

@stringparser It isn't necessary, just done because it seemed like a good idea to let async stuff finish on require before running start

interesting :) thanks a lot for the explanation ;)

@contra yup, that was the one I was looking for, thanks!
@stringparser I wanted to avoid the indirection of parsing command-line parameters, but thanks for letting me know that such a thing is possible ... I might need it in the future :)

welcome!

Logs get suppressed when triggered with gulp.start(). How do you get them back?

afaik, logging is added when you run gulp from the cli so if you are running it programmatically you will have to add them

@contra Is there an equivalent functionality for gulp.tasks.test in 4.0 alpha 1? While the above code works in 3.8, 4.0 alpha 1 gives an error "Uncaught TypeError: Cannot read property 'test' of undefined".

I also couldn't able to invoke a task programmatically with gulp.series(test)

@dacodekid gulp.task('test') will return the function that is registered for a task named test

@contra In the 3.9 version, gulp.task('test') returns all gulp tasks information, not the single task. Is your mentioned feature new in 4.0?

Here is solution for gulp 3.9:
https://github.com/gulpjs/gulp/issues/494#issuecomment-44716601

Ok, in the spirit of using Gulp programmatically instead of at the command line, what if we want to get the "return" values from Gulp tasks?

Maybe someone could help me with my SO question?

https://stackoverflow.com/questions/40496855/retrieving-result-of-gulp-4-task-programmatically

basically, I have a Gulp task like so:

const t = gulp.task('foo', function(){
        return 5;
});

how can I capture the result of the task?

t.on('done', function(val){

      // this doesn't work TMK
});

@ORESoftware

var gulp = require('gulp')
require('./gulpfile') // import the gulp file

const result = gulp.task('foo')()

Nothing fancy

oh shazam, but what about a curve ball like this Terminator sequence:

const t1 = gulp.task('one',['two'], function(){
             return Promise.resolve(5)
});

const t2 = gulp.task('two', function(){
          return Promise.resolve(11);
}):

surely I can't just do

const result1 = t1();

I must have to listen to an event or something...?

?

apologies, because I have only used Gulp 3 and am planning on using Gulp 4 heavily but still new to it, please correct syntax if it's wrong.

@ORESoftware Yeah, you need gulp 4 for that case

gulpfile.js:

import gulp from 'gulp'

const two = () => Promise.resolve(11)
const one = gulp.series(two, () => Promise.resolve(5))

gulp.task('one', one)
gulp.task('two', two)

code.js:

import gulp from 'gulp'
import './gulpfile'

const result = gulp.task('one')()

With 4, you can also export the tasks from your gulpfile if you're trying to test them. The CLI picks these up too.

Here's what that would look like -

gulpfile.js:

import gulp from 'gulp'

export const two = () => Promise.resolve(11)
export const one = gulp.series(two, () => Promise.resolve(5))

code.js:

import { one, two } from './gulpfile'

const result = one()

thanks let me try that out

another question I have, just for context => the main reason I am interested in using Gulp programmatically is that it may offer some sophisticated ways to only run tasks once and cache the result. In fact, that is the primary reason I am interested in using it programmatically - I can compose tasks and if two different tasks (tasks 2 and 3) both depend on task 1, I can configure Gulp so that task 1 only runs once, and caches the result. I assume this is possible with Gulp 4, if not then I might not use it. Sorry for sidetracking the conversation.

@ORESoftware Wrap your functions with a module like http://npm.im/once or https://github.com/gulpjs/async-once

ok, cool, I can do that, but I think it would be really cool if Gulp did that natively

Tried this, I am getting undefined as a result

const util = require('util');
const gulp = module.exports = require('gulp');

const two = () => Promise.resolve(11);

const one = gulp.series(two, () => Promise.resolve(5));

gulp.task('one', one);
gulp.task('two', two);

const prelim = gulp.task('one');
const result = prelim();

console.log(util.inspect(prelim));
console.log(util.inspect(result));

very confused :/

@ORESoftware Maybe series isn't returning the value - @phated would have more info on that since he built the task system

series and parallel don't return results because they have nothing to return. When invoking, you pass a callback function that passes the errors and results.

prelim(function(err, results) { console.log(err, results); });

Btw, all of this is documented in the dependencies (https://github.com/gulpjs/bach in this case) but haven't been surfaced to the 4.0 docs yet (always looking for people to help!)

Trying to do this with a babel-transpiled Gulpfile, Gulpfile.babel.js - doesn't work for me:

.../node_modules/DEPENDENCY/Gulpfile.babel.js:23
import gulp from "gulp"
^^^^^^
SyntaxError: Unexpected token import
    at Object.exports.runInThisContext (vm.js:76:16)
    at Module._compile (module.js:528:28)
    at Module._extensions..js (module.js:565:10)
    at Object.require.extensions.(anonymous function) [as .js] (.../node_modules/babel-watch/runner.js:63:7)
    at Module.load (module.js:473:32)
    at tryModuleLoad (module.js:432:12)
    at Function.Module._load (module.js:424:3)
    at Module.require (module.js:483:17)
    at require (internal/module.js:20:19)

Somebody experiencing the same issues?

For anyone bumping into this thread and still running into @squidfunk's issue, make sure you've installed gulp-babel and gone through the other Gulp-specific setup steps on Babel's site (including making the .babelrc config file). I just went through this and I had to setup a .babelrc config file using a babel preset to get mine to work.

Go here and click on "Gulp" under build systems for more info:
https://babeljs.io/docs/setup

nah heres how you really do it

var gulp = require('gulp');
require('./gulpfile');

if (gulp.tasks.test) { 
    console.log('gulpfile contains task!');
    gulp.start('test');
}

a gulpfile is just a node script, so you can require it in like any other.

As they said though, .start will be gone in 4.0 and replaced with series and parallel

This doesnt work for me. First of all start doesn't seem to be a function. TypeError: gulp.start is not a function

Second, when I use your if statement. It doesn't pick up my task either.
gulp

Do you know why its not working?

(I can run the task with my definednpm start script which just runs gulp watch

In case someone stumbles over this. It seems like the provided solution is deprecated.
I was able to achieve it via gulp.task('watch')();

gulp.task('taskname') will return the task itself. So we just need to invoke it with another pair if brackets ()

Was this page helpful?
0 / 5 - 0 ratings