How can I pass arguments to a Gulp task? - node.js

Say I have a task that looks something like this:
settings.localLESS = ["../css/*.less"];
gulp.task('compile-less-files', function(){
gulp.src(settings.localLESS)
.pipe(less())
.pipe(minifyCSS())
.pipe(gulp.dest(someDest));
})
gulp.watch(settings.localLESS, ['compile-less-files']).on('change', function(event) {
...
});
But I don't want to compile them all. I only want to compile the file that I pass as an argument to the task. Perhaps something like this?
gulp.task('compile-less-file', function(fileName){
gulp.src(fileName)
.pipe(less())
.pipe(minifyCSS())
.pipe(gulp.dest(someDest));
})
gulp.watch(settings.localLESS, ['compile-less-file']).on('change', function(event) {
...
});
Update: I want to set up watchers for all source project files and to run specific tasks once any of file will be changed.

Try to break down your project into small partial files, then create a new file which will act as a "master" file where you can import other files. This way you can be able to choose which file to compile when you are importing.

You can use yargs - https://www.npmjs.com/package/yargs
npm install --save-dev yargs
OR
You can use node's process.argv
gulp.task('taskname', function() {
console.log(process.argv);
});
Then you can pass arguments to your task like below
gulp taskname --option 123

Related

gulp - command-line to run a task on a specific file

I have a task scripts that do all that normal stuff with scripts on watch:
var folderScripts = "assets/scripts";
gulp.task('scripts', function(){
gulp.src([
folderScripts+'/**/*.js',
'!'+folderScripts+'/**/_*.js',
'!'+folderScripts+'/**/*.min.js'
])
// uglify, rename, etc etc...
.pipe(gulp.dest( function(file) { return file.base; } ));
});
Sometimes, I may need to run that task scripts only for a specific file outside that folder, ex: assets/plugins/flexsider/flexslider.js I'm wondering if it would be possible to do something like this on terminal:
gulp scripts assets/plugins/flexsider/flexslider.js
and then the task scripts would replace gulp.src() content for a dynamic content, this case assets/plugins/flexsider/flexslider.js, and would be like this:
var folderScripts = "assets/scripts";
gulp.task('scripts', function(){
gulp.src('assets/plugins/flexsider/flexslider.js') //this would be the "flag" I passed on terminal line
// uglify, rename, etc etc...
.pipe(gulp.dest( function(file) { return file.base; } ));
});
I searched for gulp-exec and similares but I think it is not what i'm looking for.
Thanks
Install yargs
npm install yargs --save-dev
Your task:
gulp.task('scripts', function(){
// require yargs
var args = require('yargs').argv;
var arraySources = [
folderScripts+'/**/*.js',
'!'+folderScripts+'/**/_*.js',
'!'+folderScripts+'/**/*.min.js'];
// check for an argument called file (or whatever you want)
// and set the source to the file if the argument exists. Otherwise set it to the array
var source = args.file? args.file : arraySources;
gulp.src(source)
// uglify, rename, etc etc...
.pipe(gulp.dest( function(file) { return file.base; } ));
});
Call your task from the prompt:
gulp scripts --file=assets/plugins/flexsider/flexslider.js
which will run scripts on that file only.
or
gulp scripts
which will run scripts as before

Trouble getting Grunt to run node.js script

I am a grunt and node noob but I managed to write a node script that does what I want it to and works from the command line. I don't want to publish the script as a node module but I would like to run it from my grunt file.
What changes (if any) do I need to make to the script for this to work?
The more I read about configuring grunt files and custom tasks the more confused I get. I currently have something that looks like this:
module.exports = function(grunt) {
grunt.initConfig({
'mytaskname': 'what goes here?'
});
grunt.loadNpmTasks('./node_modules/script_name');
grunt.registerTask('run-from-command-line', 'description', function() {
grunt.log.writeln('Not running...');
});
}
Any help would be greatly appreciated.
You could use the grunt-execute plugin for doing this which executes files in a node.js child process.
Example:
If your node script is in "node-scripts/script.js", Gruntfile.js would look something like this:
module.exports = function(grunt) {
grunt.initConfig({
execute: {
target: {
src: ["node-scripts/script.js"]
}
}
});
// Load the plugins
grunt.loadNpmTasks("grunt-execute");
grunt.registerTask("default", ["execute"]);
};

