gulp tasks sharing a common setting without a global object - javascript

I have a number of gulp tasks each residing in its own file (using the require-dir module) rather than a monolithic file.
I am using modules for configuration settings instead of json files (which I prefer for comments and for derived values).
To keep things simple here is an example setup with a single key I need to share/set between the gulp tasks.
/config/index.js
var config = {}
config.buildType = ''; // set this to either 'dev' or 'dist'
module.exports = config;
here is default task for which I want to set config.buildType to 'dev'
default.js
var gulp = require('gulp');
var config = require('../config/');
gulp.task('default', ['build'], function(cb) {
});
here is a deploy task for which I want to set buildType to 'dist'
deploy.js
var gulp = require('gulp');
var config = require('../config/');
gulp.task('deploy-s3', ['build'], function() {
});
here is a build task that I want to change based on buildType
build.js
var gulp = require('gulp');
var runSequence = require('run-sequence');
var config = require('../config/');
gulp.task('build', function(cb) {
console.log('in build',config.buildType);
if (config.buildType == 'dev') runSequence('clean',['sass',config.htmlGenerator], 'watch', cb);
if (config.buildType == 'dist') runSequence('clean',['sass',config.htmlGenerator], cb);
});
So here is the issue If I set config.buildType in default.js or deploy.js outside gulp.task then since they are all lumped into essentially one file by require-dir the value is simply whichever file was loaded last. If I set it inside the gulp.task function I am confused about about the timing/scope of that setting.
Update: Found this related issue https://github.com/gulpjs/gulp/issues/193. It was pointed out in this issue the task function starts after all the queued tasks so that means I can't set something inside the task function and expect it to be executed before the listed tasks (in my case 'build')
one poster made a task to set a parameter like this
gulp.task('set-dist', function () {
config.buildType = 'dist';
});
gulp.task('deploy', ['set-dist', 'build']);
So some advice..... do I go the way of this "hack" or is there some better way to do this??
(fyi, I am just a couple months into learning node/javascript on my own so my experience is limited)

You can use process.env to hold config attributes for your project. Check this.
In your case you can do:
var gulp = require('gulp');
var runSequence = require('run-sequence');
gulp.task('build', function(cb) {
if (process.env.NODE_ENV === 'development') {
runSequence('clean',['sass',config.htmlGenerator], 'watch', cb);
} else {
runSequence('clean',['sass',config.htmlGenerator], cb);
}
});
gulp build NODE_ENV=production for production
or gulp build NODE_ENV=development.
This will play nicely with existing CI tools like Travis.

Decided to go with this dropping the 'build' task altogether. It will hopefully work in some similar form after gulp 4.0 is released. It allows me to modify any setting before calling other tasks. Can use it with gulpif in tasks like my 'sass' task which is a pipe only task. Still wondering if there is a "better" way.
var gulp = require('gulp');
var config = require('../config/');
var runSequence = require('run-sequence');
gulp.task('default', function(cb) {
config.buildType='dev'
config.url = 'http://localhost:' + config.localport;
runSequence('clean',['sass',config.htmlGenerator],'watch', cb);
});

Related

How to fix a relative path when using browserify

I am trying to use browserify to compile all js files.
The issue I am having is currently with: https://github.com/amsul/pickadate.js
In: https://github.com/amsul/pickadate.js/blob/master/lib/picker.date.js
It requires a relative path:
require('./picker.js')
I assume I will run into this issue again with other files.
Once all the js files get compiled and moved to my 'dest' directory this relative path is no longer correct.
Is there a way to overwrite this so it can get the right file?
Here is my full gulp task I am currently using:
gulp.task('js', function () {
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var globby = require('globby');
var through = require('through2');
var uglify = require('gulp-uglify');
var sourcemaps = require('gulp-sourcemaps');
var reactify = require('reactify');
// gulp expects tasks to return a stream, so we create one here.
var bundledStream = through();
bundledStream
// turns the output bundle stream into a stream containing
// the normal attributes gulp plugins expect.
.pipe(source('app.js'))
// the rest of the gulp task, as you would normally write it.
// here we're copying from the Browserify + Uglify2 recipe.
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
// Add gulp plugins to the pipeline here.
.pipe(uglify())
.on('error', gutil.log)
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('./dest/js/'))
.pipe(connect.reload());
// "globby" replaces the normal "gulp.src" as Browserify
// creates it's own readable stream.
globby([
'./app/js/*.js',
'./app/js/materialize/**/*.js',
'./app/components/**/*.js'
], function(err, entries) {
// ensure any errors from globby are handled
if (err) {
bundledStream.emit('error', err);
return;
}
// create the Browserify instance.
var b = browserify({
entries: entries,
debug: true,
transform: [reactify]
});
var browser = browser({
});
// pipe the Browserify stream into the stream we created earlier
// this starts our gulp pipeline.
b.bundle().pipe(bundledStream);
});
// finally, we return the stream, so gulp knows when this task is done.
return bundledStream;
});
picker.js lives at: ./app/js/materialize/date_picker/picker.js
Which is the right location until I browserify and move it.

