Task inheritance in gulp, parent gulpfile.js - node.js

I am using node/gulp to run/build my projects. Accross those projects my gulpfiles look very similar. Since I'm coming from a Java/Maven background I was looking for sth. like a parent gulpfile one could inherit basic tasks from (this is easily possible with a parent pom.xml in maven).
Is this somehow build into gulp, are there modules doing this or do I need to figure this myself?
I could think of having a node module doing nothing else then providing basic gulp tasks that one can require from his dependent gulp file. Any experiences on an approach like this?
BR
Chris

You could just export the gulp object in your parent gulpfile and then require it in the child gulpfiles:
project/gulpfile.js:
var gulp = require('gulp');
gulp.task('commontask', function () { });
module.exports = gulp;
project/subproject/gulpfile.js:
var gulp = require('../gulpfile.js');
gulp.task('subtask', [ 'commontask' ], function() { });
Running subtask from the project/subproject directory:
> gulp subtask
[12:38:05] Using gulpfile ~/project/subproject/gulpfile.js
[12:38:05] Starting 'commontask'...
[12:38:05] Finished 'commontask' after 50 μs
[12:38:05] Starting 'subtask'...
[12:38:05] Finished 'subtask' after 20 μs
EDIT: The above won't work if the parent gulpfile isn't part of the same package (e.g. my-app) but rather from another package that you depend on (e.g. my-common-tasks). The reason is that the way module loading in Node.js works, you end up with two instances of gulp: one in my-common-tasks and one in my-app. Your tasks will be defined in the instance from my-common-tasks, but the gulp CLI will look for the tasks in the instance from my-app.
Instead you have to pass the gulp instance from my-app to my-common-tasks:
my-common-tasks/gulpfile.js:
module.exports = function(gulp) {
gulp.task('common-task', function () { });
};
my-app/gulpfile.js:
var gulp = require('gulp');
require('my-common-tasks')(gulp);
gulp.task('sub-task', [ 'common-task' ], function() { });

Related

Nodemon crashed when bound with gulp watch and restarted more than twice

I am trying to make my processes (webpack, nodemon-restart) work with a single gulp command. This works well enough. However, webpack builds only once if its task is tied to gulp's default task (together with nodemon), or embedded withing nodemon's gulp task.
Then I decided to tie both webpack build task and nodemon restart task to gulp's watch command and this works just the way I wanted, except that if you make changes and save them more than twice, the app nodemon crashed and prints this error in the console
"/home/nnanyielugo/Workspace/activity-calendar/node_modules/nodemon/lib/monitor/match.js:132
var rules = monitor.sort(function (a, b) {
^
TypeError: Cannot read property 'sort' of undefined"
As a solution, i tried to tie the webpack build task to the nodemon restart using the .on() method, and instead got an infinite loop of restarting an rebuilding (nodemon restarts first, webpack builds, nodemon restarts again, webpack rebuilds, and on and on).
Does anyone have a solution please?`
Here is a sample of my code `
var gulp = require('gulp'),
nodemon = require('gulp-nodemon'),
webpack = require('webpack-stream');
gulp.task('default', ['watch']);
gulp.task('webpack', function() {
return gulp.src('src/entry.js')
.pipe(webpack(require('./webpack.config.js')))
.pipe(gulp.dest('./public'));
});
gulp.task('nodemon', function () {
return nodemon({
script: 'app.js'
, ext: 'js html'
, env: { 'NODE_ENV': 'development' }
})
})
gulp.task('watch', function(){
gulp.watch(['./api/**/*.js', './server/**/*.js', './*.js'], ['webpack', 'nodemon']);
})`
I guess, your nodemon and gulp's watch task collides with each other. Either you should get ride of using nodemon and to rely upon gulp to start your application.
Or else, you can get rid of your gulp's watch task and add the relevant script in your nodemon's restart method like this,
nodemon({
// script goes here.
}).on('restart', your_reload_logic)
Hope this helps!

How to execute the same task with gulp, synchronously, once per each folder (in a monorepo with subpackages)?

I have the following project structure (monorepo with many packages)
/pkgA
gulpfile.js
/pkgB
gulpfile.js
/pkgC
gulpfile.js
Each package has a gulpfile.js which just loads /shared/shared-gulp-tasks.js
Important: we want to keep this independence (so that I can run gulp whatever only for a given package, if wanted) - i.e. I don't want to remove the existing tasks from the shared gulpfile, I want to reuse them.
If we want to build everything at once, we run a task synchronously like this:
bash for-each-package.sh "gulp package"
Which does something like
cd pkgA
gulp package
cd pkgB
gulp package
cd pkgC
gulp package
However this is slow, because I start gulp executable from scratch for each package, and it takes ~3 seconds every time to load gulp and all the needed deps. (we have 20+ subpackages).
What I want is to have a task defined in gulpfile.js in the root which would let me do
gulp package-all
The code would look like this:
gulp.task('package-all', function(done) {
['pkgA', 'pkgB', 'pkgC'].forEach(function(pkgName) {
process.chdir(path.join(__dirname, pkgName));
// need to run 'package' task here, synchronously
// gulp.start('package'); is async
});
done();
}
Note that folder-specific package task is already declared in shared gulpfile and I don't want to rewrite it.
The problem is that I want to do this synchronously, and when all folders are finished processing, call done().
Options explored so far:
gulp.run is deprecated, gulp.start is undocumented, generally not advised
and they don't work in this case (they are async)
runSequence looks promising, but how would I run same task many times, per-folder, with cd to that folder before
I am aware that what I ask is kind-of orthogonal to "the gulp way" but I don't want to rewrite all my tasks.
What can be a good way to achieve my goals?
Finally I solved the issue by using run-sequence and creating fake tasks (not sure if there's an easier way - BTW it seems that gulp tasks can not be anonymous, you can't just pass functions to run-sequence, you need to pass string names of registered gulp tasks) and then a sequence out of those tasks (and passing done at the end of the sequence).
gulpfile.js
var runSequence = require('run-sequence');
var gulp = require('gulp');
require('./shared-gulp-tasks')(gulp);
var folders = ['pkgA', 'pkgB', 'pkgC']; // this array comes from external helper method which reads it from disk
function registerTaskForAllFolders(wrappedTaskName) {
var tasksToExecute = [];
folders.forEach(function(folderName) {
var taskName = wrappedTaskName + '_' + folderName;
gulp.task(taskName, function(done) {
console.log(folderName);
process.chdir(path.join(__dirname, folderName));
runSequence(wrappedTaskName, done);
});
tasksToExecute.push(taskName);
});
gulp.task(wrappedTaskName + '-all', function(done) {
tasksToExecute.push(done);
runSequence.apply(null, tasksToExecute);
});
}
// this registers a task called 'nothing-all'
registerTaskForAllFolders('nothing');
// this registers a task called 'clean-all'
registerTaskForAllFolders('clean');
// this registers a task called 'package-all'
registerTaskForAllFolders('package');
shared-gulp-tasks.js
module.exports = function(gulp) {
gulp.task('nothing', function(done) {
console.log('doing nothing in ' + process.cwd());
done();
});
}
terminal
gulp nothing-all
output
[17:08:51] Starting 'nothing-all'...
[17:08:52] Starting 'nothing_pkgA'...
[17:08:52] Starting 'nothing'...
doing nothing in d:\git\myproject\pkgA
[17:08:52] Finished 'nothing' after 171 μs
[17:08:52] Finished 'nothing_pkgA' after 2.23 ms
[17:08:52] Starting 'nothing_pkgB'...
[17:08:52] Starting 'nothing'...
doing nothing in d:\git\myproject\pkgB
[17:08:52] Finished 'nothing' after 2.03 ms
[17:08:52] Finished 'nothing_pkgB' after 11 ms
[17:08:52] Starting 'nothing_pkgC'...
[17:08:52] Starting 'nothing'...
doing nothing in d:\git\myproject\pkgC
[17:08:52] Finished 'nothing' after 1.93 ms
[17:08:52] Finished 'nothing_pkgC' after 11 ms
[17:08:52] Finished 'nothing-all' after 345 ms

Loading tasks through parent folder

I want Gulp to load and run a task that is in a different folder.
For example:
files tree:
root
lib
task.js
proj
gulpfile.js
task.js:
var gulp = require('gulp');
gulp.task('myTask', function() {
console.log('done!');
});
and gulpfile.js:
var gulp = require('gulp');
gulp.task('default', ['myTask']);
What I've tried so far:
require('../lib/task.js')
require('require-dir')('../lib/')
In both cases I can see task.js is loaded, but I get the following error:
Task 'myTask' is not in your gulpfile
When task.js is in the proj folder or in a sub folder of it - it works fine,
so I think it has something to do about going up to the parent folder through "../" .
Why is this happening and what can be done?
you can use NodeJS's global or module.exports for this purpose.
http://www.hacksparrow.com/global-variables-in-node-js.html

How do I require a directory in a node_module?

To make my gulpfile.js easier to read, I put all of my gulp tasks in a gulp/ directory. The only thing I now do in my gulpfile.js is require in the whole directory like this:
var requireDir = require('require-dir');
requireDir('./gulp');
An example task file is `default.js'
gulp.task('default', function() {
// Do stuff here
});
I now use the same gulp stuff in multiple projects, so I create a npm module and packaged all of my gulp tasks into it. When I try to change my gulpfile.js to point at the directory with the same contenxt in node_modules like this:
var requireDir = require('require-dir');
requireDir('./node_modules/my-gulp/gulp');
it doesn't find any of my tasks. It is the same directory as before, so why won't it work? What can I do to pull in multiple gulp tasks in this manner?

Gulp.js: "gulp-chug" only runs one file even when set to watching many

I've started working with Gulp and the problem I'm having is getting gulp-chug to work properly.
I've followed everything in the documentation, telling my gulpfile to watch all gulpfiles within certain directories, whereas it only watches one file.
This is the code I have used following the documentation...
var gulp = require('gulp');
var chug = require('gulp-chug');
gulp.task('default', function () {
gulp.src('**/task_runner/gulpfile.js')
.pipe(chug());
});
I even tried to see if it makes a difference if I put the filepath in an array...
...
gulp.src(
[ '**/task_runner/gulpfile.js' ]
)
...
I also tried this (and a version without the array in gulp.src())...
...
gulp.src(
[ 'Project_01/task_runner/gulpfile.js', 'Project_02/task_runner/gulpfile.js' ]
)
...
...and it still does the same thing.
My file structure looks like this,
*root*
node_modules
gulpfile.js
package.json
Project_01
css
scss
task_runner
Project_02
css
scss
task_runner
All the gulpfiles work when running them individually, but I want them all to run at the same time within one cmd window with gulp-chug.
This is what my cmd looks like, which is showing that it's only watching Project_02,
C:\Users\WaheedJ\Desktop\UniServer\www\Practice\gulp>gulp
[14:19:40] Using gulpfile ~\Desktop\UniServer\www\Practice\gulp\gulpfile.js
[14:19:40] Starting 'default'...
[14:19:40] Finished 'default' after 6.37 ms
[gulp-chug] File is a buffer. Need to write buffer to temp file...
[gulp-chug] Writing buffer to Project_02\task_runner\gulpfile.tmp.1411996780120.
js...
[gulp-chug] Spawning process C:\Users\WaheedJ\Desktop\UniServer\www\Practice\gul
p\Project_02\task_runner\node_modules\gulp\bin\gulp.js with args C:\Users\Waheed
J\Desktop\UniServer\www\Practice\gulp\Project_02\task_runner\node_modules\gulp\b
in\gulp.js --gulpfile gulpfile.tmp.1411996780120.js default from directory C:\Us
ers\WaheedJ\Desktop\UniServer\www\Practice\gulp\Project_02\task_runner...
[gulp-chug](Project_02\task_runner\gulpfile.tmp.1411996780120.js) [14:19:42] Usi
ng gulpfile ~\Desktop\UniServer\www\Practice\gulp\Project_02\task_runner\gulpfil
e.tmp.1411996780120.js
[gulp-chug](Project_02\task_runner\gulpfile.tmp.1411996780120.js) [14:19:42] Sta
rting 'watch'...
[gulp-chug](Project_02\task_runner\gulpfile.tmp.1411996780120.js) [14:19:43] Fin
ished 'watch' after 18 ms
[14:19:43] Starting 'default'...
[14:19:43] Finished 'default' after 7.13 µs
What can I do to fix this?
I have the same thing happening. For now i employed this workaround :
gulp.task('default', ['one-gulpfile', 'another-gulpfile'], function () {});
gulp.task('one-gulpfile', function () { return gulp.src('./project-one/gulpfile.js').pipe(chug()); });
gulp.task('another-gulpfile', function () { return gulp.src('./project-another/gulpfile.js').pipe(chug()); });
Basically an empty default task, with dependencies on hard coded tasks that each, run one gulp file.
Of course not dynamic, and needs maintenance, but I got it going which is what i needed most at this point in time. I hope to see chug mature a bit more.

Resources