How can the base directory be replaced with gulp?

I need to alter a stream of files to contain a different base folder name. I thought the gulp-rename plugin would allow for this, but it only seems to replace the glob portion.
Example:
gulp.task("test", function() {
gulp.src("bower_components/**/*", { base: "bower_components", read:false })
.pipe($.rename(function (p) { p.dirname = "X/" + p.dirname; }))
.pipe($.print());
});
outputs:
[gulp] bower_components\X\jquery\test\data\offset\scroll.html
[gulp] bower_components\X\jquery\test\data\offset\static.html
[gulp] bower_components\X\jquery\test\data\offset\table.html
...
I want
[gulp] X\jquery\test\data\offset\scroll.html
[gulp] X\jquery\test\data\offset\static.html
[gulp] X\jquery\test\data\offset\table.html
...
Is there a way to do this with gulp-replace, or some other plugin?
I believe you could do this with gulp-tap to get a hold of the the file instances and alter properties on them before they get printed or use it to print them.
Out of curiosity what are you aiming to do?
Hope that helps!
EDIT-1::
The following is a slightly modified version of the example in the gulp-tap documentation which may work for your use case.
gulp.src("src/**/*.{coffee,js}")
.pipe(tap(function(file, t) {
file.path = 'X/' + file.path;
}))
.pipe($.print())
.pipe(gulp.dest('build'));
EDIT-2::
This is a common task I have set up in my projects for handling external scripts (note; I am using gulp-load-plugins hence invoking my plugins with plugins.<NAME>);
gulp.task('vendor:scripts:publish', function() {
return gulp.src(sources.vendor.js)
.pipe(plugins.plumber())
.pipe(plugins.concat('vendor.js'))
.pipe(gulp.dest(destinations.js))
.pipe(plugins.uglify())
.pipe(plugins.rename(pluginOpts.rename))
.pipe(gulp.dest(destinations.js));
});
destinations and sources are two variables that I have defined in a config file for my gulpfile.
But for clarity, sources.vendor.js points at an array much like the following;
js: [
'src/vendor/jquery/dist/jquery.js',
'src/vendor/lodash/lodash.js',
'src/vendor/backbone/backbone.js'
],
The reason my folder is named vendor and not bower_components is because I've made use of a .bowerrc file to point my bower installation at a different folder.
In addition if you have discrete scripts that you may not want to include all of the time you can look to make use of gulp-utils and gulp-filter to filter out certain scripts when an option is passed or not passed when gulp is invoked on the CLI.
For example; having gulp vendor:scripts:publish include all scripts but gulp vendor:scripts:publish --release omitting discrete scripts.
This then requires modifying your task to declare a filter that is piped in based on an option flag being picked up by gulp-utils.
var isRelease = (plugins.utils.env.release) ? true: false;
gulp.task('vendor:scripts:publish', function() {
var discreteFilter = plugins.filter([
'**/*.js',
'!**/discrete.min.js'
]);
return gulp.src(sources.vendor.js)
.pipe(plugins.plumber())
.pipe(isRelease ? discreteFilter: plugins.utils.noop())
.pipe(plugins.concat('vendor.js'))
.pipe(gulp.dest(destinations.js))
.pipe(plugins.uglify())
.pipe(plugins.rename(pluginOpts.rename))
.pipe(gulp.dest(destinations.js));
});
Hope that helps you out!

Include Gruntfile and run a task in an another file