How to setup jade includes with gulp-jade

I am currently using gulp-jade and I am struggling on how to setup Jade includes in my gulpfile.js.(For clarification, I am referring to this here http://jade-lang.com/reference/includes/) The following is the code in my gulpfile.js
var gulp = require('gulp');
var browserSync = require('browser-sync');
var sass = require('gulp-sass');
var uglify = require('gulp-uglify');
var jade = require('gulp-jade');
var jshint = require('gulp-jshint');
var fileinclude = require('gulp-file-include');
var reload = browserSync.reload;
//compile jade to html
gulp.task('templates', function() {
var YOUR_LOCALS = {};
gulp.src('./app/jade/*.jade')
.pipe(jade({
locals: YOUR_LOCALS
}))
.pipe(gulp.dest('./dist/'))
});
//reload files, once jade compilation happens
gulp.task('jade-watch', ['templates'], reload);
//Sass task for live injecting into all browsers
gulp.task('sass', function () {
gulp.src('./app/scss/*.scss')
.pipe(sass())
.pipe(gulp.dest('./dist/css'))
.pipe(reload({stream: true}));
});
//Separate task for the reaction to js files make change even without compilation and what not
gulp.task('compress', function() {
return gulp.src('./app/js/*.js')
.pipe(uglify())
.pipe(gulp.dest('./dist/js'));
});
gulp.task('js-watch', ['compress'], reload);
//Serve and watch the scss/jade files for changes
gulp.task('default', ['sass', 'templates', 'compress'], function () {
browserSync({server: './dist'});
gulp.watch('./app/**/*.jade', ['jade-watch']);
gulp.watch('./app/scss/*.scss', ['sass']);
gulp.watch('./app/js/*.js', ['js-watch']);
});
I know it is quite a bit to parse through. I am hoping it is a standard something, that won't take too long. If you are interested in seeing the entire file structure, it can be seen at my github here https://github.com/CharlieGreenman/Gulp-with-foundation-and-sass
Thank you, and any help would be more than appreciated!
I wrote a Gulp plugin that simplifies your includes by allowing you to add some arbitrary paths to resolve includes and extends to, so you don't have to worry so much about relative pathing. Take a look: https://github.com/tomlagier/gulp-jade-modules
Turns out it was really simple. There were one thing I was doing wrong
I was using includes ../includes/head instead of include ../includes/head (using includes actually worked for me in grunt, upon further research I saw I was using it wrong for gulp.).

Multiple gulp files and inheriting tasks from other gulpfiles.js using require

I am trying to require a gulpfile (someGulpfile.js) in my own gulpfile (gulpfile.js) from where I run the gulp command. When I try to use the tasks defined in someGulpfile it throws an error on console saying Task 'default' is not in your gulpfile even though I just did require('./someGulpfile'); in my gulpfile.js
How can I use the tasks defined in someGulpfile? What is causing this issue?
I found out that this somewhat works but it does not output every task that is run (for example it does not output, Starting sometask, Finished sometask, Starting default, ...) and if there is an error it does not show the error and where it happened but errors out in the gulp library code where it has trouble formatting the error output.
//gulpfile.js
var gulp = require('gulp');
gulp.tasks = require('./someGulpfile').tasks;
//someGulpfile.js
var gulp = require('gulp');
gulp.task('sometask', function() {});
gulp.task('default', ['sometask']);
module.exports = gulp;
Could try something like this:
gulpfile.js
require("./gulp/tasks/build-js.js")();
require("./gulp/tasks/build-css.js")();
./gulp/tasks/build-js.js
var gulp = require("gulp");
module.exports = function() {
gulp.task("js", function() {
return gulp.src("./app/**/*.js")
.pipe();
//etc.
}
}
./gulp/tasks/build-css.js
var gulp = require("gulp");
module.exports = function() {
gulp.task("css", function() {
return gulp.src("./app/style/*.css")
.pipe();
//etc.
}
}
This will let you modularize your gulp tasks into different folders.

Gulp task dependency

I would like to run (and complete) my "clean" task before running the rest of my build task.
This currently works, although "run" is deprecated and I'd like to replace it:
gulp.task('build', ['clean'],function() {
gulp.run(['styles-nomaps','usemin','scripts','assets']);
});
What's the proper syntax?
You can use the run-sequence plugin.
You can use rimraf util to clean files, it can be run in sync mode:
clean.js:
var gulp = require('gulp');
var rimraf = require('rimraf');
gulp.task('clean', function(cb) {
rimraf.sync(paths.assets, cb); // Make sure you pass callback
});

Node.js: how do I pass global variable into a file being inserted through require()?

I've split my gulpfile.js into several files in a /gulp folder to organize the code a little better. But now I want to pass a variable debug (boolean) into the files that will switch behaviour of the gulp command being included (eventually I will use command-line arguments, but for now I just want to make it work with a variable).
The way I've got this setup, using a method I saw in a yeoman angular/gulp package, is using an npm module called require-dir (which loads all *.js files in the /gulp folder, where each has a set of gulp tasks that are set).
gulpfile.js:
var gulp = require('gulp'),
run = require('run-sequence'),
debug = true;
require('require-dir')('./gulp');
gulp.task('default', ['build', 'server', 'watch', '...']);
Which would load something like...
gulp/build.js:
var gulp = require('gulp'),
plumber = require('gulp-plumber'),
...;
gulp.task('build', function () {
console.log(debug);
});
So when I run command gulp, which runs the default task, it will load build.js and then execute the build gulp task. But unfortunately, it seems that debug returns undefined.
How could I get this to work?
I was looking at using just module.exports() and node's require() method, but I couldn't figure out how to get the gulp task inside the included file to declare, so that it could then be run from the main gulpfile.js file (in the desired sequence).
Can anyone offer some assistance? Thanks
The normal module way, really. Just change that gulp/build.js file from not actually exporting anything to a proper require-able module:
module.exports = function(debug) {
"use strict";
var gulp = require('gulp'),
plumber = require('gulp-plumber'),
...;
gulp.task('build', function () {
console.log(debug);
});
};
and then call it in your main file as:
...
var loadGulp = require('require-dir/gulp');
...
var debug = true;
loadGulp(debug);
Node.js offers a single global variable named global which is, in fact, the same instance in all modules (unlike module which is different in each module). By setting values on global they become truly global. As an added bonus, you don't need the prefix access to global variables with global.. Both global.foo and just foo are equivalent so long as you don't have another variable named foo in scope.
I just create one object with all variables in it that I export as a module so I can use it throughout all my task files. For example
js/tasks/variables.js
module.exports = {
myBool: true
};
js/tasks/sass.js
var gulp = require('gulp'),
$ = require('gulp-load-plugins')(),
log = $.util.log,
vars = require('./variables');
gulp.task('sass', function () {
log('myBool: ' + vars.myBool); // logs "myBool: true"
vars.myBool = false;
});
js/tasks/build.js
var gulp = require('gulp'),
$ = require('gulp-load-plugins')(),
log = $.util.log,
vars = require('./variables');
gulp.task('build', function () {
log('myBool: ' + vars.myBool); // logs "myBool: false"
});
/gulpfile.js
Then you can get/set those variables from anywhere:
var gulp = require('gulp'),
$ = require('gulp-load-plugins')(),
runSequence = require('run-sequence'),
vars = require('./js/tasks/variables'),
requireDir = require('require-dir')('./js/tasks');
gulp.task('production', function(){
runSequence('sass', 'build');
});

Categories

Resources