gulp - command-line to run a task on a specific file - node.js

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

Related

Node.js Gulp no outputfile created

I have a Gulp script to concatenate, and minimize javascript.
It seems to be working but doesn't output the combined file.
The script is (complete - including extra debug bits):
// include plug-ins
var fs = require('fs');
var gulp = require('gulp');
var count = require('gulp-count');
var debug = require('gulp-debug');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var del = require('del');
var config = {
src: 'dist/libraries/',
dest: 'dist/js/',
outputfile: 'libraries.min.js'
}
gulp.task('read', (done) => {
fs.readdir(config.src, (err, items) => {
console.log(items);
});
done();
});
//delete the output file(s)
gulp.task('clean', gulp.series('read'), (done) => {
//del is an async function and not a gulp plugin (just standard nodejs)
//It returns a promise, so make sure you return that from this task function
// so gulp knows when the delete is complete
return del([config.dest + config.outputfile]);
});
// Combine and minify all files from the app folder
// This tasks depends on the clean task which means gulp will ensure that the
// Clean task is completed before running the scripts task.
gulp.task('scripts', gulp.series('clean'), (done) => {
//Include all js files but exclude any min.js files
var files = [config.src + '*.js', '!' + config.src + '*.min.js'];
return gulp.src(files)
.pipe(debug())
.pipe(count('## files selected'))
.pipe(uglify())
.pipe(concat(config.outputfile))
.pipe(gulp.dest(config.dest));
});
//Set a default tasks
gulp.task('default', gulp.series('scripts'), (done) => {
});
Which produces the output - including file list for verification there are src files:
[07:46:25] Using gulpfile <path>\gulpfile.js
[07:46:25] Starting 'default'...
[07:46:25] Starting 'scripts'...
[07:46:25] Starting 'clean'...
[07:46:25] Starting 'read'...
[07:46:25] Finished 'read' after 996 μs
[07:46:25] Finished 'clean' after 2.73 ms
[07:46:25] Finished 'scripts' after 4.26 ms
[07:46:25] Finished 'default' after 6.9 ms
[ 'bootstrap-datetimepicker.js',
'bootstrap.min.js',
'chart.min.js',
'cycle.js',
'farbtastic.js',
'jquery-3.2.1.min.js',
'jquery-sortable-min.js',
'moment.min.js',
'ol.min.js',
'pablo.min.js',
'popper.min.js',
'proj4.js',
'promisedIndexDB.js',
'qunit-2.6.1.js',
'toastr.js' ]
If I create an empty file, at dist/js/libraries.min.js it isn't deleted as part of the gulp tasks, however if i move the call to del() outside the gulp tasks it is deleted, so that leads me to assume that its not as simple as a permissions issue, or path issues.
Any idea what I've done wrong?
PS: its on a windows box, running in an admin cmd window.
You were using the wrong signature for the task. The correct one is :
task([taskName], taskFunction)
see task signature
But your tasks look like this:
gulp.task('scripts', gulp.series('clean'), (done) => { // 3 parameters
Merely changing that to:
gulp.task('scripts', gulp.series('clean', (done) => {
...
}));
makes it work - I tested it. So now that task has only two parameters: a task name and a function. Yours had a task name plus two functions.
You would also need to change your default and clean tasks to this proper signature. Also you should call done() at the end of the task as you did with your cb().
Your new code uses task functions, which are better than named tasks for a number of reasons - but now you know what was wrong with your original code. The main body of your scripts task was never being run.
I never worked out what was wrong, but went direct to the doc's and started again (previous version was from a example)..
Works with the below (much simpler) script.
// // include plug-ins
var gulp = require('gulp');
var count = require('gulp-count');
var debug = require('gulp-debug');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var del = require('del');
var config = {
src: 'jspa-scada/dist/libraries/',
dest: 'jspa-scada/dist/js/',
outputfile: 'libraries.min.js'
}
function defaultTask(cb) {
del([config.dest + config.outputfile]);
// Include all js files but exclude any min.js files
var globs = [
config.src + '*.js',
'!' + config.src + '*.min.js'
];
return gulp.src(globs)
.pipe(debug())
.pipe(count('## files selected'))
.pipe(uglify())
.pipe(concat(config.outputfile))
.pipe(gulp.dest(config.dest));
cb();
}
exports.default = defaultTask

Restarting gulp after changes to gulpfile.js

I am attempting to re-run my gulp build when gulpfile.js changes, but I am having issues with the method all of my research has lead me to.
I have one watcher for all my less and javascript files and a configuration object that has the list of files to watch, how they are output, etc. This is a stripped-down example of what it looks like:
var $ = require('gulp-load-plugins')();
var config = {
root: rootPath,
output: {
app: 'app',
vendor: 'vendor'
}, // ...
};
gulp.task('default', ['build', 'watch']);
gulp.task('build', ['clean', 'less:app', 'less:theme', 'css:vendor', 'js:app', 'js:vendor', 'rev', 'css:copyfonts']);
gulp.task('watch', function () {
var allFiles = config.styles.appSrc
.concat(config.styles.vendorSrc)
.concat(config.scripts.appSrc)
.concat(config.scripts.vendorSrc);
$.watch(allFiles, function () {
gulp.start('default');
});
});
gulp.task('watch:gulp', function () {
var p;
gulp.watch('gulpfile.js', spawnUpdatedGulp);
spawnUpdatedGulp();
function spawnUpdatedGulp() {
if (p) {
p.kill();
}
p = spawn('gulp', ['default', '--color'], { stdio: 'inherit' });
}
});
// .. other build tasks ..
The above code shows how I tried the accepted answer to this:
How can Gulp be restarted upon each Gulpfile change?
However, it has a major issue. When I run watch:gulp, it runs the build just fine, and everything is great. The config.output.app variable is how the app specific css and js files are named, so my test case has been:
run gulp:watch, check that the css output is named according to config.output.app
change config.output.app, and perform step #1 again
save any random javascript file that it is watching, and see if it builds correctly
Step 3 is riddled with permission errors because of multiple watchers on the files, and this only gets worse the more I repeat steps 1 and 2. Visual Studio will even freeze.
I have not found a way to clean up the old watchers. I tried to manually kill them like this:
var appFileWatcher;
gulp.task('watch', function () {
var allFiles = config.styles.appSrc
.concat(config.styles.vendorSrc)
.concat(config.scripts.appSrc)
.concat(config.scripts.vendorSrc);
appFileWatcher = $.watch(allFiles, function () {
gulp.start('default');
});
});
gulp.task('watch:gulp', function () {
var p;
var gulpWatcher = $.watch('gulpfile.js', spawnUpdatedGulp);
spawnUpdatedGulp();
function spawnUpdatedGulp() {
if (p) {
p.kill();
}
if (appFileWatcher) {
appFileWatcher.unwatch();
}
gulpWatcher.unwatch();
p = spawn('gulp', ['default', '--color'], { stdio: 'inherit' });
}
});
This also does not work. I still get multiple watchers trying to perform the build when I perform my same test case.
How do I kill those watchers that stay around after the new gulp process is spawned?

How can I pass arguments to a Gulp task?

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

jasmine with gulp, run tests on test file changed

Hi what I trying to do is to make watcher task with gulp which will run my jasmine tests. What I have done so far:
var watch = require("gulp-watch");
var jasmine = require("gulp-jasmine");
gulp.task('tests.run.change-watcher', function (cb) {
gulp.src(testsFiles)
.pipe(watch(testsFiles))
.pipe(jasmine({ verbose: true }));
});
But when I run that task and try to change any file which meets the testsFiles rules it doesn't show anything in console.
However when I run the next task:
gulp.task('tests.run', function (cb) {
gulp.src(testsFiles)
.pipe(jasmine({verbose:true}));
});
It works and shows next:
8 specs, 0 failures Finished in 0 seconds
Maybe I miss something?
Do it in two steps
1) Declare the test-unit task (like you did)
gulp.task('tests.run', function () {
return gulp.src(testsFiles)
.pipe(jasmine({verbose:true}));
});
2) Declare the watch task that will run this test-unit task when those testsFiles change
gulp.task('tests.watch', function () {
gulp.watch(testsFiles, ['tests.run']);
});
Then, you run gulp tests.watch
To run only needed specs, try something like this:
/** Watches file changes in source or spec files and executes specs automatically */
gulp.task("specs-watcher", function() {
return watch(["src/**/*.ts", "spec/**/*.ts"], { events: ["add", "change"] }, function(vinyl, event) {
if (!vinyl.isDirectory()) {
if (vinyl.basename.endsWith(".spec.ts")) {
// We are dealing with a spec file here, so call jasmine!
runJasmine(vinyl.path);
} else {
// Try to find out specs file
const specFilePath = findSpecsFile(vinyl);
if (typeof specFilePath === "string") {
runJasmine(specFilePath);
}
}
}
});
});
This watcher uses two functions, one is for deriving the spec name based on the file name. In my case, it's:
/**
* For your specs-watcher: This function is called every time a file changed which doesn't end with '.spec.ts'.
* The function's task is to return the fitting specs path of this file. For example by looking for a corresponding file in the "/spec/" folder.
* #param {vinyl} changedFile Vinyl object of changed file (see https://github.com/gulpjs/vinyl)
* #return {string|undefined} Path to the specs file to execute or undefined if your watcher shouldn't do anything.
*/
function findSpecsFile(changedFile) {
return changedFile.path.replace(__dirname, `${__dirname}/spec`).replace(".ts", ".spec.ts");
}
The other function is runJasmine, which runs jasmine with a given test file.
Just make everything fit to your setup and it should work. :-)
You can listen to file changes for both tests and source code folders with this:
"use strict";
var gulp = require('gulp');
var mocha = require('gulp-mocha');
var batch = require('gulp-batch');
gulp.watch(['tests/**', 'src/**'], batch(function (events, cb) {
return gulp.src(['tests/*.js'])
.pipe(jasmine({ verbose: true }))
.on('error', function (err) {
console.log(err.stack);
});
}));
gulp.task('default', () => {
console.log('Gulp is watching file changes...');
});

Gulp, livereload, jade

Need help.
I use gulp-conect and it livereload method. But if I build a few template in time, get a lot of page refresh. Is any solution, I want to build few templates with single page refresh?
So, I reproduce the problem you have and came accross this working solution.
First, lets check gulp plugins you need:
gulp-jade
gulp-livereload
optional: gulp-load-plugins
In case you need some of them go to:
http://gulpjs.com/plugins/
Search for them and install them.
Strategy: I created a gulp task called live that will check your *.jade files, and as you are working on a certain file & saving it, gulp will compile it into html and refresh the browser.
In order to accomplish that, we define a function called compileAndRefresh that will take the file returned by the watcher. It will compile that file into html and the refesh the browser (test with livereload plugin for chrome).
Notes:
I always use gulp-load-plugin to load plugins, so thats whay I use plugins.jad and plugins.livereload.
This will only compile files that are saved and while you have the task live exucting on the command line. Will not compile other files that are not in use. In order to accomplish that, you need to define a task that compiles all files, not only the ones that have been changed.
Assume .jade files in /jade and html output to /html
So, here is the gulpfile.js:
var gulp = require('gulp'),
gulpLoadPlugins = require('gulp-load-plugins'),
plugins = gulpLoadPlugins();
gulp.task('webserver', function() {
gulp.src('./html')
.pipe(plugins.webserver({
livereload: true
}));
gulp.watch('./jade/*.jade', function(event) {
compileAndRefresh(event.path);
});
});
function compileAndRefresh(file) {
gulp.src(file)
.pipe(plugins.jade({
}))
.pipe(gulp.dest('./html'))
}
Post edit notes:
Removed liveReload call from compileAndRefresh (webserver will do that).
Use gulp-server plugin insted of gulp-connect, as they suggest on their repository: "New plugin based on connect 3 using the gulp.src() API. Written in plain javascript. https://github.com/schickling/gulp-webserver"
Something you can do is to watch only files that changes, and then apply a function only to those files that have been changed, something like this:
gulp.task('live', function() {
gulp.watch('templates/folder', function(event) {
refresh_templates(event.path);
});
});
function refresh_templates(file) {
return
gulp.src(file)
.pipe(plugins.embedlr())
.pipe(plugins.livereload());
}
PS: this is not a working example, and I dont know if you are using embedlr, but the point, is that you can watch, and use a callback to call another function with the files that are changing, and the manipulate only those files. Also, I supposed that your goal is to refresh the templates for your browser, but you manipulate as you like, save them on dest or do whatever you want.
Key point here is to show how to manipulate file that changes: callback of watch + custom function.
var jadeTask = function(path) {
path = path || loc.jade + '/*.jade';
if (/source/.test(path)) {
path = loc.jade + '/**/*.jade';
}
return gulp.src(path)
.pipe(changed(loc.markup, {extension: '.html'}))
.pipe(jade({
locals : json_array,
pretty : true
}))
.pipe(gulp.dest(loc.markup))
.pipe(connect.reload());
}
First install required plugins
gulp
express
gulp-jade
connect-livereload
tiny-lr
connect
then write the code
var gulp = require('gulp');
var express = require('express');
var path = require('path');
var connect = require("connect");
var jade = require('gulp-jade');
var app = express();
gulp.task('express', function() {
app.use(require('connect-livereload')({port: 8002}));
app.use(express.static(path.join(__dirname, '/dist')));
app.listen(8000);
});
var tinylr;
gulp.task('livereload', function() {
tinylr = require('tiny-lr')();
tinylr.listen(8002);
});
function notifyLiveReload(event) {
var fileName = require('path').relative(__dirname, event.path);
tinylr.changed({
body: {
files: [fileName]
}
});
}
gulp.task('jade', function(){
gulp.src('src/*.jade')
.pipe(jade())
.pipe(gulp.dest('dist'))
});
gulp.task('watch', function() {
gulp.watch('dist/*.html', notifyLiveReload);
gulp.watch('src/*.jade', ['jade']);
});
gulp.task('default', ['livereload', 'express', 'watch', 'jade'], function() {
});
find the example here at GitHub

Resources