I have an app using Grunt, that I launch in my terminal, and I want to run a task through an another app.
So I'd like to know how can I include my Gruntfile.js to this other app, and run the task.
For now this new app is really basic, juste a simple local web page using NodeJS, with a button that launch the task.
Gruntfile (I want to run the "archive" task)
module.exports = function (grunt) {
require('time-grunt')(grunt);
require('jit-grunt')(grunt, {
ngtemplates: "grunt-angular-templates"
});
var Generator = require("./generator.js")(grunt);
var generator = new Generator();
generator.printLogo();
// Build
grunt.registerTask("build", function (fileType) {
//definition of build task
grunt.task.run(tasks);
});
// Archive Task.
grunt.registerTask("archive", ["build", "compress", "clean:post-rsync"]);
};
Other file : (I tried a require, It seems to work, but I can't run the "archive" task of the Gruntfile.)
var grunt = require('grunt');
var gruntfile = require('./Gruntfile.js')(grunt);
var app = express();
app.get('/', function(req, res){
res.render('test.ejs');
});
app.post('/create', function(req, res){
//run grunt task "archive" here
//gruntfile.grunt.registerTask("archive", ["build"]);
res.redirect('/');
});
app.listen(8080);
Do you have any idea how could I run the task in my gruntfile in this other file ?
(The function printLogo() is working so i'm sure the Gruntfile is include)
Thank you very much (I'm a beginner with Grunt so sorry if I miss something trivial)
You can just run a command from node. This way you don’t have to worry about dependencies and what not. You just spawn grunt, like you normally would, except programatically.
var spawn = require('child_process').spawn;
// This will run the 'archive' task of grunt
spawn('grunt', ['archive'], {
cwd: 'path/to/grunt/project'
});
Grunt is a command line tool, the cleanest approach here would be to refactor your Gruntfile and extract your task's logics into a library.
Then from your Gruntfile's task you can call that library, and from your /create route you can also call your library.
You can use grunt-hub plugin:
grunt.initConfig({
hub: {
all: {
src: ['../*/Gruntfile.js'],
tasks: ['jshint', 'nodeunit'],
},
},
});

How to use jasmine with gulp.watch

I'm trying to make my tests run each time I'm saving some files. Here is the gulp watch:
gulp.task('jasmine', function() {
gulp.src('spec/nodejs/*Spec.js')
.pipe(jasmine({verbose:true, includeStackTrace: true}));
});
gulp.task('watch', function () {
gulp.watch(['app/*.js', 'app/!(embed)**/*.js','spec/nodejs/*.js'], ['jasmine']);
});
To test for example app/maps.js I'm creating a spec/nodejs/mapsSpec.js file like this:
'use strict';
var maps = require('../../app/maps');
describe('/maps related routes', function(){
it('should ...', function(){...}
...
If I change a spec file everything is working well, if I modify app/maps.js file the change trigger the test. if I modify it again tests are tiggered but the modifications do not taking effect. For example if I add a console.log('foo') in a second time, I will not see it until I relaunch gulp watch and save it again. So only one run of jasmine is ok when using it with gulp.watch.
I guess it's because require is cached by nodejs in the gulp process. So how should I do ?
I took a look at the code of gulp-jasmine. The problem is that the only file from the cache is the Specs.js file. The cache of the children(the reqquired files to test) aren't cleared.
Within the index.js of gulp-jasmine is a row which deletes the cache:
delete require.cache[require.resolve(path.resolve(file.path))];
If you put the next block of code before the delete, you will delete all the children's cache and will it run correctly after every time you save your file.
var files = require.cache[require.resolve(path.resolve(file.path))];
if( typeof files !== 'undefined' ) {
for( var i in files.children ) {
delete require.cache[ files.children[i].id ];
}
}
You can change this in the node_modules.
I will go for a pull request, so maybe in the near future this will be solved permanently.
Also wrote a post about it on: http://navelpluisje.nl/entry/fix-cache-problem-jasmine-tests-with-gulp
I haven't found a fix for this issue, but you can work around it via the gulp-shell task.
npm install gulp-shell --save-dev
then
var shell = require('gulp-shell');
...
gulp.task('jasmine', function() {
gulp.src('spec/nodejs/*Spec.js')
.pipe(shell('minijasminenode spec/*Spec.js'));
});
You'll also need jasmine installed as a direct dependency (gulp-jasmine uses minijasminenode)

Resources