Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invoking the Gulp tool programmatically #770

Closed
ghost opened this issue Nov 14, 2014 · 34 comments
Closed

Invoking the Gulp tool programmatically #770

ghost opened this issue Nov 14, 2014 · 34 comments

Comments

@ghost
Copy link

ghost commented Nov 14, 2014

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.

@sogko
Copy link

sogko commented Nov 14, 2014

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?

@stringparser
Copy link

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

@ghost
Copy link
Author

ghost commented Nov 14, 2014

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.

@stringparser
Copy link

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.

@stringparser
Copy link

sorry there was a typo,

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

on that if

@yocontra

This comment has been minimized.

@stringparser
Copy link

Why this then?

@yocontra
Copy link
Member

@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

@stringparser
Copy link

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

@yocontra
Copy link
Member

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

@stringparser
Copy link

interesting :) thanks a lot for the explanation ;)

@ghost
Copy link
Author

ghost commented Nov 15, 2014

@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 :)

@stringparser
Copy link

welcome!

@desandro
Copy link

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

@stringparser
Copy link

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

@dacodekid
Copy link
Contributor

@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)

@yocontra
Copy link
Member

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

@lijunle
Copy link

lijunle commented Jun 13, 2015

@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?

@rafis
Copy link

rafis commented Jul 21, 2016

Here is solution for gulp 3.9:
#494 (comment)

@ORESoftware
Copy link

ORESoftware commented Nov 8, 2016

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
});

@yocontra
Copy link
Member

yocontra commented Nov 8, 2016

@ORESoftware

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

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

Nothing fancy

@ORESoftware
Copy link

ORESoftware commented Nov 8, 2016

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.

@yocontra
Copy link
Member

yocontra commented Nov 8, 2016

@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()

@ORESoftware
Copy link

thanks let me try that out

@ORESoftware
Copy link

ORESoftware commented Nov 8, 2016

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.

@yocontra
Copy link
Member

yocontra commented Nov 8, 2016

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

@ORESoftware
Copy link

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

@ORESoftware
Copy link

ORESoftware commented Nov 8, 2016

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 :/

@yocontra
Copy link
Member

yocontra commented Nov 8, 2016

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

@phated
Copy link
Member

phated commented Nov 8, 2016

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!)

@squidfunk
Copy link

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?

@bradstech01
Copy link

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

@bluebrown
Copy link

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 defined npm start script which just runs gulp watch

@bluebrown
Copy link

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 ()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests