Gulp (4.0) throws the error "Error: Invalid glob argument: undefined" when I attempt to gulp.src the path of a changed file obtained from gulp.watch. Both this:
gulp.task('watch', function() {
gulp.watch('./web/**/*.html')
.on('change', function(file) {
gulp.src(file.path)
.pipe(gulp.dest('./output'));
});
});
and this syntax variant:
gulp.task('watch', function() {
gulp.watch('./web/**/*.html', function(file) {
gulp.src(file.path)
.pipe(gulp.dest('./output'));
});
});
yield the same result.
Logging file.path before the gulp.src also outputs "undefined".
To reproduce:
npm install -g gulp#github:gulpjs/gulp#4.0
and create a gulpfile.js containing:
const gulp = require('gulp');
followed by either of the examples.
My understanding is that this is the way in which the changed file's path should be accessible as per the docs, so I'm not sure where I'm going wrong?
That documentation is all kinds of wrong. E.g it talks about gaze events, but gaze is no longer used to watch for file changes in gulp 4.0; it has been replaced by chokidar.
Concerning your problem the docs are wrong about the way you have to access the file path. The .on('change') callback function is not passed an event object, so there is no .path property.
Instead the file path is passed as a string, so your first example should look like this:
gulp.task('watch', function() {
gulp.watch('./web/**/*.html')
.on('change', function(file) {
gulp.src(file)
.pipe(gulp.dest('./output'));
});
});
The callback function in your second example doesn't receive a path at all. It's passed a done callback, in order to facilitate task execution via gulp.series() or gulp.parallel().
Related
I'm using Gulp to compress a zip file and then upload it to AWS Lambda. The upload zip file is done manually. Only the process of compressing is handled by Gulp.
Here is my gulpfile.js
var gulp = require('gulp');
var zip = require('gulp-zip');
var del = require('del');
var install = require('gulp-install');
var runSequence = require('run-sequence');
var awsLambda = require("node-aws-lambda");
gulp.task('clean', function() {
return del(['./dist', './dist.zip']);
});
gulp.task('js', function() {
return gulp.src('index.js')
.pipe(gulp.dest('dist/'));
});
gulp.task('npm', function() {
return gulp.src('./package.json')
.pipe(gulp.dest('dist/'))
.pipe(install({production: true}));
});
gulp.task('zip', function() {
return gulp.src(['dist/**/*', '!dist/package.json'])
.pipe(zip('dist.zip'))
.pipe(gulp.dest('./'));
});
gulp.task('deploy', function(callback) {
return runSequence(
['clean'],
['js', 'npm'],
['zip'],
callback
);
});
After running the deploy task, a zip folder named dist.zip is created consists of a index.js file and a node_modules folder. The node_modules folder contains only a lodash library.
This is index.js
var _ = require('lodash');
console.log('Loading function');
exports.handler = (event, context, callback) => {
//console.log('Received event:', JSON.stringify(event, null, 2));
var b = _.chunk(['a', 'b', 'c', 'd', 'e'], 3);
console.log(b);
callback(null, event.key1); // Echo back the first key value
//callback('Something went wrong');
};
After using AWS lambda console to upload the dist.zip folder. There is an error showing that the lodash library cannot be found
{
"errorMessage": "Cannot find module 'lodash'",
"errorType": "Error",
"stackTrace": [
"Function.Module._load (module.js:276:25)",
"Module.require (module.js:353:17)",
"require (internal/module.js:12:17)",
"Object.<anonymous> (/var/task/index.js:1:71)",
"Module._compile (module.js:409:26)",
"Object.Module._extensions..js (module.js:416:10)",
"Module.load (module.js:343:32)",
"Function.Module._load (module.js:300:12)",
"Module.require (module.js:353:17)"
]
}
But in the zip folder, there is a node_modules directory that contains the lodash lib.
dist.zip
|---node_modules
|--- lodash
|---index.js
When i zip the node_modules directory and the file index.js manually, it works fine.
Does anyone have idea what wrongs ? Maybe when compressing using Gulp, there is a misconfigured for the lib path ?
I had same problem few days back.
Everyone pointed to gulp zip, however it was not problem with gulp zip.
Below worked fine:
gulp
.src(['sourceDir/**'], {nodir: true, dot: true} )
.pipe(zip('target.zip'))
.pipe(gulp.dest('build/'));
That is, note the below, in 2nd param of src, in the above:
{nodir: true, dot: true}
That is, we have to include dot files for the zip (ex: .config, .abc, etc.)
So, include above in .src of gulp, else all others like copy, zip, etc. will be improper.
The package gulp-zip is massively popular (4.3k downloads per day) and there does not seem to be any Gulp substitute. The problem is definitely with relative paths and how gulp-zip processes them. Even when using a base path option in the gulp.src function (example below), gulp-zip finds a way to mess it up.
gulp.task("default", ["build-pre-zip"], function () {
return gulp.src([
"dist/**/*"
], { base: "dist/" })
.pipe(debug())
.pipe(zip("dist.zip"))
.pipe(gulp.dest("./dist/"));
});
Since there is no good Gulp solution as of 1/4/2017 I suggest a work-around. I use Gulp to populate the dist folder first, exactly how I need it with the proper node_modules folder. Then it is time to zip the dist folder properly with relative file paths stored. To do that and also update Lambda, I use a batch file (Windows) of command line options to get the job done. Here is the upload.bat file I created to take the place of the gulp-zip task:
start /wait cmd /c "gulp default"
start /wait cmd /c "C:\Program Files\WinRAR\WinRAR.exe" a -r -ep1 dist\dist.zip dist\*.*
aws lambda update-function-code --zip-file fileb://dist/dist.zip --function-name your-fn-name-here
If you use WinRAR you will find their command line docs here, for WinZip go here. That .bat file assumes you are using the AWS Command Line Interface (CLI) which is a godsend; get it here.
If you are wishing this answer pointed you towards a 100% Gulp solution, to that I say, "You and me both!". Good luck.
I want to put inside gulpfile something like:
require('web-component-tester').gulp.init(gulp);
gulp.task('default', function() {
gulp.watch(['elements/**', 'test/**'], ['test:local']);
});
The purpose is to watch test folders or elements folders (with Polymer components). If some of them will change, run test with each build.
my wct.conf.js:
module.exports = {
root: '.tmp/elements/',
suites: ['**/test/'],
plugins: {
local: {browsers: ['chrome']},
}
};
I found the code above on some page but after I add some tests and then type gulp in my terminal I found error, because .tmp folder is not updated and strange errors like Polymer is not definedor ajax.generateRequest is not a function. I got also right errors when I intentionally made a mistake in a test to fail it, so it looks like something is ok, but not at all.
I add the tests to the existing project with lots of files. When I tried to do the same thing on empty project I also got the same error until I type bower install.
Is there any chance that this is the problem with bower dependencies?
Or have you any idea what is wrong? Is this part of code in gulpfile right to perform the desired effect?
Thanks a lot.
I am not answering your question directly, because its been a while since I've done it that way. But the following defines a sub task from among others to define a task called 'client' which then runs the tests in a frame buffer (so I don't have disturbing windows popping up all over the place when the tests run - they just run and output in a console window. Its effectively spawning a command line version of wct and I don't have a wct.conf file at all.
(function() {
'use strict';
const spawn = require('child_process').spawn;
module.exports = function(gulp) {
gulp.task('test:client',['lint:client'], () => {
var child = spawn('xvfb-run', ['-a', 'wct', '--color'], {cwd: process.cwd()});
child.stdout.setEncoding('utf8');
child.stdout.on('data', function(data) {
process.stdout.write(data);
});
child.stderr.setEncoding('utf8');
child.stderr.on('data', function(data) {
process.stderr.write(data);
});
});
gulp.task('client',function() {
gulp.watch([
'app/index.html',
'app/src/*.html',
'app/test/*.html',
'aoo/mocks/*.html',
'gulpfile.js',
'tasks/*.js'
],['test:client']);
});
};
})();
This file is one file within the tasks directory (which as you can see I am watching)
My gulpfile loads this, and other tasks like so (I copied this from the angular.js team who used it to load some of there tasks supporting angular)
(function() {
'use strict';
require('dotenv').config(); //load our environment
var gulp = require('gulp');
var includeAll = require('include-all');
/**
* Loads task modules from a relative path.
*/
function loadTasks(relPath) {
return includeAll({
dirname: require('path').resolve(__dirname, relPath),
filter: /(.+)\.js$/
}) || {};
}
// *
// * Invokes the function from a Gulp configuration module with
// * a single argument - the `gulp` object.
function addTasks(tasks) {
for (var taskName in tasks) {
if (tasks.hasOwnProperty(taskName)) {
tasks[taskName](gulp);
}
}
}
/**
* Add all Gulp tasks to the gulpfile.
* Tasks are in `tasks/`
*/
addTasks(loadTasks('tasks/'));
// require('gulp-load-tasks')(__dirname + '/tasks');
gulp.task('default', ['lint:gulp','client','server']);
})();
I'm new to Gulp and I found a Gulpfile.js example I wanted to use to livereload my express app's server whenever a change takes place in either my app.js file or ./public directory. Here is the Gulpfile.js code:
var gulp = require('gulp'),
spawn = require('child_process').spawn,
node;
/**
* $ gulp server
* description: Launch the server. If there's a server already running, kill it.
*/
gulp.task('server', function() {
if (node) node.kill()
node = spawn('node', ['app.js'], {stdio: 'inherit'})
node.on('close', function (code) {
if (code === 8) {
gulp.log('Error detected, waiting for changes...');
}
});
})
/**
* $ gulp default
* description: Start the development environment
*/
gulp.task('default', function() {
gulp.run('server')
gulp.watch(['./app.js', './public/'], function() {
gulp.run('server')
})
})
// clean up if an error goes unhandled.
process.on('exit', function() {
if (node) node.kill()
})
In my terminal window I keep getting the following warning:
gulp.run() has been deprecated. Use task dependencies or gulp.watch task triggering instead.
Gulp is working and it is livereloading the web application like I want it to but I'd like to fix this issue to future proof my development process, as well as get rid of this annoying warning message.
Thanks for the help!
One option would be to simply replace all occurrences of gulp.run() with gulp.start():
gulp.task('default', function() {
gulp.start('server');
gulp.watch(['./app.js', './public/'], function() {
gulp.start('server');
});
});
However calling a task explicitly using gulp.start() is not the idiomatic way of doing things in gulp (although sometimes it's necessary).
The warning message you receive already hints at the idiomatic way of solving this:
Use task dependencies or gulp.watch task triggering
Task dependencies allow you to run a task before another task. That means you can get rid of the first gulp.run().
Task triggering in gulp.watch() allows you to run a task when a file changes. That means you can get rid of the second gulp.run().
Therefore your default task ends up looking like this:
gulp.task('default', ['server'], function() {
gulp.watch(['./app.js', './public/'], ['server']);
});
I'm new to using gulp and I think I have it setup correctly, but it does not seem to be doing what it should be doing.
My gulpfile.js has
gulp.task('compass', function() {
return gulp.src('sites/default/themes/lsl_theme/sass/**/*.scss')
.pipe(compass({
config_file: 'sites/default/themes/lsl_theme/config.rb',
css: 'css',
sass: 'scss'
}))
.pipe(gulp.dest('./sites/default/themes/lsl_theme/css'))
.pipe(notify({
message: 'Compass task complete.'
}))
.pipe(livereload());
});
with
gulp.task('scripts', function() {
return gulp.src([
'sites/default/themes/lsl_theme/js/**/*.js'
])
.pipe(plumber())
.pipe(concat('lsl.js'))
.pipe(gulp.dest('sites/default/themes/lsl_theme/js'))
// .pipe(stripDebug())
.pipe(uglify('lsl.js'))
.pipe(rename('lsl.min.js'))
.pipe(gulp.dest('sites/default/themes/lsl_theme/js'))
.pipe(sourcemaps.write())
.pipe(notify({
message: 'Scripts task complete.'
}))
.pipe(filesize())
.pipe(livereload());
});
and the watch function
gulp.task('watch', function() {
livereload.listen();
gulp.watch('./sites/default/themes/lsl_theme/js/**/*.js', ['scripts']);
gulp.watch('./sites/default/themes/lsl_theme/sass/**/*.scss', ['compass']);
});
when I run gulp, the result is
[16:14:36] Starting 'compass'...
[16:14:36] Starting 'scripts'...
[16:14:36] Starting 'watch'...
[16:14:37] Finished 'watch' after 89 ms
and no changes are registered.
for file structure, my gulpfile.js is in the root directory and the sass, css, and js are all in root/sites/default/themes/lsl_theme with the sass folder containing the folder 'components' full of partials.
My assumption is that you are on windows? Correct me if I'm wrong.
There is this problem that gulp-notify tends to break the gulp.watch functions. Try commenting out
// .pipe(notify({
// message: 'Scripts task complete.'
// }))
and see if the problem still exists.
If that does fix the issue, a solution from this thread may be helpful.
You can use the gulp-if
plugin in combination with
the os node module
to determine if you are on Windows, then exclude gulp-notify, like
so:
var _if = require('gulp-if');
//...
// From https://stackoverflow.com/questions/8683895/variable-to-detect-operating-system-in-node-scripts
var isWindows = /^win/.test(require('os').platform());
//...
// use like so:
.pipe(_if(!isWindows, notify('Coffeescript compile successful')))
It turns out that a large part of my issue was just simply being a rookie with Gulp. When I removed 'scripts' from my gulp watch it started working.
I then made the connection that it was watching the same directory that it was placing the new concatenated and minified js files in so it was putting the new file, checking that file, and looping over and over causing memory issues as well as not allowing 'compass' to run.
After creating a 'dest' folder to hold the new js everything started working just peachy.
I need to apply a build task for specific files. For finding them, I use the typical template. But I can't understood how to pass the arguments (file path) from gulp.src.
Desirable solution.
gulp.task('bundles', function() {
gulp.src('bundles/**/*.js').
pipe(gulp.start('build', file.path));
});
gulp.task('build', function (path) {
// use here
});
Question is a bit stale and I am not sure I totally understand what you're trying to achieve here, but I think what you're looking for is lazypipe
You might want to clarify your question if that's not what you're looking for
Example Usage:
var lazypipe = require('lazypipe'),
g = require('gulp-load-plugins')({lazy: true}),
jsTransformPipe = lazypipe()
.pipe(g.jshint) // <-- Notice the notation: g.jshint, not g.jshint()
.pipe(g.concat, 'bundle.js'), // <-- Notice how the param is passed to g.concat, as a second param to .pipe()
jsSourcePipe = lazypipe()
.pipe(gulp.src, './**/*.js');
gulp.task('bundle', function() {
jsSourcePipe()
.pipe(jsTransformPipe()) // <-- You execute the lazypipe by calling it as a function
.pipe(gulp.dest('../build/');
});
With lazypipe you basically create a pipe for future use; hope this help
(Can't comment because of rep, sorry)
I assume that your sample code isn't filled with everything, but why don't you merge those tasks and use your gulp.src() in your build task instead of calling another task.
Maybe it's useful for you but with what you're showing I can't find an explanation for why you do this instead of simply going with something like :
gulp.task('build', function (path) {
gulp.src('bundles/**/*.js)
//Your code for this task
});
Of course, it removes the bundles task, but it's not useful as is.
Don't hesitate to comment if I'm wrong and I'll try to help you as much as I can.
First off, gulp.task('build', function (path) won't ever work. The only valid argument for gulp tasks is a callback to signal asynchronous task completion. If you tried to do run the above, gulp would expect path to be a function and the task would never complete unless that function was called. In this example, the 'build' task should be a regular function called from the 'bundles' pipe, not a task.
The better question would be: How do I run a custom function inside a gulp pipe? Plugins like gulp-tap might get you close, but it's not difficult to create what is essentially an inline gulp plugin to call your function.
Gulp pipes receive a through2 object stream containing a vinyl file object, an encoding and a callback. Here's a basic skeleton for calling any arbitrary function against the files in a gulp pipe:
var gulp = require('gulp');
var through = require('through2');
gulp.task('stack', function() {
return gulp.src('./src/*.js')
.pipe(through.obj(function(file, enc, cb) {
// file.path is the full path to the file
myBuildFunction(file.path);
cb(null, file);
}))
.pipe(gulp.dest('./build/'));
})
This can be incredibly powerful. To modify the file's contents, just change the file.contents buffer. To rename or relocate the file, change file.path. Everything can be done in gulp's native pipes.